Make WordPress Core

Changeset 31276


Ignore:
Timestamp:
01/25/2015 02:45:11 AM (10 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.