3

Any ideas how to accomplish this?

Something like this would work, but if there are threaded comments you get the wrong number, because pages with threaded comments have actually more comments than the comments_per_page setting:

$c_page = get_query_var('cpage');
$c_per_page = get_query_var('comments_per_page');

$number = ($c_page * $c_per_page) - $c_per_page + $current_c_index;

($current_c_index is a global variable storing comment count for the current page loop)


Later edit:

A partial solution is to extend the Walker_Comment class, do a clone of the paged_walk() function in which you increase the counter within the $top_elements loop. But still that doesn't count child comments :(

3
  • I gave you an answer below. I hope you post your complete counter in here. I'd like to have a "this is comment number XY" function myself and would ask a Q if you agree, so you can profit from the answered Q yourself too.
    – kaiser
    Jun 21, 2011 at 1:04
  • Are you trying to display the comment number in order the comments are printed, or the comment number in order the comment was received. For e.g: I have 3 top level comments, the second top level comment had a child before first top level comment. So the second top level comment's child will have a number of 4 and the first top level comment's child will have a number of 5. is this what you want? Jul 4, 2011 at 6:57
  • in order the comments are printed Jul 4, 2011 at 10:51

2 Answers 2

3
+250

Try the following custom Comment Walker class. The walker keep tracks for print index in a global variable named $current_comment_print_index; which is intialized in the paged_walk function.

You can print global variable $current_comment_print_index to show the current printed comment number.

<?php 
/*
Plugin Name: Comment Count Walker for WPSE 20527
Author: Hameedullah Khan
Author URI: http://hameedullah.com
Version: 0.1
 */

class CC_Custom_Walker_Comment extends Walker_Comment {

    function paged_walk( $elements, $max_depth, $page_num, $per_page ) {
        global $current_comment_print_index;
        $current_comment_print_index = 0;

        /* sanity check */
        if ( empty($elements) || $max_depth < -1 )
            return '';

        $args = array_slice( func_get_args(), 4 );
        $output = '';

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        $count = -1;
        if ( -1 == $max_depth )
            $total_top = count( $elements );
        if ( $page_num < 1 || $per_page < 0  ) {
            // No paging
            $paging = false;
            $start = 0;
            if ( -1 == $max_depth )
                $end = $total_top;
            $this->max_pages = 1;
        } else {
            $paging = true;
            $start = ( (int)$page_num - 1 ) * (int)$per_page;
            $end   = $start + $per_page;
            if ( -1 == $max_depth )
                $this->max_pages = ceil($total_top / $per_page);
        }

        // flat display
        if ( -1 == $max_depth ) {
            if ( !empty($args[0]['reverse_top_level']) ) {
                $elements = array_reverse( $elements );
                $oldstart = $start;
                $start = $total_top - $end;
                $end = $total_top - $oldstart;
            }

            if ( $paging ) {
                // HK: if paging enabled and its a flat display.
                // HK: mark the current print index from page number * comments per page
                $current_comment_print_index = ( (int) $page_num - 1 ) * $per_page;
            }

            $empty_array = array();
            foreach ( $elements as $e ) {
                $count++;
                if ( $count < $start )
                    continue;
                if ( $count >= $end )
                    break;
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            }
            return $output;
        }

        /*
         * separate elements into two buckets: top level and children elements
         * children_elements is two dimensional array, eg.
         * children_elements[10][] contains all sub-elements whose parent is 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        $total_top = count( $top_level_elements );
        if ( $paging )
            $this->max_pages = ceil($total_top / $per_page);
        else
            $end = $total_top;

        if ( !empty($args[0]['reverse_top_level']) ) {
            $top_level_elements = array_reverse( $top_level_elements );
            $oldstart = $start;
            $start = $total_top - $end;
            $end = $total_top - $oldstart;
        }
        if ( !empty($args[0]['reverse_children']) ) {
            foreach ( $children_elements as $parent => $children )
                $children_elements[$parent] = array_reverse( $children );
        }

        foreach ( $top_level_elements as $e ) {
            $count++;

            // HK: current iteration index, will be added to global index
            // NOTE: will only be added to global index if already printed
            $iteration_comment_print_index = 1;
            // HK: count of current iteration children ( includes grand children too )
            $iteration_comment_print_index += $this->count_children( $e->comment_ID, $children_elements );

            //for the last page, need to unset earlier children in order to keep track of orphans
            if ( $end >= $total_top && $count < $start )
                    $this->unset_children( $e, $children_elements );

            if ( $count < $start ) {
                // HK: if we have already printed this top level comment
                // HK: then just add the count (including children) to global index and continue
                $current_comment_print_index += $iteration_comment_print_index;
                continue;
            }

            if ( $count >= $end )
                break;

            $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
        }

        if ( $end >= $total_top && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
        }

        return $output;
    }

    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
                global $current_comment_print_index;

        if ( !$element )
            return;

                // increment for current comment we are printing
                $current_comment_print_index += 1;

        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

        function count_children( $comment_id, $children_elements ) {
            $children_count = 0;
            if ( isset( $children_elements[$comment_id] ) ) {
                $children_count = count( $children_elements[$comment_id] );
                foreach( $children_elements[$comment_id] as $child ) {
                    $children_count += $this->count_children( $child->comment_ID, $children_elements );
                }
            }
            return $children_count;
        }

}
?>
0
2

I needed something similar a while ago. The following code is from my comment callback function. Inside your comment callback function, call wpse20527_count_children();. I assume that your $number is a global variable.

function wpse20527_count_children()
{
    static $ancestors = null;
    $parent = (int) $comment->comment_parent;

    $is_child = false;
    if ( $parent > (int) 0 )
    {
        $is_child = true;

        if ( ! isset( $ancestors ) )
            $ancestors = array();

        if ( ! array_key_exists( $parent, $ancestors ) )
        {
            $ancestors[$parent] = get_comment_ID();
        }
        else 
        {
            foreach ( $ancestors as $parent_id => $child_id )
            {
                if ( $parent_id == $parent )
                {
                    $ancestors_temp[$parent_id] = $child_id;
                    break;
                }

                $ancestors_temp[$parent_id] = $child_id;
            }
            $ancestors = $ancestors_temp;
        }

        $parent_counter = count( $ancestors );
    }
    return $GLOBALS['number'] + $parent_counter;
}
2
  • I'm not sure what this is supposed to do. If you're counting all comments that have parents, woudn't it be easier and faster to just iterate trough all comments and count the ones that have the comment_parent property !== 0 ? Jun 21, 2011 at 3:34
  • As i said it's part of the code (from my comments template - except for the return value). I personally use this to add classes on the flight for threaded comments. I'm, not sure about what your usecase it.
    – kaiser
    Jun 21, 2011 at 5:20

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.