Make WordPress Core

Changeset 34729


Ignore:
Timestamp:
10/01/2015 03:10:13 AM (9 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.