Make WordPress Core

Changeset 31276


Ignore:
Timestamp:
01/25/2015 02:45:11 AM (12 years ago)
Author:
boonebgorges
Message:

In get_terms(), check hierarchy for all $taxonomies before bailing early from 'parent' or 'child_of'.

There is a pre-check in get_terms() that prevents an unnecessary database
query if the 'parent' or 'child_of' parameter is not found in the cached term
hierarchy (since a term without an index in the hierarchy cache has no
descendants). Previously, only the first item in the $taxonomies array was
being checked, with the result that an empty array was being erroneously
returned in cases where the 'parent' or 'child_of' term is in a subsequent
taxonomy.

See #31118.

Location:
trunk
Files:
2 edited

Legend:

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

    r31275 r31276  
    16581658        $args = apply_filters( 'get_terms_args', $args, $taxonomies );
    16591659
     1660        // Avoid the query if the queried parent/child_of term has no descendants.
    16601661        $child_of = $args['child_of'];
     1662        $parent   = $args['parent'];
     1663
    16611664        if ( $child_of ) {
    1662                 $hierarchy = _get_term_hierarchy( reset( $taxonomies ) );
    1663                 if ( ! isset( $hierarchy[ $child_of ] ) ) {
    1664                         return $empty_array;
    1665                 }
    1666         }
    1667 
    1668         $parent = $args['parent'];
    1669         if ( $parent ) {
    1670                 $hierarchy = _get_term_hierarchy( reset( $taxonomies ) );
    1671                 if ( ! isset( $hierarchy[ $parent ] ) ) {
     1665                $_parent = $child_of;
     1666        } elseif ( $parent ) {
     1667                $_parent = $parent;
     1668        } else {
     1669                $_parent = false;
     1670        }
     1671
     1672        if ( $_parent ) {
     1673                $in_hierarchy = false;
     1674                foreach ( $taxonomies as $_tax ) {
     1675                        $hierarchy = _get_term_hierarchy( $_tax );
     1676
     1677                        if ( isset( $hierarchy[ $_parent ] ) ) {
     1678                                $in_hierarchy = true;
     1679                        }
     1680                }
     1681
     1682                if ( ! $in_hierarchy ) {
    16721683                        return $empty_array;
    16731684                }
     
    19431954
    19441955        if ( $child_of ) {
    1945                 $children = _get_term_hierarchy( reset( $taxonomies ) );
    1946                 if ( ! empty( $children ) ) {
    1947                         $terms = _get_term_children( $child_of, $terms, reset( $taxonomies ) );
     1956                foreach ( $taxonomies as $_tax ) {
     1957                        $children = _get_term_hierarchy( $_tax );
     1958                        if ( ! empty( $children ) ) {
     1959                                $terms = _get_term_children( $child_of, $terms, $_tax );
     1960                        }
    19481961                }
    19491962        }
  • trunk/tests/phpunit/tests/term/getTerms.php

    r31275 r31276  
    375375                $terms = get_terms( 'category', array( 'child_of' => $parent, 'hide_empty' => false ) );
    376376                $this->assertEquals( 1, count( $terms ) );
     377        }
     378
     379        /**
     380         * @ticket 31118
     381         */
     382        public function test_child_of_should_skip_query_when_specified_parent_is_not_found_in_hierarchy_cache() {
     383                global $wpdb;
     384
     385                register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true, ) );
     386
     387                $terms = $this->factory->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     388
     389                $num_queries = $wpdb->num_queries;
     390
     391                $found = get_terms( 'wptests_tax', array(
     392                        'hide_empty' => false,
     393                        'child_of' => $terms[0],
     394                ) );
     395
     396                $this->assertEmpty( $found );
     397                $this->assertSame( $num_queries, $wpdb->num_queries );
     398        }
     399
     400        /**
     401         * @ticket 31118
     402         */
     403        public function test_child_of_should_respect_multiple_taxonomies() {
     404                register_taxonomy( 'wptests_tax1', 'post', array( 'hierarchical' => true ) );
     405                register_taxonomy( 'wptests_tax2', 'post', array( 'hierarchical' => true ) );
     406
     407                $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     408                $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     409                $t3 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2', 'parent' => $t2 ) );
     410
     411                $found = get_terms( array( 'wptests_tax1', 'wptests_tax2' ), array(
     412                        'fields' => 'ids',
     413                        'hide_empty' => false,
     414                        'child_of' => $t2,
     415                ) );
     416
     417                $this->assertEqualSets( array( $t3 ), $found );
    377418        }
    378419
     
    11571198        }
    11581199
     1200        /**
     1201         * @ticket 31118
     1202         */
     1203        public function test_parent_should_skip_query_when_specified_parent_is_not_found_in_hierarchy_cache() {
     1204                global $wpdb;
     1205
     1206                register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true, ) );
     1207
     1208                $terms = $this->factory->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
     1209
     1210                $num_queries = $wpdb->num_queries;
     1211
     1212                $found = get_terms( 'wptests_tax', array(
     1213                        'hide_empty' => false,
     1214                        'parent' => $terms[0],
     1215                ) );
     1216
     1217                $this->assertEmpty( $found );
     1218                $this->assertSame( $num_queries, $wpdb->num_queries );
     1219        }
     1220
     1221        /**
     1222         * @ticket 31118
     1223         */
     1224        public function test_parent_should_respect_multiple_taxonomies() {
     1225                register_taxonomy( 'wptests_tax1', 'post', array( 'hierarchical' => true ) );
     1226                register_taxonomy( 'wptests_tax2', 'post', array( 'hierarchical' => true ) );
     1227
     1228                $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     1229                $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     1230                $t3 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2', 'parent' => $t2 ) );
     1231
     1232                $found = get_terms( array( 'wptests_tax1', 'wptests_tax2' ), array(
     1233                        'fields' => 'ids',
     1234                        'hide_empty' => false,
     1235                        'parent' => $t2,
     1236                ) );
     1237
     1238                $this->assertEqualSets( array( $t3 ), $found );
     1239        }
     1240
    11591241        public function test_hierarchical_false_parent_should_override_child_of() {
    11601242                $initial_terms = $this->create_hierarchical_terms();
Note: See TracChangeset for help on using the changeset viewer.