Skip to content

Commit

Permalink
Query: Move cache key generation to its own method.
Browse files Browse the repository at this point in the history
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: https://core.svn.wordpress.org/trunk@54237 1a063a9b-81f0-0310-95a4-ce76da25c4cd
  • Loading branch information
peterwilsoncc committed Oct 25, 2022
1 parent 6ea5be9 commit 6438ecf
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 35 deletions.
91 changes: 57 additions & 34 deletions wp-includes/class-wp-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -3106,41 +3106,8 @@ public function get_posts() {
*/
$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 ) {
Expand Down Expand Up @@ -4755,6 +4722,62 @@ public function generate_postdata( $post ) {

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.
Expand Down
2 changes: 1 addition & 1 deletion wp-includes/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 6438ecf

Please sign in to comment.