WordPress.org

Make WordPress Core

Changeset 31275


Ignore:
Timestamp:
01/24/2015 06:47:30 PM (6 years ago)
Author:
boonebgorges
Message:

Introduce 'childless' parameter to get_terms().

This new parameter allows developers to limit queried terms to terminal nodes -
ie, those without any descendants.

As part of the improvement, some internal logic in get_terms() has been
consolidated. Parameters that resolve to a NOT IN clause containing term IDs
('exclude', 'exclude_tree', and 'childless') are now parsed into a single
"exclusions" array before the SQL clause is generated.

Props theMikeD, horike.
Fixes #29839.

Location:
trunk
Files:
2 edited

Legend:

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

    r31270 r31275  
    15481548 *
    15491549 * @since 2.3.0
    1550  * @since 4.2.0 Introduced 'name' parameter.
     1550 * @since 4.2.0 Introduced 'name' and 'childless' parameters.
    15511551 *
    15521552 * @global wpdb $wpdb WordPress database abstraction object.
     
    15961596 *                                           are passed, $child_of is ignored. Default 0.
    15971597 *     @type int|string   $parent            Parent term ID to retrieve direct-child terms of. Default empty.
     1598 *     @type bool         $childless         True to limit results to terms that have no children. This parameter has
     1599 *                                           no effect on non-hierarchical taxonomies. Default false.
    15981600 *     @type string       $cache_domain      Unique cache key to be produced when this query is stored in an
    15991601 *                                           object cache. Default is 'core'.
     
    16201622    $defaults = array('orderby' => 'name', 'order' => 'ASC',
    16211623        'hide_empty' => true, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(),
    1622         'number' => '', 'fields' => 'all', 'name' => '', 'slug' => '', 'parent' => '',
     1624        'number' => '', 'fields' => 'all', 'name' => '', 'slug' => '', 'parent' => '', 'childless' => false,
    16231625        'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'description__like' => '',
    16241626        'pad_counts' => false, 'offset' => '', 'search' => '', 'cache_domain' => 'core' );
     
    16391641
    16401642    if ( 'all' == $args['get'] ) {
     1643        $args['childless'] = false;
    16411644        $args['child_of'] = 0;
    16421645        $args['hide_empty'] = 0;
     
    17551758    }
    17561759
     1760    $exclusions = array();
    17571761    if ( ! empty( $exclude_tree ) ) {
    17581762        $exclude_tree = wp_parse_id_list( $exclude_tree );
     
    17641768            );
    17651769        }
    1766         $exclusions = implode( ',', array_map( 'intval', $excluded_children ) );
    1767     } else {
    1768         $exclusions = '';
     1770        $exclusions = array_merge( $excluded_children, $exclusions );
    17691771    }
    17701772
    17711773    if ( ! empty( $exclude ) ) {
    1772         $exterms = wp_parse_id_list( $exclude );
    1773         if ( empty( $exclusions ) ) {
    1774             $exclusions = implode( ',', $exterms );
    1775         } else {
    1776             $exclusions .= ', ' . implode( ',', $exterms );
     1774        $exclusions = array_merge( wp_parse_id_list( $exclude ), $exclusions );
     1775    }
     1776
     1777    // 'childless' terms are those without an entry in the flattened term hierarchy.
     1778    $childless = (bool) $args['childless'];
     1779    if ( $childless ) {
     1780        foreach ( $taxonomies as $_tax ) {
     1781            $term_hierarchy = _get_term_hierarchy( $_tax );
     1782            $exclusions = array_merge( array_keys( $term_hierarchy ), $exclusions );
    17771783        }
    17781784    }
    17791785
    17801786    if ( ! empty( $exclusions ) ) {
    1781         $exclusions = ' AND t.term_id NOT IN (' . $exclusions . ')';
     1787        $exclusions = ' AND t.term_id NOT IN (' . implode( ',', array_map( 'intval', $exclusions ) ) . ')';
    17821788    }
    17831789
  • trunk/tests/phpunit/tests/term/getTerms.php

    r31248 r31275  
    494494
    495495        $this->assertEqualSets( array( $t3, $t1 ), $found );
     496    }
     497
     498    /**
     499     * @ticket 29839
     500     */
     501    public function test_childless_should_return_all_terms_for_flat_hierarchy() {
     502        // If run on a flat hierarchy it should return everything.
     503        $flat_tax = 'countries';
     504        register_taxonomy( $flat_tax, 'post', array( 'hierarchical' => false ) );
     505        $australia = $this->factory->term->create( array( 'name' => 'Australia', 'taxonomy' => $flat_tax ) );
     506        $china     = $this->factory->term->create( array( 'name' => 'China',     'taxonomy' => $flat_tax ) );
     507        $tanzania  =  $this->factory->term->create( array( 'name' => 'Tanzania',  'taxonomy' => $flat_tax ) );
     508
     509        $terms = get_terms( $flat_tax, array(
     510            'childless' => true,
     511            'hide_empty' => false,
     512            'fields' => 'ids',
     513        ) );
     514
     515        $expected = array( $australia, $china, $tanzania );
     516        $this->assertEqualSets( $expected, $terms );
     517    }
     518
     519
     520    /**
     521     * @ticket 29839
     522     */
     523    public function test_childless_hierarchical_taxonomy() {
     524        $tax = 'location';
     525        register_taxonomy( $tax, 'post', array( 'hierarchical' => true ) );
     526        /*
     527        Canada
     528            Ontario
     529                Ottawa
     530                    Nepean
     531                Toronto
     532            Quebec
     533                Montreal
     534            PEI
     535        */
     536        // Level 1
     537        $canada = $this->factory->term->create( array( 'name' => 'Canada', 'taxonomy' => $tax ) );
     538
     539        // Level 2
     540        $ontario = $this->factory->term->create( array( 'name' => 'Ontario', 'parent' => $canada, 'taxonomy' => $tax ) );
     541        $quebec  = $this->factory->term->create( array( 'name' => 'Quebec', 'parent' => $canada, 'taxonomy' => $tax ) );
     542        $pei     = $this->factory->term->create( array( 'name' => 'PEI', 'parent' => $canada, 'taxonomy' => $tax ) );
     543
     544        // Level 3
     545        $toronto  = $this->factory->term->create( array( 'name' => 'Toronto', 'parent' => $ontario, 'taxonomy' => $tax ) );
     546        $ottawa   = $this->factory->term->create( array( 'name' => 'Ottawa', 'parent' => $ontario, 'taxonomy' => $tax ) );
     547        $montreal = $this->factory->term->create( array( 'name' => 'Montreal', 'parent' => $quebec, 'taxonomy' => $tax ) );
     548
     549        // Level 4
     550        $nepean = $this->factory->term->create( array( 'name' => 'Nepean', 'parent' => $ottawa, 'taxonomy' => $tax ) );
     551
     552        $terms = get_terms( $tax, array(
     553            'childless' => true,
     554            'hide_empty' => false,
     555            'fields' => 'ids',
     556        ) );
     557
     558        $this->assertEqualSets( array( $montreal, $nepean, $toronto, $pei ), $terms );
     559    }
     560
     561    /**
     562     * @ticket 29839
     563     */
     564    public function test_childless_hierarchical_taxonomy_used_with_child_of() {
     565        $tax = 'location';
     566        register_taxonomy( $tax, 'post', array( 'hierarchical' => true ) );
     567
     568        // Level 1
     569        $canada = $this->factory->term->create( array( 'name' => 'Canada', 'taxonomy' => $tax ) );
     570
     571        // Level 2
     572        $ontario = $this->factory->term->create( array( 'name' => 'Ontario', 'parent' => $canada, 'taxonomy' => $tax ) );
     573        $quebec  = $this->factory->term->create( array( 'name' => 'Quebec', 'parent' => $canada, 'taxonomy' => $tax ) );
     574
     575        // Level 3
     576        $laval   = $this->factory->term->create( array( 'name' => 'Laval', 'parent' => $quebec, 'taxonomy' => $tax ) );
     577        $montreal = $this->factory->term->create( array( 'name' => 'Montreal', 'parent' => $quebec, 'taxonomy' => $tax ) );
     578
     579        // Level 4
     580        $dorval = $this->factory->term->create( array( 'name' => 'Dorval', 'parent' => $montreal, 'taxonomy' => $tax ) );
     581
     582        $terms = get_terms( $tax, array(
     583            'childless' => true,
     584            'child_of' => $quebec,
     585            'hide_empty' => false,
     586            'fields' => 'ids',
     587        ) );
     588
     589        $this->assertEqualSets( array( $laval ), $terms );
     590    }
     591
     592    /**
     593     * @ticket 29839
     594     */
     595    public function test_childless_should_enforce_childless_status_for_all_queried_taxonomies() {
     596        register_taxonomy( 'wptests_tax1', 'post', array( 'hierarchical' => true ) );
     597        register_taxonomy( 'wptests_tax2', 'post', array( 'hierarchical' => true ) );
     598
     599        $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     600        $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1', 'parent' => $t1 ) );
     601        $t3 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     602        $t4 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2', 'parent' => $t3 ) );
     603
     604        $found = get_terms( array( 'wptests_tax1', 'wptests_tax2' ), array(
     605            'fields' => 'ids',
     606            'hide_empty' => false,
     607            'childless' => true,
     608        ) );
     609
     610        $this->assertEqualSets( array( $t2, $t4 ), $found );
    496611    }
    497612
Note: See TracChangeset for help on using the changeset viewer.