Alphabetizing Group Directories in Buddypress

Buddypress is awesome. It is really pretty amazing. But it is far from perfect. Some things are really difficult to modify unless they’ve been expressly designed to be changed. One of those things is the issue with the sorting of group directories.

I’ve built a site where members are given access to follow a group of professionals. I use Buddypress Follow, and it works pretty well. One problem, when the members come with the intent to sign up and follow a specific professional, the group members directory is not alphabetized. By default it is sorted by sign up date (I think?), which is pretty much the last sorting method you’d want to use if you are trying to look up a specific person by name. I’ve spent the past six or seven months off and on trying to find some nice way to rectify this without any luck. A lot of people seemed to be looking for a method, but nobody was finding it. So I figured this one out on my own.

Right now, I have a custom activity loop showing only activity done by the professional members of the site, and it is the default home page for all members. This page had to be set up to look up member ID numbers, which I look up directly in the MySQL database like so:

  1. Log into phpMyAdmin through your hosting provider
  2. Find your WordPress database, possibly something like “******_wrdp1” and open it
  3. Scroll all the way down the directory listed along the left hand side and click on what is usually the last entry, “wp_users”
  4. A list will appear that shows all of the stored user credentials, including the user “ID”. You will need to navigate through this list, sorting it by login key or user login name, and find the user IDs of the users you want added to your directory. The numbers need to be copied exactly and saved for later

Now this process is annoying, but I couldn’t think of an elegant alternative. the numbers you just copied are going to be used for the new template we are going to make to let you alphabetize your group directory in Buddypress.

Return to WordPress and log in. If you are using multisite, make sure you are logged in as a Superuser.

I’m assuming you at least know how to get around the menus. Go to the Theme Editor and find a “Directory Members Page” template. You may need to make one yourself, depending on the theme you have installed. It is pretty easy, so don’t worry if you can’t find one. Upload a file and just paste something like this into it:

http://codex.buddypress.org/developer/developer-docs/loops-reference/the-members-loop/

 

If you aren’t sure how, here is how I start my default Member Directory template:

<?php /* Template Name: Template Directory Custom */ ?> <?php get_header( 'buddypress' ); ?> <?php do_action( 'bp_before_directory_members_page' ); ?> <div id="content"> <div> <?php do_action( 'bp_before_directory_members' ); ?>

 

Here is the code from the Buddypress Codex that actually does something:

<?php if( bp_has_members( bp_ajax_querystring( 'members') ) ) : ?> <div id="pag-top"class="pagination"> <div class="pag-count"id="member-dir-count-top"> <?php bp_members_pagination_count(); ?> </div> <div class="pagination-links"id="member-dir-pag-top"> <?php bp_members_pagination_links(); ?> </div> </div> <?php do_action( 'bp_before_directory_members_list'); ?> <ul id="members-list"class="item-list"role="main"> <?php while( bp_members() ) : bp_the_member(); ?> <li> <div class="item-avatar"> <a href="<?php bp_member_permalink(); ?>"><?php bp_member_avatar(); ?></a> </div> <div class="item"> <div class="item-title"> <a href="<?php bp_member_permalink(); ?>"><?php bp_member_name(); ?></a> <?php if( bp_get_member_latest_update() ) : ?> <span class="update"> <?php bp_member_latest_update(); ?></span> <?php endif; ?> </div> <div class="item-meta"><span class="activity"><?php bp_member_last_active(); ?></span></div> <?php do_action( 'bp_directory_members_item'); ?> <?php /*** * If you want to show specific profile fields here you can, * but it'll add an extra query for each member in the loop * (only one regardless of the number of fields you show): * * bp_member_profile_data( 'field=the field name' ); */ ?> </div> <div class="action"> <?php do_action( 'bp_directory_members_actions'); ?> </div> <div class="clear"></div> </li> <?php endwhile; ?> </ul> <?php do_action( 'bp_after_directory_members_list'); ?> <?php bp_member_hidden_fields(); ?> <div id="pag-bottom"class="pagination"> <div class="pag-count"id="member-dir-count-bottom"> <?php bp_members_pagination_count(); ?> </div> <div class="pagination-links"id="member-dir-pag-bottom"> <?php bp_members_pagination_links(); ?> </div> </div> <?php else: ?> <div id="message"class="info"> <p><?php _e( "Sorry, no members were found.", 'buddypress'); ?></p> </div> <?php endif; ?>
Finally, this is how I end my Member Directory template:
        <?php do_action( 'bp_after_directory_members' ); ?> </div><!-- .padder --> </div><!-- #content --> <?php do_action( 'bp_after_directory_members_page' ); ?> <?php get_sidebar( 'buddypress' ); ?> <?php get_footer( 'buddypress' ); ?>

Now we get to the customizing part. This step is listed in the Buddypress Codex, and you’ll find plenty of tutorials on it, but some of them are a little vague. Here’s my step by step. Remember those numbers you recorded from your WordPress MySQL database? We put those in where it says<?php if( bp_has_members( bp_ajax_querystring( 'members') ) ) : ?>

so it looks like this:

<?php if (bp_has_members(bp_ajax_querystring('members').'&include=3,4,6,5,7,8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,28,29,57,73,66,45,38,99,71, 72,54,95,36,93,76,68,103,60,24,25,34,26,39,27,55,30,78,31,50,32,37, 33,67,35,59,40,41,91,42,43,44,46,47,48,49,51,53,56,58,61,62,63,64,65, 69,70,74,75,77,79,80,81,82,83,84,85,86,87,88,89,90,92,94,96,97,98, 100,101,102,104,105,110,52,118,121,123,126,130,131,137,144,145,146, 188,226,293,295,381,383,433,445,532,570,571,579,607,648,731,742, 747,748,751,757,829,841,845,850,1077,1126,1247,1312,1325,1328, 1402,1592,1624,1625,1790,1814,1894,1915,2339,2342,2351,2365,2439, 2501,2511,2512,2516,2523,2527'

NOTICE THAT THERE ARE NO SPACES IN THERE! If you put spaces in, you’re going to have a bad time. So don’t. Step by step, what we did was put a period after the querystring, then enclose the next section in single quotes, then an ampersand, then the “include” parameter, followed by the user IDs that are included in this list. We use an ampersand to combine parameters and a comma to separate the values. This is basic stuff to a lot of people, but if you are just staring out, maybe you don’t know this.

Next, we have to make sure these profiles are all pulled at once. We can’t alphabetize them unless we pull them all at once. If you know how to split it up into pages again, let me know. As far as I can tell, there is no simple way to do it. So here is the next simple step. Just add this parameter just before the include parameter: “&per_page=9000”

Now this section of our template looks like this:

<?php if (bp_has_members(bp_ajax_querystring('members'). '&per_page=9000&include=3,4,6,5,7,8,9,10,11,12,13,14,15,16,17, 18,19,20,21,22,23,28,29,57,73,66,45,38,99,71,72,54,95,36,93,76, 68,103,60,24,25,34,26,39,27,55,30,78,31,50,32,37,33,67,35,59, 40,41,91,42,43,44,46,47,48,49,51,53,56,58,61,62,63,64,65,69,70, 74,75,77,79,80,81,82,83,84,85,86,87,88,89,90,92,94,96,97,98, 100,101,102,104,105,110,52,118,121,123,126,130,131,137,144, 145,146,188,226,293,295,381,383,433,445,532,570,571,579,607, 648,731,742,747,748,751,757,829,841,845,850,1077,1126, 1247,1312,1325,1328,1402,1592,1624,1625,1790,1814,1894,1915, 2339,2342,2351,2365,2439,2501,2511,2512,2516,2523,2527'

And… we’re done with that little chunk. I know the codex says there is an alphabetization parameter, but it doesn’t work on groups. Sorry. You will have to keep reading if you want to alphabetize.

This step is the part that made me sweat a little. I couldn’t find much on it. You’ll have to create an array. It is not too hard if you know how, but if you don’t, it is pretty difficult. I have taken classes on coding, but nothing in php or ajax, so it took a couple of hours for me to get this thing working how I wanted it.

What we need to do is edit the actual chunk that displays member data, which is found just after the line “<?php do_action( 'bp_before_directory_members_list' );“. You can delete everything between that and “<?php do_action( 'bp_after_directory_members_list' ); ?>“. We are going to recreate it.

Starting with <?php do_action( 'bp_before_directory_members_list' ); , we add an array using this line:

$directory_members_array = array();//insert array ?>

Next we replace this line. It was here before, and it is one of the few pieces that we’ll keep:

<?php while ( bp_members() ) : bp_the_member(); ?>

Next! Now we are going to pull in the user name, explode it, then do a few tests to make sure we have a first name and a last name to use in our sorting:

<?php $nom = explode(” “, bp_get_member_name());//dissect member name
if ($nom[1]==””) { $nom[1] = $nom[0];}//if one name provided, return as last name for sorting
$count = 0;//reset counter
while ($nom[$count + 1]!=””) { $nom[1] = $nom[$count + 1];//if middle name(s) are provided, discard them and save the final name as last, exit loop when name is null
$count++;}//increment counter of input names

Now let’s get this array put together:

array_push($directory_members_array, array( “link” => bp_get_member_permalink(), “full” => bp_get_member_name(), “icon” => bp_get_member_avatar(), “first” => $nom[0], “last” => $nom[1] ) );//populate the member list array ?>

And we can end the while loop we started earlier:

<?php endwhile; ?>

Now we can sort! Finally. This piece goes through our array and gives it values, then sorts it.

<?php foreach($directory_members_array as $key => $value) { $atoz[$key] = $value[“last”]; $printed = $value[“full”] ; }
array_multisort($atoz, SORT_ASC, $directory_members_array);//alphabetize the array by last name?>

Now here is where you might need to start paying attention because your theme might have a different format. You can echo html and css calls within the php function to keep your formatting. Take a close look and see how I did mine, then tweak it so it looks best for you.

<?php
echo “<ul id=’member-list’ class=’item-list’>”;
foreach($directory_members_array as $key){
echo “<li><table><tbody><tr><td>”;
echo “<a href=”.$key[‘link’].”>”;
echo $key[‘icon’].”</a>”;
echo “<h5> <a href=”.$key[‘link’].”>”;
echo $key[‘full’].”</a> </h5>”;
echo “</td></tr></tbody></table></li>”;
;}?>
<?php echo “</ul>” ?>

And we are pretty much done! Whew! This isn’t a perfect solution, and you should probably put a version of this in your functions file instead of right inside your template, but it works. As far as I know, it is the only thing that does work at this point. Adding something like this by default has been proposed, but the BP team keeps shuffling it around while they work on more important features. It doesn’t look like it is going to be added any time soon.

Here is the code I have in my template from beginning to end (thought not very nicely formatted, sorry):

<?php /* Template Name: Member List Alpha */ ?> <?php get_header( 'buddypress' ); ?>     <?php do_action( 'bp_before_directory_members_page' ); ?>     <div id="content">         <div>         <?php do_action( 'bp_before_directory_members' ); ?> <?php if ( bp_has_members( bp_ajax_querystring('members' ).'&per_page=900&include=3,4,6,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, 28,29,57,73,66,45,38,99,71,72,54,95,36,93,76,68,103,60,24,25, 34,26,39,27,55,30,78,31,50,32,37,33,67,35,59,40,41,91,42,43,44, 46,47,48,49,51,53,56,58,61,62,63,64,65,69,70,74,75,77,79,80,81, 82,83,84,85,86,87,88,89,90,92,94,96,97,98,100,101,102,104,105, 110,52,118,121,123,126,130,131,137,144,145,146,188,226,293,295, 381,383,433,445,532,570,571,579,607,648,731,742,747,748,751, 757,829,841,845,850,1077,1126,1247,1312,1325,1328,1402,1592, 1624,1625,1790,1814,1894,1915,2339,2342,2351,2365,2439,2501, 2511,2512,2516,2523,2527') ) : ?>       <div id="pag-top">           <div id="member-dir-count-top">               <?php bp_members_pagination_count(); ?>           </div>           <div id="member-dir-pag-top">               <?php bp_members_pagination_links(); ?>           </div>       </div>       <?php do_action( 'bp_before_directory_members_list' );  $directory_members_array = array();//insert array?>       <?php while ( bp_members() ) : bp_the_member(); ?> <?php $nom = explode(" ", bp_get_member_name());//dissect member name if ($nom[1]=="") { $nom[1] = $nom[0];}//if one name provided, return as last name for sorting     $count = 0;//reset counter     while ($nom[$count + 1]!="") { $nom[1] = $nom[$count + 1];//if middle name(s) are provided, discard them and save the final name as last, exit loop when name is null         $count++;}//increment counter of input names array_push($directory_members_array, array( "link" => bp_get_member_permalink(), "full" => bp_get_member_name(), "icon" => bp_get_member_avatar(), "first" => $nom[0], "last" => $nom[1] ) );//populate the member list array ?> <?php endwhile; ?> <?php foreach($directory_members_array as $key => $value) { $atoz[$key] = $value["last"]; $printed = $value["full"] ; } array_multisort($atoz, SORT_ASC, $directory_members_array);//alphabetize the array by last name?> <?php echo "<ul id='member-list' class='item-list'>"; foreach($directory_members_array as $key){         echo "<li><table><tbody><tr><td>";             echo "<a href=".$key['link'].">";             echo $key['icon']."</a>";             echo "<h5> <a href=".$key['link'].">";             echo $key['full']."</a> </h5>";             echo "</td></tr></tbody></table></li>"; ;}?> <?php echo "</ul>" ?>       <?php do_action( 'bp_after_directory_members_list' ); ?>       <?php bp_member_hidden_fields(); ?>       <div id="pag-bottom">           <div id="member-dir-count-bottom">               <?php bp_members_pagination_count(); ?>           </div>           <div id="member-dir-pag-bottom">               <?php bp_members_pagination_links(); ?>           </div>       </div>   <?php endif; ?>         <?php do_action( 'bp_after_directory_members' ); ?>         </div><!-- .padder -->     </div><!-- #content -->     <?php do_action( 'bp_after_directory_members_page' ); ?> <?php get_sidebar( 'buddypress' ); ?> <?php get_footer( 'buddypress' ); ?>

 

And that is it. Leave comments if you have any.

Leave a Reply