Make WordPress Core

Changeset 53496 for trunk


Ignore:
Timestamp:
06/14/2022 11:41:33 AM (4 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.