diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 1f6f926b1a05e..dc596cb79a818 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -3088,10 +3088,12 @@ public function get_posts() { $cache_args['update_post_meta_cache'], $cache_args['update_post_term_cache'], $cache_args['lazy_load_term_meta'], - $cache_args['update_menu_item_cache'] + $cache_args['update_menu_item_cache'], + $cache_args['search_orderby_title'] ); $new_request = str_replace( $fields, "{$wpdb->posts}.*", $this->request ); + $new_request = $wpdb->remove_placeholder_escape( $new_request ); $key = md5( serialize( $cache_args ) . $new_request ); $last_changed = wp_cache_get_last_changed( 'posts' ); diff --git a/src/wp-includes/class-wpdb.php b/src/wp-includes/class-wpdb.php index 88317f535e918..c021d606be7e0 100644 --- a/src/wp-includes/class-wpdb.php +++ b/src/wp-includes/class-wpdb.php @@ -2413,12 +2413,17 @@ public function log_query( $query, $query_time, $query_callstack, $query_start, * Generates and returns a placeholder escape string for use in queries returned by ::prepare(). * * @since 4.8.3 + * @since 6.1.0 Added `$reset` parameter. + * + * @param bool $reset Optional. Whether to reset the placeholder. Default false. * * @return string String to escape placeholders. */ - public function placeholder_escape() { + public function placeholder_escape( $reset = false ) { static $placeholder; - + if ( $reset ) { + $placeholder = null; + } if ( ! $placeholder ) { // If ext/hash is not present, compat.php's hash_hmac() does not support sha256. $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1'; diff --git a/tests/phpunit/tests/query/cacheResults.php b/tests/phpunit/tests/query/cacheResults.php index 723c78a2bf0d3..d1c317ed32b23 100644 --- a/tests/phpunit/tests/query/cacheResults.php +++ b/tests/phpunit/tests/query/cacheResults.php @@ -191,6 +191,18 @@ public function data_query_cache() { ), ), ), + 'cache meta query search' => array( + 'args' => array( + 'cache_results' => true, + 'meta_query' => array( + array( + 'key' => 'color', + 'value' => '00', + 'compare' => 'LIKE', + ), + ), + ), + ), 'cache comment_count' => array( 'args' => array( 'cache_results' => true, @@ -209,6 +221,12 @@ public function data_query_cache() { ), ), ), + 'cache search query' => array( + 'args' => array( + 'cache_results' => true, + 's' => 'e', + ), + ), ); } @@ -827,6 +845,70 @@ public function test_query_cache_delete_meta() { $this->assertNotSame( $query1->found_posts, $query2->found_posts ); } + + /** + * @ticket 56802 + */ + public function test_query_cache_like_meta() { + global $wpdb; + $p1 = self::$posts[0]; + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 'meta_query' => array( + array( + 'key' => 'color', + 'value' => '00', + 'compare' => 'LIKE', + ), + ), + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + $num_queries = get_num_queries(); + + // Force placeholder to be different. + $wpdb->placeholder_escape( true ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertSame( $posts1, $posts2, 'Results of first and second query should be the same' ); + $this->assertSame( $num_queries, get_num_queries(), 'Should not result in another database query.' ); + $this->assertContains( $p1, $posts2, 'Result should contain post 0.' ); + $this->assertSame( $query1->found_posts, $query2->found_posts, 'Found posts should match on both queries' ); + } + + /** + * @ticket 56802 + */ + public function test_query_cache_search() { + global $wpdb; + // Post 0 already has the category foo. + $p1 = self::$posts[1]; + + $args = array( + 'cache_results' => true, + 'fields' => 'ids', + 's' => 'e', + ); + $query1 = new WP_Query(); + $posts1 = $query1->query( $args ); + $num_queries = get_num_queries(); + + // Force placeholder to be different. + $wpdb->placeholder_escape( true ); + + $query2 = new WP_Query(); + $posts2 = $query2->query( $args ); + + $this->assertSame( $posts1, $posts2, 'Results of first and second query should be the same' ); + $this->assertSame( $num_queries, get_num_queries(), 'Should not result in another database query.' ); + $this->assertContains( $p1, $posts2, 'Result should contain post 0.' ); + $this->assertSame( $query1->found_posts, $query2->found_posts, 'Found posts should match on both queries' ); + } + /** * @ticket 22176 */