From 1b8c0d611a3a03fb7b1e7dd5cf5047187936a4d2 Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Sun, 3 Jan 2016 02:02:59 +0000 Subject: [PATCH] Ensure that non-default pagination values work in `wp_list_comments()`. Prior to 4.4, it was possible to pass 'page' and 'per_page' values to `wp_list_comments()` that do not match the corresponding global query vars. This ability was lost in 4.4 with the refactor of how `comments_template()` queries for comments; when the main comment query started fetching only the comments that ought to appear on a page, instead of all of a post's comments, it became impossible for the comment walker to select comments corresponding to custom pagination parameters. See #8071. We restore the previous behavior by (a) detecting when a 'page' or 'per_page' parameter has been passed to `wp_list_comments()` that does not match the corresponding query vars (so that the desired comments will not be found in `$wp_query`), and if so, then (b) querying for all of the post's comments and passing them to the comment walker for pagination, as was the case before 4.4. Props boonebgorges, smerriman. Fixes #35175. git-svn-id: https://develop.svn.wordpress.org/trunk@36157 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/comment-template.php | 21 ++++ .../phpunit/tests/comment/wpListComments.php | 113 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 tests/phpunit/tests/comment/wpListComments.php diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index ac843243e9..f4c904bc88 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -1876,6 +1876,27 @@ function wp_list_comments( $args = array(), $comments = null ) { */ $r = apply_filters( 'wp_list_comments_args', $r ); + /* + * If 'page' or 'per_page' has been passed, and does not match what's in $wp_query, + * perform a separate comment query and allow Walker_Comment to paginate. + */ + if ( is_singular() && ( $r['page'] || $r['per_page'] ) ) { + $current_cpage = get_query_var( 'cpage' ); + if ( ! $current_cpage ) { + $current_cpage = 'newest' === get_option( 'default_comments_page' ) ? 1 : $wp_query->max_num_comment_pages; + } + + $current_per_page = get_query_var( 'comments_per_page' ); + if ( $r['page'] != $current_cpage || $r['per_page'] != $current_per_page ) { + $comments = get_comments( array( + 'post_id' => get_queried_object_id(), + 'orderby' => 'comment_date_gmt', + 'order' => 'ASC', + 'status' => 'all', + ) ); + } + } + // Figure out what comments we'll be looping through ($_comments) if ( null !== $comments ) { $comments = (array) $comments; diff --git a/tests/phpunit/tests/comment/wpListComments.php b/tests/phpunit/tests/comment/wpListComments.php new file mode 100644 index 0000000000..84f6e4c517 --- /dev/null +++ b/tests/phpunit/tests/comment/wpListComments.php @@ -0,0 +1,113 @@ +post->create(); + + $comments = array(); + $now = time(); + for ( $i = 0; $i <= 5; $i++ ) { + $comments[] = self::factory()->comment->create( array( + 'comment_post_ID' => $p, + 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - $i ), + 'comment_author' => 'Commenter ' . $i, + ) ); + } + + update_option( 'page_comments', true ); + update_option( 'comments_per_page', 2 ); + + $this->go_to( get_permalink( $p ) ); + + // comments_template() populates $wp_query->comments + get_echo( 'comments_template' ); + + $found = wp_list_comments( array( + 'page' => 2, + 'echo' => false, + ) ); + + preg_match_all( '|id="comment\-([0-9]+)"|', $found, $matches ); + + $this->assertEqualSets( array( $comments[2], $comments[3] ), $matches[1] ); + } + + /** + * @ticket 35175 + */ + public function test_should_respect_per_page_param() { + $p = self::factory()->post->create(); + + $comments = array(); + $now = time(); + for ( $i = 0; $i <= 5; $i++ ) { + $comments[] = self::factory()->comment->create( array( + 'comment_post_ID' => $p, + 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - $i ), + 'comment_author' => 'Commenter ' . $i, + ) ); + } + + update_option( 'page_comments', true ); + update_option( 'comments_per_page', 2 ); + + $this->go_to( get_permalink( $p ) ); + + // comments_template() populates $wp_query->comments + get_echo( 'comments_template' ); + + $found = wp_list_comments( array( + 'per_page' => 3, + 'echo' => false, + ) ); + + preg_match_all( '|id="comment\-([0-9]+)"|', $found, $matches ); + + $this->assertEqualSets( array( $comments[0], $comments[1], $comments[2] ), $matches[1] ); + } + + /** + * @ticket 35175 + */ + public function test_should_respect_reverse_top_level_param() { + $p = self::factory()->post->create(); + + $comments = array(); + $now = time(); + for ( $i = 0; $i <= 5; $i++ ) { + $comments[] = self::factory()->comment->create( array( + 'comment_post_ID' => $p, + 'comment_date_gmt' => date( 'Y-m-d H:i:s', $now - $i ), + 'comment_author' => 'Commenter ' . $i, + ) ); + } + + update_option( 'page_comments', true ); + update_option( 'comments_per_page', 2 ); + + $this->go_to( get_permalink( $p ) ); + + // comments_template() populates $wp_query->comments + get_echo( 'comments_template' ); + + $found1 = wp_list_comments( array( + 'reverse_top_level' => true, + 'echo' => false, + ) ); + preg_match_all( '|id="comment\-([0-9]+)"|', $found1, $matches ); + $this->assertSame( array( $comments[0], $comments[1] ), array_map( 'intval', $matches[1] ) ); + + $found2 = wp_list_comments( array( + 'reverse_top_level' => false, + 'echo' => false, + ) ); + preg_match_all( '|id="comment\-([0-9]+)"|', $found2, $matches ); + $this->assertSame( array( $comments[1], $comments[0] ), array_map( 'intval', $matches[1] ) ); + } +}