Need some help with your project? Contact me

Theming the Comment block in Drupal 7

Ever wondered how you can modify the way the default Comment block outputs the list of comments? In this article I’m going to show you how to override theme_comment_block() in order allow you to display these comments however you want.

If you look into comment.module (look but don't touch), you’ll notice that the Comment block content is given by the theme_comment_block() function:

function comment_block_view($delta = '') {
  if (user_access('access comments')) {
    $block['subject'] = t('Recent comments');
    $block['content'] = theme('comment_block');
    return $block;
  }
}

So this is what you need to override. To do that, like usual go ahead and copy the original from its API page:

function theme_comment_block() {
  $items = array();
  $number = variable_get('comment_block_count', 10);
  foreach (comment_get_recent($number) as $comment) {
    $items[] = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)) . '&nbsp;<span>' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->changed))) . '</span>';
  }
  if ($items) {
    return theme('item_list', array('items' => $items));
  }
  else {
    return t('No comments available.');
  }
}

...and then make the modifications you want. Don’t forget to change theme in the function name with the name of your module or theme. As an example below, I will override this function in my demo theme in order to add an html entity (») before each comment subject:

function demo_comment_block() {
  $items = array();
  $number = variable_get('comment_block_count', 10);
  foreach (comment_get_recent($number) as $comment) {
    $items[] = l('&raquo; ' . $comment->subject, 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid, 'html' => true)) . '&nbsp;<span><em>' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->changed))) . '</em></span>';
  }
  if ($items) {
    return theme('item_list', array('items' => $items));
  }
  else {
    return t('No comments available.');
  }
}

So let’s break this theme function down a bit. As you can see, it first retrieves the n recent comments on the site (n being the number you set in the block configuration form). Then, iterating through that array of comments, another array ($items) is filled with the comment subjects passed through the l() function plus the comment's timestamp. If you don’t know the l() function construct, check it out on its API page, it is very cool and useful.

Now, I did 2 things for my purpose. I added my html entity right before the comment subject and passed to the l() function the html attribute setting it to TRUE. This makes sure my html entity is parsed as html and not plain text (more information on this in the l() function documentation).

And that is pretty much it. I mean, you can do a lot more than this. I just gave you a short example. For questions or clarifications, just drop a comment below.

Comments

If you want this to be easier in D8, please help out by reviewing the Twig conversion at http://drupal.org/node/1898054 :)

I need to learn a bit about this :)

I thought the Twig initiative has been abandoned? At least, that was what an article on Drupal Planet indicated a couple months back. So is Twig 100% certainty for D8. Thanks.

Twig hasn't been abandoned but there are a ton of patches that need reviewing at http://drupal.org/node/1757550

Ah! Great to know. Thanks!

Is there some nice drupal/twig theming tutorial (for both creating and porting themes?

Thanks for the tutorial. It would be great if you could expand it to demonstrate how to add CSS classes to form elements! Cheers kevin

Let me know what you mean exactly and I'll take a look into it ;)

Hi Danny,

Thanks for the quick reply. Unfortunately, there are not many great looking Drupal templates so it is often necessary to convert an HTML template to Drupal. Most of the aspects of doing so are pretty easy. The part that I always get stuck on is theming Drupal's standard forms (e.g., login, search, comments, contact). I usually get around this with some preprocess hacks and css hacks. But i am not very happy with it as I don't feel like it is the "right" way. i guess i am a perfectionist... ;o) that is why i was excited to read your post. While, insightful, it still did not help me with mastering form CSS.

Below I have pasted a comment form from one html template I am currently converting. If you look look at the form below you will see classes embedded in the form for wrappers and input types. Using your example, how do we elegantly apply the classes for fields below to override default Drupal comments form?

    Name (required)


    Email (required)


    Website



    Your Message (required)

Thanks again for the great blog and Drupal insight. Cheers Kevin

I see all of the code i copied got wiped out.

Yes it did because of the Filter HTML text format. But I can still access the code and I will take a look.

My question to you is this though: Are you implementing these forms using the Form API or what you are trying to do is change the way let's say the comment form looks like (markup and css classes) ?

D

Most of the templates set the button colour is black.

May I ask how can I change the colour of the buttons (both mouse over and out) in a Drupal template.

Thank you very much.

Thanks for sharing useful information about Drupal theme. It is a specialized package that makes things easier for people starting out or wanting to deploy a blog section quickly on the website.

Add new comment

You must have Javascript enabled to use this form.