Make WordPress Core

Changeset 34735


Ignore:
Timestamp:
10/01/2015 05:12:39 AM (9 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.