Building a top contributor list in WordPress

You might be running a site or building a site for a customer where multiple people are contributing to the content. Then there come the time where you need to build a top contributor list of the WordPress site users. I have been looking for plugins to do this, however I didn’t found anything satisfying or the one I tried were not very good for large list of user. So I have decided to poke around the web and combine some code with my own ideas.

Thus, In this example we will simple build a list that order the user by the number of articles published and then by the user name.

First of all, you need to create a new template file which you will use in the admin to create the WordPress page that will show the list.

Now in this template after the loop, let’s do our custom SQL query to get the list of users:

$query = "SELECT u.ID, u.display_name, count(*) as cnt FROM $wpdb->posts p, $wpdb->users u WHERE p.post_parent = 0 AND  p.post_status = 'publish' AND p.post_author = u.ID GROUP BY u.user_login ORDER BY cnt DESC, u.display_name ASC";

Basically this Query is doing what we need, it gets the ID, display name of the users and order them by the number of post (count(*)) they have published. Here we are using count(*) to calculate the number of occurrence the user is appearing for a publishes post and we are grouping the result by user login name. We use an aliases (cnt) because some server can be tricky and not like count(*) term when you do the Order. Let’s run the query:

$UsersID = $wpdb->get_results( $query );

Now we are ready to enter our loop to display the results:

$counter = 0;
$siteurl = get_bloginfo('template_url');
foreach ( $UsersID as $iUserID ) :

   $user = get_userdata( $iUserID->ID );
   $numpost = get_usernumposts($iUserID->ID);

   if ($user->user_level < 3){

      $counter++;
      $membersince = date('M dS Y',strtotime($user->user_registered));

      if ($counter == 2){
         $counter =0;
         echo '<div class="user-block last">';
      }else{
         echo '<div class="user-block">';
      }

      echo '<a href="'.get_author_posts_url($iUserID->ID).'">'.get_avatar( $user->user_email, '60', $default=$siteurl.'/images/gravatar.jpg' ).'</a>';

      echo '<h2><a href="'.get_author_posts_url($iUserID->ID).'">'. $user->display_name .'</a></h2>

      <p>Articles published: <strong>'.$numpost.'</strong></p>
      <p>Member since: <strong>'.$membersince.'</strong></p>

      </div>';
   }

endforeach;

With this loop we are displaying the user avatar, name, number of post and membership history. The name and avatar are linking to the author archive page with all the articles form this user. We are using a counter to add a class to our user block in order to remove the margin on the right side (2 column design).

Obviously, this could be optimize:

  • The query could have been part of a function, so we don’t have the sql query showing up in the template page.
  • We could have got the user meta directly from the query instead of calling get_userdata in the FOR loop.

And could be improve with ideas to make this code evolved:

  • Paging the result, if you have more than 50 users, it will be great to page the results.
  • Install a post rating plugin and get the top contributor order by rating.

Please don’t hesitate to leave a comment if you have other suggestion to optimize the code.

3 Responses

07.20.10

I couldn’t get this to work for some reason…

07.20.10

Could show me the page you have built?

11.29.11

Thank you so much for this SQL snippet! It really helped me get my head around querying multiple tables. I’m using it for a Top Authors box on the front-end of one of my sites. Works a treat!

Leave Your Response

* Name, Email, Comment are Required