Make WordPress Core

Changeset 34735


Ignore:
Timestamp:
10/01/2015 05:12:39 AM (11 years ago)
Author:
boonebgorges
Message:

Ensure that comment permalinks reflect pagination.

After [34561], wp_list_comments() no longer passed all of a post's comments
to Walker_Comments. As a result, calls to get_comment_link() occurring
inside the comment loop had insufficient context to determine the proper
'cpage' value to use when generating comment permalinks. This, in turn, caused
comment permalinks to behave erratically.

The current changeset addresses the problem as follows:

  • get_comment_link() now accepts a 'cpage' parameter. When present, 'cpage' will be used to build the comment permalink - no automatic calculation will take place.
  • When called within the main loop, wp_list_comments() calculates the proper 'cpage' value for comments in the loop, and passes it down to get_comment_link().
  • cpage and comment-page-x query vars are generally required in comment permalinks (see #34068), but an exception is made when 'default_comment_page=oldest': the bare post permalink will always be the same as cpage=1, so cpage is excluded in this case.

Props peterwilsoncc for assiduous spreadsheeting.
Fixes #34073.

Location:
trunk
Files:
1 added
2 edited

Legend:

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

    r34729 r34735  
    660660 *
    661661 * @since 1.5.0
    662  * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object.
     662 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. Added `$cpage` argument.
    663663 *
    664664 * @see get_page_of_comment()
    … …  
    671671 *     An array of optional arguments to override the defaults.
    672672 *
    673  *     @type string $type      Passed to {@see get_page_of_comment()}.
    674  *     @type int    $page      Current page of comments, for calculating comment pagination.
    675  *     @type int    $per_page  Per-page value for comment pagination.
    676  *     @type int    $max_depth Passed to {@see get_page_of_comment()}.
     673 *     @type string     $type      Passed to {@see get_page_of_comment()}.
     674 *     @type int        $page      Current page of comments, for calculating comment pagination.
     675 *     @type int        $per_page  Per-page value for comment pagination.
     676 *     @type int        $max_depth Passed to {@see get_page_of_comment()}.
     677 *     @type int|string $cpage     Value to use for the comment's "comment-page" or "cpage" value. If provided, this
     678 *                                 value overrides any value calculated from `$page` and `$per_page`.
    677679 * }
    678680 * @return string The permalink to the given comment.
    … …  
    688690        }
    689691
    690         $defaults = array( 'type' => 'all', 'page' => '', 'per_page' => '', 'max_depth' => '' );
     692        $defaults = array(
     693                'type'      => 'all',
     694                'page'      => '',
     695                'per_page'  => '',
     696                'max_depth' => '',
     697                'cpage'     => null,
     698        );
    691699        $args = wp_parse_args( $args, $defaults );
    692700
    693         if ( '' === $args['per_page'] )
    694                 $args['per_page'] = get_option('comments_per_page');
    695 
    696         if ( empty($args['per_page']) ) {
    697                 $args['per_page'] = 0;
    698                 $args['page'] = 0;
    699         }
    700 
    701         if ( $args['per_page'] ) {
    702                 if ( '' == $args['page'] )
    703                         $args['page'] = ( !empty($in_comment_loop) ) ? get_query_var('cpage') : get_page_of_comment( $comment->comment_ID, $args );
    704 
    705                 if ( $wp_rewrite->using_permalinks() )
    706                         $link = user_trailingslashit( trailingslashit( get_permalink( $comment->comment_post_ID ) ) . $wp_rewrite->comments_pagination_base . '-' . $args['page'], 'comment' );
    707                 else
    708                         $link = add_query_arg( 'cpage', $args['page'], get_permalink( $comment->comment_post_ID ) );
     701        $link = get_permalink( $comment->comment_post_ID );
     702
     703        // The 'cpage' param takes precedence.
     704        if ( ! is_null( $args['cpage'] ) ) {
     705                $cpage = $args['cpage'];
     706
     707        // No 'cpage' is provided, so we calculate one.
    709708        } else {
    710                 $link = get_permalink( $comment->comment_post_ID );
     709                if ( '' === $args['per_page'] ) {
     710                        $args['per_page'] = get_option('comments_per_page');
     711                }
     712
     713                if ( empty( $args['per_page'] ) ) {
     714                        $args['per_page'] = 0;
     715                        $args['page'] = 0;
     716                }
     717
     718                $cpage = $args['page'];
     719
     720                if ( '' == $cpage ) {
     721                        if ( ! empty( $in_comment_loop ) ) {
     722                                $cpage = get_query_var( 'cpage' );
     723                        } else {
     724                                // Requires a database hit, so we only do it when we can't figure out from context.
     725                                $cpage = get_page_of_comment( $comment->comment_ID, $args );
     726                        }
     727                }
     728
     729                // Drop the 'page' var if we're on the default page.
     730                $comment_post = get_post( $comment->comment_post_ID );
     731                if ( $args['per_page'] ) {
     732                        $total_pages = ceil( $comment_post->comment_count / $args['per_page'] );
     733                } else {
     734                        $total_pages = 1;
     735                }
     736
     737                /*
     738                 * If the default page displays the oldest comments, the permalinks for comments on the default page
     739                 * do not need a 'cpage' query var.
     740                 */
     741                $default_comments_page = get_option( 'default_comments_page' );
     742                if ( 'oldest' === get_option( 'default_comments_page' ) && 1 === $cpage ) {
     743                        $cpage = '';
     744                }
     745        }
     746
     747        if ( $cpage ) {
     748                if ( $wp_rewrite->using_permalinks() ) {
     749                        if ( $cpage ) {
     750                                $link = trailingslashit( $link ) . $wp_rewrite->comments_pagination_base . '-' . $cpage;
     751                        }
     752
     753                        $link = user_trailingslashit( $link, 'comment' );
     754                } elseif ( $cpage ) {
     755                        $link = add_query_arg( 'cpage', $cpage, $link );
     756                }
     757
     758        }
     759
     760        if ( $wp_rewrite->using_permalinks() ) {
     761                $link = user_trailingslashit( $link, 'comment' );
    711762        }
    712763
    713764        $link = $link . '#comment-' . $comment->comment_ID;
     765
    714766        /**
    715767         * Filter the returned single comment permalink.
    716768         *
    717769         * @since 2.8.0
     770         * @since 4.4.0 Added the `$cpage` parameter.
    718771         *
    719772         * @see get_page_of_comment()
    … …  
    722775         * @param WP_Comment $comment The current comment object.
    723776         * @param array      $args    An array of arguments to override the defaults.
    724          */
    725         return apply_filters( 'get_comment_link', $link, $comment, $args );
     777         * @param int        $cpage   The calculated 'cpage' value.
     778         */
     779        return apply_filters( 'get_comment_link', $link, $comment, $args, $cpage );
    726780}
    727781
    … …  
    18781932
    18791933                // Pagination is already handled by `WP_Comment_Query`, so we tell Walker not to bother.
    1880                 if ( 1 < $wp_query->max_num_comment_pages ) {
    1881                         $r['page'] = 1;
     1934                if ( $wp_query->max_num_comment_pages ) {
     1935                        $default_comments_page = get_option( 'default_comments_page' );
     1936                        $cpage = get_query_var( 'cpage' );
     1937                        if ( 'newest' === $default_comments_page ) {
     1938                                $r['cpage'] = $cpage;
     1939
     1940                        // When first page shows oldest comments, post permalink is the same as the comment permalink.
     1941                        } elseif ( $cpage == 1 ) {
     1942                                $r['cpage'] = '';
     1943                        } else {
     1944                                $r['cpage'] = $cpage;
     1945                        }
     1946
     1947                        $r['page'] = 0;
     1948                        $r['per_page'] = 0;
    18821949                }
    18831950        }
  • trunk/tests/phpunit/tests/comment/commentsTemplate.php

    r34729 r34735  
    410410                $this->assertSame( array( $comment_1 ), $found_cids );
    411411        }
     412
     413        /**
     414         * @ticket 34073
     415         */
     416        public function test_comment_permalinks_should_be_correct_when_using_default_display_callback_with_default_comment_page_oldest() {
     417                $now = time();
     418                $p = $this->factory->post->create();
     419                $comment_1 = $this->factory->comment->create( array(
     420                        'comment_post_ID' => $p,
     421                        'comment_content' => '1',
     422                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 100 ),
     423                ) );
     424                $comment_2 = $this->factory->comment->create( array(
     425                        'comment_post_ID' => $p,
     426                        'comment_content' => '2',
     427                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 200 ),
     428                ) );
     429                $comment_3 = $this->factory->comment->create( array(
     430                        'comment_post_ID' => $p,
     431                        'comment_content' => '3',
     432                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 300 ),
     433                ) );
     434                $comment_4 = $this->factory->comment->create( array(
     435                        'comment_post_ID' => $p,
     436                        'comment_content' => '4',
     437                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 400 ),
     438                ) );
     439
     440                update_option( 'comment_order', 'desc' );
     441                update_option( 'default_comments_page', 'oldest' );
     442
     443                $link_p1 = add_query_arg( array(
     444                        'comments_per_page' => 2,
     445                ), get_permalink( $p ) );
     446
     447                $this->go_to( $link_p1 );
     448
     449                $found_p1 = get_echo( 'comments_template' );
     450
     451                // Find the comment permalinks.
     452                preg_match_all( '|href="(.*?#comment-([0-9]+))|', $found_p1, $matches );
     453
     454                // This is the main post page, so we don't expect any cpage param.
     455                foreach ( $matches[1] as $m ) {
     456                        $this->assertNotContains( 'cpage', $m );
     457                }
     458
     459                $link_p2 = add_query_arg( array(
     460                        'cpage' => 2,
     461                        'comments_per_page' => 2,
     462                ), get_permalink( $p ) );
     463
     464                $this->go_to( $link_p2 );
     465
     466                $found_p2 = get_echo( 'comments_template' );
     467
     468                // Find the comment permalinks.
     469                preg_match_all( '|href="(.*?#comment-([0-9]+))|', $found_p2, $matches );
     470
     471                // They should all be on page 2.
     472                foreach ( $matches[1] as $m ) {
     473                        $this->assertContains( 'cpage=2', $m );
     474                }
     475        }
     476
     477        /**
     478         * @ticket 34073
     479         */
     480        public function test_comment_permalinks_should_be_correct_when_using_default_display_callback_with_default_comment_page_newest() {
     481                $now = time();
     482                $p = $this->factory->post->create();
     483                $comment_1 = $this->factory->comment->create( array(
     484                        'comment_post_ID' => $p,
     485                        'comment_content' => '1',
     486                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 100 ),
     487                ) );
     488                $comment_2 = $this->factory->comment->create( array(
     489                        'comment_post_ID' => $p,
     490                        'comment_content' => '2',
     491                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 200 ),
     492                ) );
     493                $comment_3 = $this->factory->comment->create( array(
     494                        'comment_post_ID' => $p,
     495                        'comment_content' => '3',
     496                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 300 ),
     497                ) );
     498                $comment_4 = $this->factory->comment->create( array(
     499                        'comment_post_ID' => $p,
     500                        'comment_content' => '4',
     501                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 400 ),
     502                ) );
     503                $comment_5 = $this->factory->comment->create( array(
     504                        'comment_post_ID' => $p,
     505                        'comment_content' => '4',
     506                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 500 ),
     507                ) );
     508                $comment_6 = $this->factory->comment->create( array(
     509                        'comment_post_ID' => $p,
     510                        'comment_content' => '4',
     511                        'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - 600 ),
     512                ) );
     513
     514                update_option( 'comment_order', 'desc' );
     515                update_option( 'default_comments_page', 'newest' );
     516
     517                $link_p0 = add_query_arg( array(
     518                        'comments_per_page' => 2,
     519                ), get_permalink( $p ) );
     520
     521                $this->go_to( $link_p0 );
     522
     523                $found_p0 = get_echo( 'comments_template' );
     524
     525                // Find the comment permalinks.
     526                preg_match_all( '|href="(.*?#comment-([0-9]+))|', $found_p0, $matches );
     527
     528                foreach ( $matches[1] as $m ) {
     529                        $this->assertContains( 'cpage=3', $m );
     530                }
     531
     532                $link_p2 = add_query_arg( array(
     533                        'cpage' => 2,
     534                        'comments_per_page' => 2,
     535                ), get_permalink( $p ) );
     536
     537                $this->go_to( $link_p2 );
     538
     539                $found_p2 = get_echo( 'comments_template' );
     540
     541                // Find the comment permalinks.
     542                preg_match_all( '|href="(.*?#comment-([0-9]+))|', $found_p2, $matches );
     543
     544                // They should all be on page 2.
     545                foreach ( $matches[1] as $m ) {
     546                        $this->assertContains( 'cpage=2', $m );
     547                }
     548
     549                // p1 is the last page (neat!).
     550                $link_p1 = add_query_arg( array(
     551                        'cpage' => 1,
     552                        'comments_per_page' => 2,
     553                ), get_permalink( $p ) );
     554
     555                $this->go_to( $link_p1 );
     556
     557                $found_p1 = get_echo( 'comments_template' );
     558
     559                // Find the comment permalinks.
     560                preg_match_all( '|href="(.*?#comment-([0-9]+))|', $found_p1, $matches );
     561
     562                // They should all be on page 2.
     563                foreach ( $matches[1] as $m ) {
     564                        $this->assertContains( 'cpage=1', $m );
     565                }
     566        }
    412567}
Note: See TracChangeset for help on using the changeset viewer.