Getting the comment number relative to all the post’s comments

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:

Read More
$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 🙁

Related posts

Leave a Reply

2 comments

  1. 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;
            }
    
    }
    ?>
    
  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;
    }