Make WordPress Core

Changeset 55083


Ignore:
Timestamp:
01/18/2023 09:56:55 AM (11 months ago)
Author:
spacedmonkey
Message:

Taxonomy: Remove placeholder from WP_Term_Query cache key.

Remove escape placeholder from query cache key, as placeholders are on a based on a unique id on every request. This meant that it is impossible for a cache to be reused, making queries that use escape placeholders such as searches, meta queries or using the description__like / name__like parameters were unable to be cached.

Follow on from [54634].

Props spacedmonkey, peterwilsoncc.
Fixes #57298.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-term-query.php

    r54867 r55083  
    775775        }
    776776
    777         // $args can be anything. Only use the args defined in defaults to compute the key.
    778         $cache_args = wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) );
    779 
    780         unset( $cache_args['update_term_meta_cache'] );
    781 
    782         if ( 'count' !== $_fields && 'all_with_object_id' !== $_fields ) {
    783             $cache_args['fields'] = 'all';
    784         }
    785 
    786         $key          = md5( serialize( $cache_args ) . serialize( $taxonomies ) . $this->request );
    787         $last_changed = wp_cache_get_last_changed( 'terms' );
    788         $cache_key    = "get_terms:$key:$last_changed";
    789         $cache        = wp_cache_get( $cache_key, 'terms' );
     777        $cache_key = $this->generate_cache_key( $args, $this->request );
     778        $cache     = wp_cache_get( $cache_key, 'terms' );
    790779
    791780        if ( false !== $cache ) {
     
    11431132        return $term_objects;
    11441133    }
     1134
     1135    /**
     1136     * Generate cache key.
     1137     *
     1138     * @since 6.2.0
     1139     *
     1140     * @global wpdb $wpdb WordPress database abstraction object.
     1141     *
     1142     * @param array  $args WP_Term_Query arguments.
     1143     * @param string $sql  SQL statement.
     1144     *
     1145     * @return string Cache key.
     1146     */
     1147    protected function generate_cache_key( array $args, $sql ) {
     1148        global $wpdb;
     1149        // $args can be anything. Only use the args defined in defaults to compute the key.
     1150        $cache_args = wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) );
     1151
     1152        unset( $cache_args['update_term_meta_cache'] );
     1153
     1154        if ( 'count' !== $args['fields'] && 'all_with_object_id' !== $args['fields'] ) {
     1155            $cache_args['fields'] = 'all';
     1156        }
     1157        $taxonomies = (array) $args['taxonomy'];
     1158
     1159        // Replace wpdb placeholder in the SQL statement used by the cache key.
     1160        $sql = $wpdb->remove_placeholder_escape( $sql );
     1161
     1162        $key          = md5( serialize( $cache_args ) . serialize( $taxonomies ) . $sql );
     1163        $last_changed = wp_cache_get_last_changed( 'terms' );
     1164        return "get_terms:$key:$last_changed";
     1165    }
    11451166}
  • trunk/tests/phpunit/tests/term/query.php

    r53942 r55083  
    868868        $this->assertContains( $t1, $q->terms );
    869869    }
     870
     871    /**
     872     * Ensure cache keys are generated without WPDB placeholders.
     873     *
     874     * @ticket 57298
     875     *
     876     * @covers       WP_Term_Query::generate_cache_key
     877     * @dataProvider data_query_cache
     878     */
     879    public function test_generate_cache_key_placeholder( $args ) {
     880        global $wpdb;
     881        $query1 = new WP_Term_Query();
     882        $query1->query( $args );
     883
     884        $query_vars = $query1->query_vars;
     885        $request    = $query1->request;
     886
     887        $reflection = new ReflectionMethod( $query1, 'generate_cache_key' );
     888        $reflection->setAccessible( true );
     889
     890        $cache_key_1 = $reflection->invoke( $query1, $query_vars, $request );
     891
     892        $request_without_placeholder = $wpdb->remove_placeholder_escape( $request );
     893
     894        $cache_key_2 = $reflection->invoke( $query1, $query_vars, $request_without_placeholder );
     895
     896        $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs when using wpdb placeholder.' );
     897    }
     898
     899    /**
     900     * Data provider.
     901     *
     902     * @return array[] Test parameters.
     903     */
     904    public function data_query_cache() {
     905        return array(
     906            'empty query'                => array(
     907                'args' => array(),
     908            ),
     909            'search query'               => array(
     910                'args' => array(
     911                    'search' => 'title',
     912                ),
     913            ),
     914            'search name query'          => array(
     915                'args' => array(
     916                    'name__like' => 'title',
     917                ),
     918            ),
     919            'search description query'   => array(
     920                'args' => array(
     921                    'description__like' => 'title',
     922                ),
     923            ),
     924            'meta query'                 => array(
     925                'args' => array(
     926                    'meta_query' => array(
     927                        array(
     928                            'key' => 'color',
     929                        ),
     930                    ),
     931                ),
     932            ),
     933            'meta query search'          => array(
     934                'args' => array(
     935                    'meta_query' => array(
     936                        array(
     937                            'key'     => 'color',
     938                            'value'   => '00',
     939                            'compare' => 'LIKE',
     940                        ),
     941                    ),
     942                ),
     943            ),
     944            'nested meta query search'   => array(
     945                'args' => array(
     946                    'meta_query' => array(
     947                        'relation' => 'AND',
     948                        array(
     949                            'key'     => 'color',
     950                            'value'   => '00',
     951                            'compare' => 'LIKE',
     952                        ),
     953                        array(
     954                            'relation' => 'OR',
     955                            array(
     956                                'key'     => 'color',
     957                                'value'   => '00',
     958                                'compare' => 'LIKE',
     959                            ),
     960                            array(
     961                                'relation' => 'AND',
     962                                array(
     963                                    'key'     => 'wp_test_suite',
     964                                    'value'   => '56802',
     965                                    'compare' => 'LIKE',
     966                                ),
     967                                array(
     968                                    'key'     => 'wp_test_suite_too',
     969                                    'value'   => '56802',
     970                                    'compare' => 'LIKE',
     971                                ),
     972                            ),
     973                        ),
     974                    ),
     975                ),
     976            ),
     977            'meta query not like search' => array(
     978                'args' => array(
     979                    'meta_query' => array(
     980                        array(
     981                            'key'     => 'color',
     982                            'value'   => 'ff',
     983                            'compare' => 'NOT LIKE',
     984                        ),
     985                    ),
     986                ),
     987            ),
     988        );
     989    }
    870990}
Note: See TracChangeset for help on using the changeset viewer.