Dissection of a WordPress theme: Part 4

Comments

Comments are an important part of any blog and they are one of the genres defining factors. They allow anyone to give feedback on a post, and allow different websites and users to be participate together as a community.

Our theme will only display comments for a single post, and we have discovered that the responsibility for this has been handed to the comments.php file. If we look at this we find a big chunk of PHP and HTML:

<?php // Do not delete these lines
 if ('comments.php' == basename($_SERVER['SCRIPT_FILENAME']))
   die ('Please do not load this page directly. Thanks!');

 if (!empty($post->post_password)) { // if there's a password
   if ($_COOKIE['wp-postpass_' . COOKIEHASH] != $post->post_password) {  // and it doesn't match the cookie
  ?>
  <p class="nocomments"><?php _e("This post is password protected. Enter the password to view comments."); ?><p>

 <?php
 return;
     }
 }

 /* This variable is for alternating comment background */
 $oddcomment = 'alt';
?>

<!-- You can start editing here. -->

<?php if ($comments) : ?>
  <h3 id="comments"><?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;<?php the_title(); ?>&#8221;</h3>

  <ol class="commentlist">
  <?php foreach ($comments as $comment) : ?>
    <li class="<?php echo $oddcomment; ?>" id="comment-<?php comment_ID() ?>">
      <cite><?php comment_author_link() ?></cite> Says:

      <?php if ($comment->comment_approved == '0') : ?>
      <em>Your comment is awaiting moderation.</em>
      <?php endif; ?>
      <br />

      <small class="commentmetadata"><a href="#comment-<?php comment_ID() ?>" title=""><?php comment_date('F jS, Y') ?> at <?php comment_time() ?></a> <?php edit_comment_link('e','',''); ?></small>
      <?php comment_text() ?>
    </li>

  <?php /* Changes every other comment to a different class */ 
    if ('alt' == $oddcomment) $oddcomment = '';
    else $oddcomment = 'alt';
  ?>

  <?php endforeach; /* end for each comment */ ?>
  </ol>

 <?php else : // this is displayed if there are no comments so far ?>

  <?php if ('open' == $post-> comment_status) : ?>
    <!-- If comments are open, but there are no comments. -->
  <?php else : // comments are closed ?>
    <!-- If comments are closed. -->
    <p class="nocomments">Comments are closed.</p>
  <?php endif; ?>
<?php endif; ?>

<?php if ('open' == $post-> comment_status) : ?>

<h3 id="respond">Leave a Reply</h3>
	<?php if ( get_option('comment_registration') && !$user_ID ) : ?>

	<p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php the_permalink(); ?>">logged in</a> to post a comment.</p>
	<?php else : ?>

	<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">
		<?php if ( $user_ID ) : ?>
			<p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?action=logout" title="<?php _e('Log out of this account') ?>">Logout &raquo;</a></p>
		<?php else : ?>

			<p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" />
			<label for="author"><small>Name <?php if ($req) _e('(required)'); ?></small></label></p>
			
			<p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" />
			<label for="email"><small>Mail (will not be published) <?php if ($req) _e('(required)'); ?></small></label></p>
			
			<p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" />
			<label for="url"><small>Website</small></label></p>

		<?php endif; ?>

		<!--<p><small><strong>XHTML:</strong> You can use these tags: <?php echo allowed_tags(); ?></small></p>-->

		<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>
		<p>
			<input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" />
			<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" />
		</p>
		<?php do_action('comment_form', $post->ID); ?>
	</form>
<?php endif; // If registration required and not logged in ?>

<?php endif; // if you delete this the sky will fall on your head 

This can be broken down into three distinct sections:

  • Direct linking & password protection
  • Comments
  • Comment reply

I will look at each of these in turn.

Direct linking & password protection

This part prevents direct access to the comments.php file and ensures that a correct password has been entered, should the post be protected.

<?php // Do not delete these lines
 if ('comments.php' == basename($_SERVER['SCRIPT_FILENAME']))
   die ('Please do not load this page directly. Thanks!');

 if (!empty($post->post_password)) { // if there's a password
   if ($_COOKIE['wp-postpass_' . COOKIEHASH] != $post->post_password) {  // and it doesn't match the cookie
  ?>
  <p class="nocomments"><?php _e("This post is password protected. Enter the password to view comments."); ?><p>

 <?php
 return;
     }
 }

 /* This variable is for alternating comment background */
 $oddcomment = 'alt';
?>

Although it states that you should not delete the lines this is more a warning that an absolute rule.

The first part prevents direct access to the file:

if ('comments.php' == basename($_SERVER['SCRIPT_FILENAME']))
    die ('Please do not load this page directly. Thanks!');

You can verify the effectiveness of this by browsing to the full URL of the comments.php file (try the one here). The above code will simply print that you shouldn’t load the page directly, and then ‘die’. In PHP terms this tells it to stop running the current script.

This protection is not really necessary as direct access to the file will not provide any backdoor information – The Loop will not be running, and no information will be loaded by WordPress. Its existence in the file is possible a hang-over from an earlier version of Kubrick or WordPress.

The next part checks if a password has been set on the post. If so, it then checks for the existence of a password cookie and compares this to the password. This password cookie will only have been set if the user has logged in to the post, and this is handled elsewhere by WordPress. For the most part this section should be left as it is, although you could change the text to display something else when no password has been entered.

Comments

Now we come to the important part – the comments themselves. We start with a simple check for comments, and then display the number of comments available:

<?php if ($comments) : ?>
  <h3 id="comments"><?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;<?php the_title(); ?>&#8221;</h3>

The comments_number function returns the number of comments, and we provide it with three text strings to display when there are no comments, one comment, and many comments. This handles all natural language issues.

Next we have the bulk of the work:

<ol class="commentlist">
  <?php foreach ($comments as $comment) : ?>
    <li class="<?php echo $oddcomment; ?>" id="comment-<?php comment_ID() ?>">
      <cite><?php comment_author_link() ?></cite> Says:

      <?php if ($comment->comment_approved == '0') : ?>
      <em>Your comment is awaiting moderation.</em>
      <?php endif; ?>
      <br />

      <small class="commentmetadata"><a href="#comment-<?php comment_ID() ?>" title=""><?php comment_date('F jS, Y') ?> at <?php comment_time() ?></a> <?php edit_comment_link('e','',''); ?></small>
      <?php comment_text() ?>
    </li>

  <?php /* Changes every other comment to a different class */ 
    if ('alt' == $oddcomment) $oddcomment = '';
    else $oddcomment = 'alt';
  ?>

  <?php endforeach; /* end for each comment */ ?>
</ol>

You can immediately see that comments are structured as an ordered list, with each list item being a separate comment. The PHP construct used here is a foreach statement:

<?php foreach ($comments as $comment) : ?> 

The first argument $comments is an array of comments provided by WordPress. The foreach statement is an easy way of saying ‘for each element in array $comments assign the value to $comment’. This allows us to step through every comment and have the information assigned to the $comment variable.

<li class="<?php echo $oddcomment; ?>" id="comment-<?php comment_ID() ?>">

This is the start of the comment, and the class is assigned the value of the variable $oddcomment. Although this may seem strange, it is explained several lines later with:

<?php /* Changes every other comment to a different class */ 
    if ('alt' == $oddcomment) $oddcomment = '';

    else $oddcomment = 'alt';
  ?>

Simply put, this changes the class of the comments by assigning a class of ‘alt’ to alternate comments. That is, the first comment has a class of ‘alt’, the second one doesn’t, and the third does. This allows us to have alternate styling to make the comments easier to read. We’ll look at this more later.

A link anchor has also been defined for the comment allowing direct linking.

The rest of the code is straightforward:

<cite><?php comment_author_link() ?></cite> Says:
<?php if ($comment->comment_approved == '0') : ?>

<em>Your comment is awaiting moderation.</em>
<?php endif; ?>
<br />

<small class="commentmetadata"><a href="#comment-<?php comment_ID() ?>" title=""><?php comment_date('F jS, Y') ?> at <?php comment_time() ?></a> <?php edit_comment_link('e','',''); ?></small>

<?php comment_text() ?>

First the author name and URL is displayed, followed by comment approval status (if approved then nothing is visible). Next is the meta data for the comment – ID number, date, and edit link for administrators. The final part is the comment itself.

All of this code can be changed, and you may decide to rearrange the information completely. For this guide the only modification will be changing ‘Says’ to ‘says’ – it’s better English!

If no comments are displayed then this section of code will be executed::

<?php else : // this is displayed if there are no comments so far ?>
  <?php if ('open' == $post-> comment_status) : ?>

    <!-- If comments are open, but there are no comments. -->
   
  <?php else : // comments are closed ?>

    <!-- If comments are closed. -->
    <p class="nocomments">Comments are closed.</p>

  <?php endif; ?>
<?php endif; ?>

You may want to change the displayed text and style.

Comments reply

The rest of comments.php is involved in displaying a form for visitors to leave their own comments. You change the layout of this if you wish.

The only part worth mentioning is:

<?php if ( $user_ID ) : ?>
  <p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?action=logout" title="<?php _e('Log out of this account') ?>">Logout &raquo;</a></p>

WordPress keeps track of users that are logged in, and we can use this knowledge through special variables – in this instance $user_ID and $user_identity determine if the user is logged in and what they are called.

Styling the comments

We’ve discovered that comments are structured as an ordered list, and this is a key factor in styling them.

Here I present a basic block style:

ol.commentlist {
  width: 90%;
  margin: 0 auto;
}

ol.commentlist li {
  margin-bottom: 1.5em;
  border: 1px solid #c69835;
  padding: 5px;
  background-color: #f5de74;
}

ol.commentlist li.alt {
  background-color: #fdf6a7;
}

ol.commentlist a {
  color: #bd492a;
}

small.commentmetadata {
  font-size: 0.8em;
  margin-bottom: 1em;
  display: block;
}

The comment width is shrunk slightly, and then centred. Space is introduced between comments, and also inside the comment itself. The comment meta data is given extra spacing, and everything is wrapped inside coloured blocks – the colour of the block changes alternately, using the ‘alt’ class discussed earlier.

Now when we look at the comments:

Comments

105 comments

  1. Superb, Stunning and Diligent… I was just looking how to design a WordPress theme from my HTML template and this is one tutorial which was just perfect. Thanks for all the painstaking documentation. God Bless!

  2. Thank YOU!

    I thought I knew CSS but one look at the Kubrick style.css made wonder whether I really knew it. Anyway, that look was enough to put aside the theme redesign project I had in mind, particularly when I found that whatever changes I make to the stylesheet, the header had the same blue background. It was only when I went through your tutorial that I really was able to identify the problem and go to the Admin panel of wordpress.

    Your tutorial provided many more such insights into small details with big impact.

    Above all, it provided the confidence to start on the theme redesign project.

    Once again, Thank YOU!

Leave a comment

Your email address will not be published. Required fields are marked *