In: , ,
On: 2009 / 11 / 16
Shorter URL for this post: http://ozh.in/ro

I've recently moved to WordPress an active community site which is run and moderated by several editors and administrators. Each post gets dozens of comments, and I wanted to highlight those made by staff members.

What not to do

If you've googled a bit for a solution on how to identify authors' or admins' comments, you've probably seen several explanations on how to implement this by comparing emails. Something like:

  1. <?php
  2. if( $comment->comment_author_email == 'admin@blog.com' ) {
  3.     $class = 'admin';
  4. }
  5. ?>

While this is sort of OK for a single author weblog, it's totally inconvenient and not scalable for a community site run by several editors and administrators: you would need to edit the template file whenever there's a new member in the staff, and nothing prevents an unlogged user from commenting using your well known email address.

So, what to do instead?

First, collect all users and their role

WordPress function get_users_of_blog() returns an array of all users with their user_id and role. We're going to loop through all users and collect their id's and roles in an array.

  1. $users = get_users_of_blog();
  2. foreach( $users as $user ) {
  3.     $role = array_pop( array_keys( unserialize($user->meta_value) ) ); // yeah, I know, looks awkward :)
  4.     $user_id = $user->user_id;
  5.     if ( $role != 'subscriber' ) // collect id of anyone whose role is greater than 'subscriber'
  6.         $roles[ $user_id ] = $role;
  7. }

At this point, the array $roles is populated with something like:

  1. $roles = array (
  2.     '1' => 'administrator',
  3.     '2' => 'editor',
  4.     '3' => 'editor',
  5.     '4' => 'administrator',
  6.     '5' => 'author',
  7. );

Now identify for each comment the commenter's role

Typically, your theme has a file named comments.php with a loop that looks like this:

  1. <ol id="commentlist">
  2. <?php foreach ($comments as $comment) : ?>
  3.     <li>
  4.     <p>By <?php comment_author_link() ?> - <?php comment_date() ?></p>
  5.     <?php comment_text() ?>
  6.     </li>
  7. <?php endforeach; ?>
  8. </ol>

WordPress fetches every comment as an object containing, among others, the following informations:

  1. stdClass Object (
  2.     [comment_author] => Joe
  3.     [comment_author_email] => joe@email.com
  4.     [comment_author_url] => http://joe.com/
  5.     [comment_author_IP] => 100.101.102.103
  6.     [user_id] => 4
  7. )

If the user is logged in, $comment->user_id is an integer greater than 0. If the user is not logged in (assuming non logged users can comment), $comment->user_id is zero.

A trivial way to get an user's role would be to issue a call to get_userdata( $user_id ) within the comment loop but that would add an extra query per logged in user, which is an unnecessary burden if you an active community of commenters and a lot of registered users.

Instead we'll simply compare each user_id with what we've collected at the beginning. The comment loop would be something like:

  1. <ol id="commentlist">
  2. <?php foreach ($comments as $comment) : ?>
  3.     <?php // The extra stuff to get commenter's role
  4.     $user_id = $comment->user_id;
  5.     $role = ( isset( $roles[$user_id] ) ? $roles[$user_id] : '' );
  6.     ?>
  7.     <li class="<?php echo $role; ?>">
  8.     <p>By <?php comment_author_link() ?> - <?php comment_date() ?></p>
  9.     <?php comment_text() ?>
  10.     </li>
  11. <?php endforeach; ?>
  12. </ol>

Now, identifying staff comments is just a matter of CSS:

  1. #commentlist li { border:2px solid white; } /* not logged or subscriber */
  2. #commentlist li.administrator { border:2px solid red } /* blog admin */
  3. #commentlist li.editor { border:2px solid blue } /* editor */

All in all

All in all, this very simple method only adds one extra query to the whole page (issued by get_users_of_blog()). You could even easily get rid of that extra query with caching in a flat .php file the array produced by get_users_of_blog() and refresh it with hooking into 'set_user_role' (see wp-includes/capabilities.php)

Shorter URL

Want to share or tweet this post? Please use this short URL: http://ozh.in/ro

Metastuff

This entry "How To Style Editor (Or Any Role) Comments in WordPress" was posted on 16/11/2009 at 10:24 pm and is tagged with , ,
Watch this discussion : Comments RSS 2.0.

15 Blablas

  1. saad says:

    Thanks Ozh.It really helped me.

  2. scribu says:

    What happens if you want to use threaded comments? :P

    Better wrap it up in a plugin, if there isn't one already.

    My .02 $.

  3. scribu says:

    Oh, and what the hell? I'm not in Sweden now! LOL.

  4. I like the way you used the cache method here. Good job!

  5. Ozh says:

    scribu » I don't think threaded comments would change anything

  6. scribu says:

    Yes it would, since you have to use wp_list_comments(), instead of a loop.

    But I guess you could apply the same principle to the callback method.

  7. Simon says:

    Hey Ozh that's exactly what I was looking for. I'm not sure I understand though:

    $users = get_users_of_blog(); does this have to be included as a function or something or will it work "out of the box" just as you described at the end of the post?

  8. Ozh says:

    Simon: just inline in comments.php is fine

  9. Simon says:

    Thanks Ozh. It should work sitewide right, not only in comments, or am I still not getting something here?

    I tried to add it somewhere else for an avatar class outside the comments loop. And it just give a blank output like this class=" ".

    Have a great weekend

  10. Ozh says:

    Simon » it will work anywhere. Paste your code snippet somewhere and I'll have a look

  11. Simon says:

    Merci beaucoup Ozh. Just for argument's sake, let's say I wanted to make the BuddyPress avatars show their role as a class, so I could style them.
    I get an empty output. It's probably because I don't really get it ;)

  12. I'm unsure of the scalability of getting and looping over ALL the users of the blog just to get a list of available roles. Could the code instead use the $wp_roles global?

    1. global $wp_roles;
    2.     $all_roles = $wp_roles-&gt;roles;

    Sensible?

    S

  13. Ozh says:

    Simon Wheatley » I'm not getting a list of available roles. I'm getting a list of *users* and their roles.

  14. fico says:

    great.. nice info.. i was looking for this tutorial and found here..

    thanks dude

  15. Steve says:

    Hello Ozh, thanks for the source code, it is what i'm looking for, an old source code that very important, thanks for your post Ozh.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Gravatars: Curious about the little images next to each commenter's name ? Go to Gravatar and sign for a free account
Spam: Various spam plugins may be activated. I'll put pins in a Voodoo doll if you spam me.

Read more ?