4

I am developing a WordPress theme for which I would like each comment's timestamp wrapped in in a <span> element for the sake of styling it with CSS rules. However, the wp_list_comments() function as I use it in my theme's comments.php template does not seem to provide options to alter the HTML produced:

<ol class="comment-list">
    <?php
        wp_list_comments( array(
            'style'       => 'ol',
            'format'      => 'html5',
            'short_ping'  => true,
        ) );
    ?>
</ol>

which produces timestamps as such:

<time datetime="2015-12-21T19:09:49+00:00"> december 21st,  2015 on 19:09 </time>

How can I alter the function's output to include a <span>element around each <time> element without altering core files?

I've tried looking at my theme's functions.php, as well as WordPress wp-includes/comment.php and wp-includes/comment-template.php. None of them deal with the actual tag structure of the comment timestamps generated by wp_list_comments(), so there was nothing there for me to play with.

  • Have you seen the source of wp_list_comments()? Are you sure this the function responsible and it's not for e.g. the comments.php template or a completely different part responsible? – kaiser Feb 2 '16 at 21:51
  • 1
    Are you certain you actually need a <span> wrapper? Why not apply styles directly to the <time> element? – bosco Feb 2 '16 at 22:11
  • I agree with @bosco, it sounds like the <span> isn't needed here. Else you should show the arguments to the wp_list_comments() function, to see if it's using callback or custom walker. Most likely you're using the built-in Walker_Comment::html5_comment(). A somewhat related question was asked here yesterday. – birgire Feb 2 '16 at 22:43
  • 1
    @birgie my bad - I actually edited out his use of wp_list_comments() because I thought it was extraneous. Corrected O.o – bosco Feb 2 '16 at 22:50
  • found EXACTLY what i needed in this file: wp-includes/class-walker-comment.php - this is where i could change the html of the comment date. i want to style the time differently than the date, so i needed them in seperate tags. thanks everyone! – marlakash Feb 3 '16 at 7:37
9

Here are some options on how we can override the native layout for each comment:

Approach #1 - Overriding start_el() with a custom walker

Let's define our custom wpse comment format:

// Arguments for wp_list_comments() 
$args = [
    'style'       => 'ol',
    'format'      => 'html5',
    'short_ping'  => true,
];

// Use our custom walker if it's available
if( class_exists( 'WPSE_Walker_Comment' ) )
{
    $args['format'] = 'wpse';
    $args['walker'] = new WPSE_Walker_Comment;
}

wp_list_comments( $args );

with a custom comment walker, that handles this new format (PHP 5.4+):

/**
 * Custom comment walker
 *
 * @users Walker_Comment
 */
class WPSE_Walker_Comment extends Walker_Comment
{
    public function start_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 )
    {
       // Our custom 'wpse' comment format
       if ( 'wpse' === $args['format'] )
       {
           $depth++;
           $GLOBALS['comment_depth'] = $depth;
           $GLOBALS['comment'] = $comment;

           // Start output buffering
           ob_start();

           // Let's use the native html5 comment template
           $this->html5_comment( $comment, $depth, $args );

           // Our modifications (wrap <time> with <span>)
           $output .= str_replace( 
               [ '<time ', '</time>' ], 
               ['<span><time ', '</time></span>' ], 
               ob_get_clean() 
           );
       }
       else
       {
           // Fallback for the native comment formats
           parent::start_el( $output, $comment, $depth, $args, $id );
       }    
    }
} // end class

Note how we handle our custom comment format. We also reuse the start_el() method from the parent class for the native formats, by calling parent::start_el().

Also note that we use the output buffering in a similar way as the parent class.

Approach #2 - Overriding html5_comment() with a custom walker

We can also directly override the native Walker_Comment::html5_comment() method, in the following way:

// Arguments for wp_list_comments() 
$args = [
    'style'       => 'ol',
    'format'      => 'html5',
    'short_ping'  => true,
];

// Use our custom walker if it's available
if( class_exists( 'WPSE_Walker_Comment' ) )
{
    $args['walker'] = new WPSE_Walker_Comment;
}

wp_list_comments( $args );

where our custom walker class is defined as:

/**
 * Custom comment walker
 *
 * @users Walker_Comment
 */
class WPSE_Walker_Comment extends Walker_Comment
{
    public function html5_comment( $comment, $depth, $args )
    {
        // Place the modifications of the Walker_Comment::html5_comment() method here
    }
} // end class

Here we can store our modifications to the Walker_Comment::html5_comment() method. It's rather long, so I didn't add it here.

Approach #3 - Custom callback

Here we would use the callback attribute:

// Arguments for wp_list_comments() 
$args = [
    'style'       => 'ol',
    'format'      => 'html5',
    'short_ping'  => true,
];

// Use our custom callback if it's available
if( function_exists( 'wpse_comment_callback' ) )
{
    $args['format'] = 'wpse';
    $args['callback'] = 'wpse_comment_callback';
}

wp_list_comments( $args );

where we define the wpse_comment_callback() to our needs.

/**
 * Custom comment callback
 */
function wpse_comment_callback( $comment, $depth, $args )
{
    // Modify the Walker_Comment::html5_comment() method to our needs 
    // and place it here
}

where we could start by simulating the Walker_Comment::html5_comment() method. But we must remember to replace all reference to $this.

There are other approaches avilable, but hopefully you can adjust these to your needs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.