uweschmidt.org

42 / π ≈ 13.37 

Comments in WordPress

The primary purpose of this post is to document the changes I made to core WordPress code in order to get comments working they way I want. Since all of this is a hack, I have to re-do those changes when I upgrade WordPress to a newer version. It would probably be best to write a plugin instead, so I wouldn’t have to change the code each time I upgrade.

Maybe someone is reading this and knows a better way to do all of this. I’m a WordPress novice and just figured those things out by browsing the code, I never read the documentation.

Btw, all of the following applies to WordPress 2.9.1, so things might be different in other versions…

Threaded comments

In Discussion Settings, it’s problematic to first enable threaded (nested) comments X levels deep, then later decrease the maximum comment depth, or even disable nested comments altogether. Comment pagination will break if you have comment threads with a depth that is greather than the one currently set. I experienced this problem because I imported my comments from Drupal, and some comment threads were 10 levels deep. I think WordPress should at least warn about this on the Discussion Settings page…

Also other plugins, like Quote Comments, add thread information to the database even if nested comments are turned off.

I wanted to restore the behavior I had in Drupal, which is a flat comment list, but the user could reply to each comment individually and the comment parent relation is stored in the database. I disabled threaded comments and made the following changes.

Changes in wp-includes/comment.php

This is needed for the function get_page_of_comment to work correctly, if threaded comments are turned off (args['max_depth'] ≤ 1), but (some) comments in the DB have a thread structure (comment_parent ≠ 0).

Original

// Count comments older than this one
$oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) );

Replacement

// Count comments older than this one
if ( $args['max_depth'] > 1 )
  $oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) );
else
  $oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) );

Changes in wp-includes/comment-template.php

Although threaded comments are disabled, I still want to show the Reply-button for each individual comment, which requires changing the function get_comment_reply_link.

Commented code

// if ( 0 == $args[‘depth’] || $args[‘max_depth’] <= $args[‘depth’] )
//  return;

Incorrect comment links

When the HTML code for comments on a page is generated, the variable $in_comment_loop will be set so that the function get_page_of_comment won’t be called each time inside the function get_comment_link (the comments are all on the same page anyway). This is a problem in case one actually wants to get the link to a comment that is on a different page — one example would be the default Recent Comments widget. I also ran into this problem with my in reply to-links (see below).

Changes in wp-includes/comment-template.php

Original

if ( $args['per_page'] ) {
    if ( '' == $args['page'] )
        $args['page'] = ( !empty($in_comment_loop) ) ? get_query_var('cpage') : get_page_of_comment( $comment->comment_ID, $args );

    if ( $wp_rewrite->using_permalinks() )
        $link = user_trailingslashit( trailingslashit( get_permalink( $comment->comment_post_ID ) ) . 'comment-page-' . $args['page'], 'comment' );
    else
        $link = add_query_arg( 'cpage', $args['page'], get_permalink( $comment->comment_post_ID ) );
} else {
    $link = get_permalink( $comment->comment_post_ID );
}

Replacement

Now checking for get_page_of_comment argument that can be set to force page computation.

if ( $args['per_page'] ) {
    if ( '' == $args['page'] )
        $args['page'] = ( !empty($in_comment_loop) && empty($args['get_page_of_comment']) ) ? get_query_var('cpage') : get_page_of_comment( $comment->comment_ID, $args );
    if ( $wp_rewrite->using_permalinks() )
        $link = user_trailingslashit( trailingslashit( get_permalink( $comment->comment_post_ID ) ) . 'comment-page-' . $args['page'], 'comment' );
    else
        $link = add_query_arg( 'cpage', $args['page'], get_permalink( $comment->comment_post_ID ) );
} else {
    $link = get_permalink( $comment->comment_post_ID );
}

Changes in wp-includes/default-widgets.php

Fixing the Recent Comments widget.

Original

<?php echo $before_widget; ?>
    <?php if ( $title ) echo $before_title . $title . $after_title; ?>
    <ul id="recentcomments"><?php
    if ( $comments ) : foreach ( (array) $comments as $comment) :
    echo  '<li class="recentcomments">' . /* translators: comments widget: 1: comment author, 2: post link */ sprintf(_x('%1$s on %2$s', 'widgets'), get_comment_author_link(), '<a href="' . esc_url( get_comment_link($comment->comment_ID) ) . '">' . get_the_title($comment->comment_post_ID) . '</a>') . '</li>';
    endforeach; endif;?></ul>
<?php echo $after_widget; ?>

Replacement

Setting argument get_page_of_comment because the recent comments can all be on different pages.

<?php echo $before_widget; ?>
    <?php if ( $title ) echo $before_title . $title . $after_title; ?>
    <ul id="recentcomments"><?php
    if ( $comments ) : foreach ( (array) $comments as $comment) :
    echo  '<li class="recentcomments">' . /* translators: comments widget: 1: comment author, 2: post link */ sprintf(_x('%1$s on %2$s', 'widgets'), get_comment_author_link(), '<a href="' . esc_url( get_comment_link($comment->comment_ID, array('get_page_of_comment' => true)) ) . '">' . get_the_title($comment->comment_post_ID) . '</a>') . '</li>';
    endforeach; endif;?></ul>
<?php echo $after_widget; ?>

Keeping track of replies

I have a lot of comments on my Wiimote Whiteboard page and it’s sometimes hard to figure to which previous comments someone has replied to. That’s the reason I made a small change to show the comment’s parent.

Changes in wp-includes/comment-template.php

Original

<div class="comment-author vcard">
<?php if ($args['avatar_size'] != 0) echo get_avatar( $comment, $args['avatar_size'] ); ?>
<?php printf(__('<cite class="fn">%s</cite> <span class="says">says:</span>'), get_comment_author_link()) ?>
</div>

Replacement

Setting argument get_page_of_comment, in case the the comment parent is on another comment page.

<div class="comment-author vcard">
<?php if ($args['avatar_size'] != 0) echo get_avatar( $comment, $args['avatar_size'] ); ?>
<?php printf(__('<cite class="fn">%s</cite> <span class="says">says:</span>'), get_comment_author_link()) ?>
<?php
    if ($comment->comment_parent) {
        $parent_comment = get_comment($comment->comment_parent);
        print 'in reply to <a href="'.(htmlspecialchars(get_comment_link($parent_comment->comment_ID, array('get_page_of_comment' => true)))).'">'.$parent_comment->comment_author.'</a>';
    } 
?>
</div>

2 Responses

  1. toto says:

    Thanks for sharing, Uwe.
    The identical “no link to a comment page” problem has WP-RecentComments widget. To tell the truth, it would be nice to hear a miracle cure from You. :)

  2. Uwe says: in reply to toto

    Hi toto,

    I took a brief look at WP-RecentComments and guess you mean the incorrect comment links.

    I glanced over the code and found the culprit in core.php (starting at line 119). The plugin simply assumes that all comments are on the same page — it doesn’t even use WordPress’ get_comment_link function. This should be rather easy to fix; I suggest you contact the author of that plugin about this and send him or her a link to this page.

    if ($comment->comment_type == 'pingback') {
    	$result .= '<li id="rc_item_' . ++$count . '" class="rc_item rc_pingback">' . sprintf('<div class="rc_info"><span class="rc_label">' . __('Pingback:') . '</span> %1$s</div>', get_comment_author_link()) . '</li>';
    } else if ($comment->comment_type == 'trackback') {
    	$result .= '<li id="rc_item_' . ++$count . '" class="rc_item rc_trackback">' . sprintf('<div class="rc_info"><span class="rc_label">' . __('Trackback:') . '</span> %1$s</div>', get_comment_author_link()) . '</li>';
    } else if ($args['post'] == 'true') {
    	$result .= '<li id="rc_item_' . ++$count . '" class="rc_item">' . $element_avatar . sprintf('<div class="rc_info"><span class="author_name">%1$s</span> ' . __('on', 'wp-recentcomments') . ' <span class="post_title">%2$s</span></div>', get_comment_author_link(), '<a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . get_the_title($comment->comment_post_ID) . '</a>') . '<div class="rc_excerpt">' . $comment_excerpt . '</div></li>';
    } else {
    	$result .= '<li id="rc_item_' . ++$count . '" class="rc_item">' . $element_avatar . sprintf('<div class="rc_info"><span class="author_name">%1$s</span>' . rc_get_author_info() . '</div>', '<a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . $comment->comment_author . '</a>') . '<div class="rc_excerpt">' . $comment_excerpt . '</div></li>';
    }
    

    Uwe

Leave a Reply