Make WordPress Core

Changeset 54111


Ignore:
Timestamp:
09/09/2022 02:04:18 AM (18 months ago)
Author:
peterwilsoncc
Message:

Query: Improve WP_Query's cache key generation for taxonomy queries.

Modify how WP_Query determines whether a database query contains a taxonomy component and accounts for term changes when generating the cache key. This presents a stale cache been used under some circumstances.

Props Chouby, costdev, peterwilsoncc.
See #22176.

Location:
trunk
Files:
2 edited

Legend:

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

    r53941 r54111  
    30953095
    30963096            $last_changed = wp_cache_get_last_changed( 'posts' );
    3097             if ( ! empty( $this->tax_query->queried_terms ) ) {
     3097            if ( ! empty( $this->tax_query->queries ) ) {
    30983098                $last_changed .= wp_cache_get_last_changed( 'terms' );
    30993099            }
  • trunk/tests/phpunit/tests/query/cacheResults.php

    r53941 r54111  
    33/**
    44 * @group query
     5 * @covers WP_Query::get_posts
    56 */
    67class Test_Query_CacheResults extends WP_UnitTestCase {
     
    894895        $this->assertNotSame( $query1->found_posts, $query2->found_posts );
    895896    }
     897
     898    /**
     899     * @ticket 22176
     900     */
     901    public function test_query_cache_should_exclude_post_with_excluded_term() {
     902        $term_id = self::$t1;
     903        // Post 0 has the term applied
     904        $post_id = self::$posts[0];
     905
     906        $args = array(
     907            'fields'    => 'ids',
     908            'tax_query' => array(
     909                array(
     910                    'taxonomy' => 'category',
     911                    'terms'    => array( $term_id ),
     912                    'operator' => 'NOT IN',
     913                ),
     914            ),
     915        );
     916
     917        $post_ids_q1 = get_posts( $args );
     918        $this->assertNotContains( $post_id, $post_ids_q1, 'First query includes the post ID.' );
     919
     920        $num_queries = get_num_queries();
     921        $post_ids_q2 = get_posts( $args );
     922        $this->assertNotContains( $post_id, $post_ids_q2, 'Second query includes the post ID.' );
     923
     924        $this->assertSame( $num_queries, get_num_queries(), 'Second query is not cached.' );
     925    }
     926
     927    /**
     928     * @ticket 22176
     929     */
     930    public function test_query_cache_should_exclude_post_when_excluded_term_is_added_after_caching() {
     931        $term_id = self::$t1;
     932        // Post 1 does not have the term applied.
     933        $post_id = self::$posts[1];
     934
     935        $args = array(
     936            'fields'    => 'ids',
     937            'tax_query' => array(
     938                array(
     939                    'taxonomy' => 'category',
     940                    'terms'    => array( $term_id ),
     941                    'operator' => 'NOT IN',
     942                ),
     943            ),
     944        );
     945
     946        $post_ids_q1 = get_posts( $args );
     947        $this->assertContains( $post_id, $post_ids_q1, 'First query does not include the post ID.' );
     948
     949        wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     950
     951        $num_queries = get_num_queries();
     952        $post_ids_q2 = get_posts( $args );
     953        $this->assertNotContains( $post_id, $post_ids_q2, 'Second query includes the post ID.' );
     954        $this->assertNotSame( $num_queries, get_num_queries(), 'Applying term does not invalidate previous cache.' );
     955    }
     956
     957    /**
     958     * @ticket 22176
     959     */
     960    public function test_query_cache_should_not_exclude_post_when_excluded_term_is_removed_after_caching() {
     961        $term_id = self::$t1;
     962        // Post 0 has the term applied.
     963        $post_id = self::$posts[0];
     964
     965        $args = array(
     966            'fields'    => 'ids',
     967            'tax_query' => array(
     968                array(
     969                    'taxonomy' => 'category',
     970                    'terms'    => array( $term_id ),
     971                    'operator' => 'NOT IN',
     972                ),
     973            ),
     974        );
     975
     976        $post_ids_q1 = get_posts( $args );
     977        $this->assertNotContains( $post_id, $post_ids_q1, 'First query includes the post ID.' );
     978
     979        // Clear the post of terms.
     980        wp_set_object_terms( $post_id, array(), 'category' );
     981
     982        $num_queries = get_num_queries();
     983        $post_ids_q2 = get_posts( $args );
     984        $this->assertContains( $post_id, $post_ids_q2, 'Second query does not include the post ID.' );
     985        $this->assertNotSame( $num_queries, get_num_queries(), 'Removing term does not invalidate previous cache.' );
     986    }
    896987}
Note: See TracChangeset for help on using the changeset viewer.