From ec6982289ab0633718eef8852fbea045a25abfce Mon Sep 17 00:00:00 2001 From: pbearne Date: Fri, 15 Oct 2021 15:33:15 -0400 Subject: [PATCH 1/3] #47642 --- src/wp-includes/class-wp-query.php | 28 +++++++++++++ tests/phpunit/tests/query/orderby.php | 57 +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 tests/phpunit/tests/query/orderby.php diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 1f9516eec472e..0568fc0bd54b3 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -2331,6 +2331,32 @@ public function get_posts() { } elseif ( 'none' === $q['orderby'] ) { $orderby = ''; } else { + // https://core.trac.wordpress.org/ticket/47642 + // Database engine fix to prevent strange (duplicate or missing) results in paginated resultsets + // Test for possible duplicate (non-unique, numeric or datetime) DB keys, add the unique ID + $force_ID = array( 'post_author', 'post_date', 'post_date_gmt', 'post_modified', 'post_modified', 'post_modified_gmt', 'post_parent', 'comment_count' ); + if ( is_array( $q['orderby'] ) ) { + $needs_ID = false; + $has_ID = false; + foreach ( $q['orderby'] as $_orderby => $order ) { + if( in_array( $_orderby, $force_ID ) ) { + $needs_ID = true; + } else { + if( $_orderby === 'ID' ) { + $has_ID = true; + break; // All done + } + } + } + if( $needs_ID && !$has_ID ) { + $q['orderby']['ID'] = 'ASC'; + } + } else { + // Not an array, test as string + if( in_array( $q['orderby'], $force_ID ) ) { + $q['orderby'] .= ' ID'; // Add ID here, note the space + } + } $orderby_array = array(); if ( is_array( $q['orderby'] ) ) { foreach ( $q['orderby'] as $_orderby => $order ) { @@ -2386,6 +2412,8 @@ public function get_posts() { */ $search_orderby = apply_filters( 'posts_search_orderby', $search_orderby, $this ); } + //Add additional sort by order to break ties consistently for pagination https://core.trac.wordpress.org/ticket/47642 + $orderby = $orderby ? $orderby . ', ID' : ' ID'; if ( $search_orderby ) { $orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby; diff --git a/tests/phpunit/tests/query/orderby.php b/tests/phpunit/tests/query/orderby.php new file mode 100644 index 0000000000000..9647ccc099a59 --- /dev/null +++ b/tests/phpunit/tests/query/orderby.php @@ -0,0 +1,57 @@ +post->create_many( 5 ); + + $wpdb->update( + $wpdb->posts, + array( + 'comment_count' => 50, + ), + array( + 'ID' => $posts[2], + ) + ); + $wpdb->update( + $wpdb->posts, + array( + 'comment_count' => 100, + ), + array( + 'ID' => $posts[4], + ) + ); + $args = array( + 'posts_per_page' => 1, + 'paged' => 1, + 'orderby' => 'comment_count', + 'order' => 'desc', + ); + + $query = new WP_Query( $args ); + $actual = array(); + $expected = array( + $posts[4], // 100 comments + $posts[2], // 50 comments + $posts[3], // 0 comments + $posts[1], // 0 comments + $posts[0], // 0 comments + ); + + while ( $query->have_posts() ) { + $actual = array_merge( $actual, wp_list_pluck( $query->posts, 'ID' ) ); + $args['paged']++; + $query = new WP_Query( $args ); + } + + $this->assertSame( $expected, $actual ); + } +} From 30da7acd3b20385f13afccd72b91d87bedffe6c1 Mon Sep 17 00:00:00 2001 From: pbearne Date: Mon, 18 Oct 2021 13:14:14 -0400 Subject: [PATCH 2/3] #47642 whitespace --- src/wp-includes/class-wp-query.php | 25 +++++++++++++++++-------- tests/phpunit/tests/query/orderby.php | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 0568fc0bd54b3..347b84aeac5ac 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -2334,26 +2334,35 @@ public function get_posts() { // https://core.trac.wordpress.org/ticket/47642 // Database engine fix to prevent strange (duplicate or missing) results in paginated resultsets // Test for possible duplicate (non-unique, numeric or datetime) DB keys, add the unique ID - $force_ID = array( 'post_author', 'post_date', 'post_date_gmt', 'post_modified', 'post_modified', 'post_modified_gmt', 'post_parent', 'comment_count' ); + $force_ID = array( + 'post_author', + 'post_date', + 'post_date_gmt', + 'post_modified', + 'post_modified', + 'post_modified_gmt', + 'post_parent', + 'comment_count', + ); if ( is_array( $q['orderby'] ) ) { $needs_ID = false; - $has_ID = false; + $has_ID = false; foreach ( $q['orderby'] as $_orderby => $order ) { - if( in_array( $_orderby, $force_ID ) ) { + if ( in_array( $_orderby, $force_ID, true ) ) { $needs_ID = true; } else { - if( $_orderby === 'ID' ) { + if ( 'ID' === $_orderby ) { $has_ID = true; break; // All done } } } - if( $needs_ID && !$has_ID ) { + if ( $needs_ID && !$has_ID ) { $q['orderby']['ID'] = 'ASC'; } } else { // Not an array, test as string - if( in_array( $q['orderby'], $force_ID ) ) { + if ( in_array( $q['orderby'], $force_ID, true ) ) { $q['orderby'] .= ' ID'; // Add ID here, note the space } } @@ -2397,14 +2406,14 @@ public function get_posts() { // Order search results by relevance only when another "orderby" is not specified in the query. if ( ! empty( $q['s'] ) ) { $search_orderby = ''; - if ( ! empty( $q['search_orderby_title'] ) && ( empty( $q['orderby'] ) && ! $this->is_feed ) || ( isset( $q['orderby'] ) && 'relevance' === $q['orderby'] ) ) { + if ( ( ! empty( $q['search_orderby_title'] ) && ( empty( $q['orderby'] ) && ! $this->is_feed ) ) || ( isset( $q['orderby'] ) && 'relevance' === $q['orderby'] ) ) { $search_orderby = $this->parse_search_order( $q ); } if ( ! $q['suppress_filters'] ) { /** * Filters the ORDER BY used when ordering search results. - * + *https://core.trac.wordpress.org/attachment/ticket/47642 * @since 3.7.0 * * @param string $search_orderby The ORDER BY clause. diff --git a/tests/phpunit/tests/query/orderby.php b/tests/phpunit/tests/query/orderby.php index 9647ccc099a59..9e45703544014 100644 --- a/tests/phpunit/tests/query/orderby.php +++ b/tests/phpunit/tests/query/orderby.php @@ -4,6 +4,8 @@ * Tests for query result ordering, specifically indeterminate ordering. * * @group query + * + * @covers WP_Query::posts */ class Tests_Query_Orderby extends WP_UnitTestCase { function test_order_by_comment_count_does_not_cause_duplication_when_paginating() { From aecc44f01ec8226a1828309d3fd3fcb4032bf217 Mon Sep 17 00:00:00 2001 From: pbearne Date: Mon, 18 Oct 2021 13:36:12 -0400 Subject: [PATCH 3/3] #47642 more white space --- src/wp-includes/class-wp-query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 347b84aeac5ac..8ca1e9c48458f 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -2357,7 +2357,7 @@ public function get_posts() { } } } - if ( $needs_ID && !$has_ID ) { + if ( $needs_ID && ! $has_ID ) { $q['orderby']['ID'] = 'ASC'; } } else {