Make WordPress Core

Changeset 34729


Ignore:
Timestamp:
10/01/2015 03:10:13 AM (11 years ago)
Author:
boonebgorges
Message:

Simplify pagination logic in comments_template().

[34561] "fixed" the problem of newest-first comments showing fewer than
'per_page' comments on the post permalink when the total number of comments
was not divisible by 'per_page'. See #29462. But this fix caused numerous
other problems. First, comment pages reported by get_page_of_comment()
(which expects comment pages to be filled oldest-first) were no longer correct.
Second, and more seriously, the new logic caused comments to be shifted
between pages, making their permalinks non-permanent.

The current changeset reverts the changed behavior. In order to preserve the
performance improvements introduced in [34561], an additional query must be
performed when 'default_comments_page=newest' and 'cpage=0' (ie, you're viewing
the post permalink). A nice side effect of this revert is that we no longer
need the hacks required to determine proper comment pagination, introduced in
[34561].

See #8071. See #34073.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/comment-template.php

    r34716 r34729  
    12411241        }
    12421242
    1243         /*
    1244          * For legacy reasons, higher page numbers always mean more recent comments, regardless of sort order.
    1245          * Since we don't have full pagination info until after the query, we use some tricks to get the
    1246          * right comments for the current page.
    1247          *
    1248          * Abandon all hope, ye who enter here!
    1249          */
    1250         $flip_comment_order = $trim_comments_on_page= false;
     1243        $comment_args['order']  = 'ASC';
    12511244        $comment_args['number'] = $per_page;
    12521245        $page = (int) get_query_var( 'cpage' );
    1253         if ( 'newest' === get_option( 'default_comments_page' ) ) {
    1254                 if ( $page ) {
    1255                         $comment_args['order'] = 'ASC';
    1256 
    1257                         /*
    1258                          * We don't have enough data (namely, the total number of comments) to calculate an
    1259                          * exact offset. We'll fetch too many comments, and trim them as needed
    1260                          * after the query.
    1261                          */
    1262                         $offset = ( $page - 2 ) * $per_page;
    1263                         if ( 0 > $offset ) {
    1264                                 // `WP_Comment_Query` doesn't support negative offsets.
    1265                                 $comment_args['offset'] = 0;
    1266                         } else {
    1267                                 $comment_args['offset'] = $offset;
    1268                         }
    1269 
    1270                         // Fetch double the number of comments we need.
    1271                         $comment_args['number'] += $per_page;
    1272                         $trim_comments_on_page = true;
    1273                 } else {
    1274                         $comment_args['order'] = 'DESC';
    1275                         $comment_args['offset'] = 0;
    1276                         $flip_comment_order = true;
    1277                 }
     1246
     1247        if ( $page ) {
     1248                $comment_args['offset'] = ( $page - 1 ) * $per_page;
     1249        } elseif ( 'oldest' === get_option( 'default_comments_page' ) ) {
     1250                $comment_args['offset'] = 0;
    12781251        } else {
    1279                 $comment_args['order'] = 'ASC';
    1280                 if ( $page ) {
    1281                         $comment_args['offset'] = ( $page - 1 ) * $per_page;
    1282                 } else {
    1283                         $comment_args['offset'] = 0;
    1284                 }
     1252                // If fetching the first page of 'newest', we need a top-level comment count.
     1253                $top_level_query = new WP_Comment_Query();
     1254                $top_level_count = $top_level_query->query( array(
     1255                        'count'   => true,
     1256                        'orderby' => false,
     1257                        'post_id' => $post->ID,
     1258                        'parent'  => 0,
     1259                ) );
     1260
     1261                $comment_args['offset'] = ( ceil( $top_level_count / $per_page ) - 1 ) * $per_page;
    12851262        }
    12861263
    12871264        $comment_query = new WP_Comment_Query( $comment_args );
    12881265        $_comments = $comment_query->comments;
    1289 
    1290         // Delightful pagination quirk #1: `wp_list_comments()` expects the order to be wrong, so we make it wrong.
    1291         if ( $flip_comment_order ) {
    1292                 $_comments = array_reverse( $_comments );
    1293         }
    1294 
    1295         // Delightful pagination quirk #2: reverse chronological order requires page shifting.
    1296         if ( $trim_comments_on_page ) {
    1297                 // Correct the value of max_num_pages, which is wrong because we manipulated the per_page 'number'.
    1298                 $comment_query->max_num_pages = ceil( $comment_query->found_comments / $per_page );
    1299 
    1300                 // Identify the number of comments that should appear on page 1.
    1301                 $page_1_count = $comment_query->found_comments - ( ( $comment_query->max_num_pages - 1 ) * $per_page );
    1302 
    1303                 // Use that value to shift the matched comments.
    1304                 if ( 1 === $page ) {
    1305                         $_comments = array_slice( $_comments, 0, $page_1_count );
    1306                 } else {
    1307                         $_comments = array_slice( $_comments, $page_1_count, $per_page );
    1308                 }
    1309         }
    13101266
    13111267        // Trees must be flattened before they're passed to the walker.
  • trunk/tests/phpunit/tests/comment/commentsTemplate.php

    r34713 r34729  
    326326                $this->assertSame( array( $comment_1, $comment_2 ), $found_cids );
    327327        }
     328
     329        /**
     330         * @ticket 8071
     331         * @ticket 34073
     332         * @ticket 29462
     333         */
     334        public function test_last_page_of_comments_should_be_full_when_default_comment_page_is_newest() {
     335                $now = time();
     336                $p = $this->factory->post->create();
     337                $comment_1 = $this->factory->comment->create( array(
     338                        'comment_post_ID' => $p,
     339                        'comment_content' => '1',
     340                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 100 ),
     341                ) );
     342                $comment_2 = $this->factory->comment->create( array(
     343                        'comment_post_ID' => $p,
     344                        'comment_content' => '2',
     345                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 200 ),
     346                ) );
     347                $comment_3 = $this->factory->comment->create( array(
     348                        'comment_post_ID' => $p,
     349                        'comment_content' => '3',
     350                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 300 ),
     351                ) );
     352
     353                update_option( 'default_comments_page', 'newest' );
     354                update_option( 'comment_order', 'desc' );
     355
     356                $link = add_query_arg( array(
     357                        'cpage' => 1,
     358                        'comments_per_page' => 2,
     359                ), get_permalink( $p ) );
     360
     361                $this->go_to( $link );
     362                $found = get_echo( 'comments_template' );
     363
     364                $comments = preg_match_all( '/id="comment-([0-9]+)"/', $found, $matches );
     365
     366                $found_cids = array_map( 'intval', $matches[1] );
     367
     368                $this->assertSame( array( $comment_2, $comment_3 ), $found_cids );
     369        }
     370
     371        /**
     372         * @ticket 8071
     373         * @ticket 34073
     374         * @ticket 29462
     375         */
     376        public function test_first_page_of_comments_should_have_remainder_when_default_comments_page_is_newest() {
     377                $now = time();
     378                $p = $this->factory->post->create();
     379                $comment_1 = $this->factory->comment->create( array(
     380                        'comment_post_ID' => $p,
     381                        'comment_content' => '1',
     382                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 100 ),
     383                ) );
     384                $comment_2 = $this->factory->comment->create( array(
     385                        'comment_post_ID' => $p,
     386                        'comment_content' => '2',
     387                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 200 ),
     388                ) );
     389                $comment_3 = $this->factory->comment->create( array(
     390                        'comment_post_ID' => $p,
     391                        'comment_content' => '3',
     392                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 300 ),
     393                ) );
     394
     395                update_option( 'default_comments_page', 'newest' );
     396                update_option( 'comment_order', 'desc' );
     397
     398                $link = add_query_arg( array(
     399                        'cpage' => 2,
     400                        'comments_per_page' => 2,
     401                ), get_permalink( $p ) );
     402
     403                $this->go_to( $link );
     404                $found = get_echo( 'comments_template' );
     405
     406                $comments = preg_match_all( '/id="comment-([0-9]+)"/', $found, $matches );
     407
     408                $found_cids = array_map( 'intval', $matches[1] );
     409
     410                $this->assertSame( array( $comment_1 ), $found_cids );
     411        }
    328412}
Note: See TracChangeset for help on using the changeset viewer.