Make WordPress Core

Changeset 53496 for trunk


Ignore:
Timestamp:
06/14/2022 11:41:33 AM (2 years ago)
Author:
spacedmonkey
Message:

Taxonomy: Fix caching issues in WP_Term_Query class.

Introduced [52836] when passing child_of or pad_counts parameters to get_terms or WP_Term_Query class, the array of terms received by the query, was not correctly cached. This
change simplifies the logic in WP_Term_Query and ensures terms are correctly cached. This change also, improves performance, by only caching an array of term ids where possible.

Props denishua, spacedmonkey, oztaser, peterwilsoncc, SergeyBiryukov, georgestephanis, jnz31, knutsp, mukesh27, costdev.
Fixes #55837.

Location:
trunk
Files:
3 edited

Legend:

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

    r53469 r53496  
    771771        $cache_args = wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) );
    772772
    773         unset( $cache_args['pad_counts'], $cache_args['update_term_meta_cache'] );
     773        unset( $cache_args['update_term_meta_cache'] );
    774774
    775775        if ( 'count' !== $_fields && 'all_with_object_id' !== $_fields ) {
     
    784784        if ( false !== $cache ) {
    785785            if ( 'ids' === $_fields ) {
    786                 $term_ids = wp_list_pluck( $cache, 'term_id' );
    787                 $cache    = array_map( 'intval', $term_ids );
     786                $cache = array_map( 'intval', $cache );
    788787            } elseif ( 'count' !== $_fields ) {
    789                 $term_ids = wp_list_pluck( $cache, 'term_id' );
     788                if ( ( 'all_with_object_id' === $_fields && ! empty( $args['object_ids'] ) ) || ( 'all' === $_fields && $args['pad_counts'] ) ) {
     789                    $term_ids = wp_list_pluck( $cache, 'term_id' );
     790                } else {
     791                    $term_ids = array_map( 'intval', $cache );
     792                }
    790793                _prime_term_caches( $term_ids, $args['update_term_meta_cache'] );
    791794                $term_objects = $this->populate_terms( $cache );
     
    850853        }
    851854
    852         /*
    853          * When querying for terms connected to objects, we may get
    854          * duplicate results. The duplicates should be preserved if
    855          * `$fields` is 'all_with_object_id', but should otherwise be
    856          * removed.
    857          */
    858         if ( ! empty( $args['object_ids'] ) && 'all_with_object_id' !== $_fields ) {
    859             $_tt_ids = array();
    860             $_terms  = array();
    861             foreach ( $terms as $term ) {
    862                 if ( isset( $_tt_ids[ $term->term_id ] ) ) {
    863                     continue;
    864                 }
    865 
    866                 $_tt_ids[ $term->term_id ] = 1;
    867                 $_terms[]                  = $term;
    868             }
    869 
    870             $terms = $_terms;
    871         }
    872 
    873855        // Hierarchical queries are not limited, so 'offset' and 'number' must be handled now.
    874         if ( $hierarchical && $number && is_array( $terms ) ) {
    875             if ( $offset >= count( $terms ) ) {
    876                 $terms        = array();
     856        if ( $hierarchical && $number && is_array( $term_objects ) ) {
     857            if ( $offset >= count( $term_objects ) ) {
    877858                $term_objects = array();
    878859            } else {
    879                 $terms        = array_slice( $terms, $offset, $number, true );
    880860                $term_objects = array_slice( $term_objects, $offset, $number, true );
    881861            }
     
    888868        }
    889869
    890         wp_cache_add( $cache_key, $terms, 'terms' );
    891         $terms = $this->format_terms( $term_objects, $_fields );
    892 
    893         $this->terms = $terms;
     870        if ( 'all_with_object_id' === $_fields && ! empty( $args['object_ids'] ) ) {
     871            $term_cache = array();
     872            foreach ( $term_objects as $term ) {
     873                $object            = new stdClass();
     874                $object->term_id   = $term->term_id;
     875                $object->object_id = $term->object_id;
     876                $term_cache[]      = $object;
     877            }
     878        } elseif ( 'all' === $_fields && $args['pad_counts'] ) {
     879            $term_cache = array();
     880            foreach ( $term_objects as $term ) {
     881                $object          = new stdClass();
     882                $object->term_id = $term->term_id;
     883                $object->count   = $term->count;
     884                $term_cache[]    = $object;
     885            }
     886        } else {
     887            $term_cache = wp_list_pluck( $term_objects, 'term_id' );
     888        }
     889        wp_cache_add( $cache_key, $term_cache, 'terms' );
     890        $this->terms = $this->format_terms( $term_objects, $_fields );
     891
    894892        return $this->terms;
    895893    }
     
    11201118                    $term->object_id = (int) $term_data->object_id;
    11211119                }
     1120                if ( property_exists( $term_data, 'count' ) ) {
     1121                    $term->count = (int) $term_data->count;
     1122                }
    11221123            } else {
    11231124                $term = get_term( $term_data );
  • trunk/src/wp-includes/version.php

    r53344 r53496  
    2424 * @global int $wp_db_version
    2525 */
    26 $wp_db_version = 51917;
     26$wp_db_version = 53496;
    2727
    2828/**
  • trunk/tests/phpunit/tests/term/getTerms.php

    r53309 r53496  
    745745        );
    746746        $this->assertCount( 1, $terms );
     747    }
     748
     749    /**
     750     * @ticket 55837
     751     * @covers ::get_terms
     752     */
     753    public function test_get_terms_child_of_cache() {
     754        $parent = self::factory()->category->create();
     755        self::factory()->category->create( array( 'parent' => $parent ) );
     756
     757        $args  = array(
     758            'fields'     => 'ids',
     759            'child_of'   => $parent,
     760            'hide_empty' => false,
     761        );
     762        $terms = get_terms( 'category', $args );
     763        $this->assertCount( 1, $terms, 'The first call to get_terms() did not return 1 term' );
     764
     765        $terms2 = get_terms( 'category', $args );
     766        $this->assertCount( 1, $terms2, 'The second call to get_terms() did not return 1 term' );
     767        $this->assertSameSets( $terms, $terms2, 'Results are not the same after caching' );
    747768    }
    748769
     
    25912612
    25922613    /**
     2614     * @ticket 55837
     2615     * @covers ::get_terms
     2616     */
     2617    public function test_pad_counts_cached() {
     2618        register_taxonomy( 'wptests_tax_1', 'post', array( 'hierarchical' => true ) );
     2619
     2620        $posts = self::factory()->post->create_many( 3 );
     2621
     2622        $t1 = self::factory()->term->create(
     2623            array(
     2624                'taxonomy' => 'wptests_tax_1',
     2625            )
     2626        );
     2627        $t2 = self::factory()->term->create(
     2628            array(
     2629                'taxonomy' => 'wptests_tax_1',
     2630                'parent'   => $t1,
     2631            )
     2632        );
     2633        $t3 = self::factory()->term->create(
     2634            array(
     2635                'taxonomy' => 'wptests_tax_1',
     2636                'parent'   => $t2,
     2637            )
     2638        );
     2639
     2640        wp_set_object_terms( $posts[0], array( $t1 ), 'wptests_tax_1' );
     2641        wp_set_object_terms( $posts[1], array( $t2 ), 'wptests_tax_1' );
     2642        wp_set_object_terms( $posts[2], array( $t3 ), 'wptests_tax_1' );
     2643
     2644        $found = get_terms(
     2645            'wptests_tax_1',
     2646            array(
     2647                'pad_counts' => true,
     2648            )
     2649        );
     2650
     2651        $this->assertSameSets( array( $t1, $t2, $t3 ), wp_list_pluck( $found, 'term_id' ), 'Check to see if results are as expected' );
     2652
     2653        foreach ( $found as $f ) {
     2654            if ( $t1 === $f->term_id ) {
     2655                $this->assertSame( 3, $f->count, 'Check to see if term 1, has the correct count' );
     2656            } elseif ( $t2 === $f->term_id ) {
     2657                $this->assertSame( 2, $f->count, 'Check to see if term 2, has the correct count' );
     2658            } else {
     2659                $this->assertSame( 1, $f->count, 'Check to see if term 3, has the correct count' );
     2660            }
     2661        }
     2662
     2663        $found = get_terms(
     2664            'wptests_tax_1',
     2665            array(
     2666                'pad_counts' => true,
     2667            )
     2668        );
     2669
     2670        $this->assertSameSets( array( $t1, $t2, $t3 ), wp_list_pluck( $found, 'term_id' ), 'Check to see if results are as expected on second run' );
     2671
     2672        foreach ( $found as $f ) {
     2673            if ( $t1 === $f->term_id ) {
     2674                $this->assertSame( 3, $f->count, 'Check to see if term 1, has the correct count on second run' );
     2675            } elseif ( $t2 === $f->term_id ) {
     2676                $this->assertSame( 2, $f->count, 'Check to see if term 2, has the correct count on second run' );
     2677            } else {
     2678                $this->assertSame( 1, $f->count, 'Check to see if term 3, has the correct count on second run' );
     2679            }
     2680        }
     2681    }
     2682
     2683    /**
    25932684     * @ticket 20635
    25942685     */
     
    30983189                    'taxonomy' => self::$taxonomy,
    30993190                    'fields'   => 'slugs',
    3100                 ),
    3101             ),
    3102             'meta cache off, pad count on  vs meta cache on, pad count off' => array(
    3103                 array(
    3104                     'taxonomy'               => self::$taxonomy,
    3105                     'pad_counts'             => true,
    3106                     'update_term_meta_cache' => false,
    3107                 ),
    3108                 array(
    3109                     'taxonomy' => self::$taxonomy,
    3110                     'fields'   => 'ids',
    31113191                ),
    31123192            ),
Note: See TracChangeset for help on using the changeset viewer.