From ea18ccfdb440116aca885be29077ed515f42f19a Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Tue, 25 Oct 2022 00:37:17 +0000 Subject: [PATCH] Query: Move cache key generation to its own method. Introduce `WP_Query::generate_cache_key()` for generating the cache key used by the main database query. This removes the need for a filter to test that cache keys do not include the WPDB placeholder causing unreachable cache keys. The tests now call `WP_Query::generate_cache_key()` directly. The filter `wp_query_cache_key` is removed as a hard deprecation. The filter was not included in a stable release. Follow up to [54634]. Props spacedmonkey, jorbin, azaozz, hellofromtonya, mukesh27, peterwilsoncc, desrosj, audrasjb, adamsilverstein, flixos90, davidbaumwald, joedolson, sergeybiryukov. Fixes #56802. Built from https://develop.svn.wordpress.org/trunk@54685 git-svn-id: http://core.svn.wordpress.org/trunk@54237 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-query.php | 91 +++++++++++++++++++++------------- wp-includes/version.php | 2 +- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/wp-includes/class-wp-query.php b/wp-includes/class-wp-query.php index 601ff077a2..511c4a7eec 100644 --- a/wp-includes/class-wp-query.php +++ b/wp-includes/class-wp-query.php @@ -3106,41 +3106,8 @@ class WP_Query { */ $id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), ' RAND(' ); if ( $q['cache_results'] && $id_query_is_cacheable ) { - $cache_args = $q; - - unset( - $cache_args['suppress_filters'], - $cache_args['cache_results'], - $cache_args['fields'], - $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['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' ); - if ( ! empty( $this->tax_query->queries ) ) { - $last_changed .= wp_cache_get_last_changed( 'terms' ); - } - - $cache_key = "wp_query:$key:$last_changed"; - - /** - * Filters query cache key. - * - * @since 6.1.0 - * - * @param string $cache_key Cache key. - * @param array $cache_args Query args used to generate the cache key. - * @param string $new_request SQL Query. - * @param WP_Query $query The WP_Query instance. - */ - $cache_key = apply_filters( 'wp_query_cache_key', $cache_key, $cache_args, $new_request, $this ); + $cache_key = $this->generate_cache_key( $q, $new_request ); $cache_found = false; if ( null === $this->posts ) { @@ -4755,6 +4722,62 @@ class WP_Query { return $elements; } + + /** + * Generate cache key. + * + * @since 6.1.0 + * + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param array $args Query arguments. + * @param string $sql SQL statement. + * + * @return string Cache key. + */ + protected function generate_cache_key( array $args, $sql ) { + global $wpdb; + + unset( + $args['cache_results'], + $args['fields'], + $args['lazy_load_term_meta'], + $args['update_post_meta_cache'], + $args['update_post_term_cache'], + $args['update_menu_item_cache'], + $args['suppress_filters'] + ); + + $placeholder = $wpdb->placeholder_escape(); + array_walk_recursive( + $args, + /* + * Replace wpdb placeholders with the string used in the database + * query to avoid unreachable cache keys. This is necessary because + * the placeholder is randomly generated in each request. + * + * $value is passed by reference to allow it to be modified. + * array_walk_recursive() does not return an array. + */ + function ( &$value ) use ( $wpdb, $placeholder ) { + if ( is_string( $value ) && str_contains( $value, $placeholder ) ) { + $value = $wpdb->remove_placeholder_escape( $value ); + } + } + ); + + // Replace wpdb placeholder in the SQL statement used by the cache key. + $sql = $wpdb->remove_placeholder_escape( $sql ); + $key = md5( serialize( $args ) . $sql ); + + $last_changed = wp_cache_get_last_changed( 'posts' ); + if ( ! empty( $this->tax_query->queries ) ) { + $last_changed .= wp_cache_get_last_changed( 'terms' ); + } + + return "wp_query:$key:$last_changed"; + } + /** * After looping through a nested query, this function * restores the $post global to the current post in this query. diff --git a/wp-includes/version.php b/wp-includes/version.php index 252ba9e020..3f9331a998 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.2-alpha-54678'; +$wp_version = '6.2-alpha-54685'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.