WordPress.org

Make WordPress Core

Changeset 31792


Ignore:
Timestamp:
03/16/2015 11:15:34 AM (5 years ago)
Author:
boonebgorges
Message:

In wp_insert_term(), allow a term with an existing name if a unique $slug has been provided.

wp_insert_term() protects against the creation of terms with duplicate names
at the same level of a taxonomy hierarchy. However, it's historically been
possible to override this protection by explicitly providing a value of $slug
that is unique at the hierarchy tier. This ability was broken in [31734], and
the current changeset restores the original behavior.

A number of unit tests are added and refactored in support of these changes.

See #17689 for discussion of a fix that was superceded by [31734]. This commit
retains the fix for the underlying bug described in that ticket.

See #31328.

Location:
trunk
Files:
2 edited

Legend:

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

    r31734 r31792  
    29042904    }
    29052905
    2906     // Terms with duplicate names are not allowed at the same level of a taxonomy hierarchy.
    2907     if ( $existing_term = get_term_by( 'name', $name, $taxonomy ) ) {
    2908         if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    2909             $siblings = get_terms( $taxonomy, array( 'fields' => 'names', 'get' => 'all', 'parent' => $parent ) );
    2910             if ( in_array( $name, $siblings ) ) {
    2911                 return new WP_Error( 'term_exists', __( 'A term with the name already exists with this parent.' ), $existing_term->term_id );
     2906    /*
     2907     * Prevent the creation of terms with duplicate names at the same level of a taxonomy hierarchy,
     2908     * unless a unique slug has been explicitly provided.
     2909     */
     2910    if ( $name_match = get_term_by( 'name', $name, $taxonomy ) ) {
     2911        $slug_match = get_term_by( 'slug', $slug, $taxonomy );
     2912        if ( ! $slug_provided || $name_match->slug === $slug || $slug_match ) {
     2913            if ( is_taxonomy_hierarchical( $taxonomy ) ) {
     2914                $siblings = get_terms( $taxonomy, array( 'get' => 'all', 'parent' => $parent ) );
     2915
     2916                $existing_term = null;
     2917                if ( $name_match->slug === $slug && in_array( $name, wp_list_pluck( $siblings, 'name' ) ) ) {
     2918                    $existing_term = $name_match;
     2919                } elseif ( $slug_match && in_array( $slug, wp_list_pluck( $siblings, 'slug' ) ) ) {
     2920                    $existing_term = $slug_match;
     2921                }
     2922
     2923                if ( $existing_term ) {
     2924                    return new WP_Error( 'term_exists', __( 'A term with the name already exists with this parent.' ), $existing_term->term_id );
     2925                }
     2926            } else {
     2927                return new WP_Error( 'term_exists', __( 'A term with the name already exists in this taxonomy.' ), $name_match->term_id );
    29122928            }
    2913         } else {
    2914             return new WP_Error( 'term_exists', __( 'A term with the name already exists in this taxonomy.' ), $existing_term->term_id );
    29152929        }
    29162930    }
  • trunk/tests/phpunit/tests/term.php

    r31734 r31792  
    175175        // Test existing term name with unique slug
    176176        $term1 = $this->factory->tag->create( array( 'name' => 'Bozo', 'slug' => 'bozo1' ) );
    177         $this->assertTrue( is_wp_error( $term1 ) );
    178         $this->assertSame( 'term_exists', $term1->get_error_code() );
    179         $this->assertEquals( $term->term_id, $term1->get_error_data() );
     177        $this->assertFalse( is_wp_error( $term1 ) );
    180178
    181179        // Test an existing term name
     
    229227
    230228    /**
     229     * @ticket 31328
     230     */
     231    public function test_wp_insert_term_should_not_allow_duplicate_names_when_slug_is_a_duplicate_of_the_same_term_in_non_hierarchical_taxonomy() {
     232        register_taxonomy( 'wptests_tax', 'post' );
     233        $t1 = $this->factory->term->create( array(
     234            'name' => 'Foo',
     235            'slug' => 'foo',
     236            'taxonomy' => 'wptests_tax',
     237        ) );
     238
     239        $t2 = wp_insert_term( 'Foo', 'wptests_tax', array(
     240            'slug' => 'foo',
     241        ) );
     242
     243        $this->assertWPError( $t2 );
     244        $this->assertSame( 'term_exists', $t2->get_error_code() );
     245    }
     246
     247    /**
     248     * @ticket 31328
     249     */
     250    public function test_wp_insert_term_should_not_allow_duplicate_names_when_slug_is_a_duplicate_of_a_different_term_in_non_hierarchical_taxonomy() {
     251        register_taxonomy( 'wptests_tax', 'post' );
     252        $t1 = $this->factory->term->create( array(
     253            'name' => 'Foo',
     254            'slug' => 'foo',
     255            'taxonomy' => 'wptests_tax',
     256        ) );
     257
     258        $t2 = $this->factory->term->create( array(
     259            'name' => 'Bar',
     260            'slug' => 'bar',
     261            'taxonomy' => 'wptests_tax',
     262        ) );
     263
     264        $t3 = wp_insert_term( 'Foo', 'wptests_tax', array(
     265            'slug' => 'bar',
     266        ) );
     267
     268        $this->assertWPError( $t3 );
     269        $this->assertSame( 'term_exists', $t3->get_error_code() );
     270    }
     271
     272    /**
     273     * @ticket 31328
     274     */
     275    public function test_wp_insert_term_should_allow_duplicate_names_when_a_unique_slug_has_been_provided_in_non_hierarchical_taxonomy() {
     276        register_taxonomy( 'wptests_tax', 'post' );
     277        $t1 = $this->factory->term->create( array(
     278            'name' => 'Foo',
     279            'slug' => 'foo',
     280            'taxonomy' => 'wptests_tax',
     281        ) );
     282
     283        $t2 = wp_insert_term( 'Foo', 'wptests_tax', array(
     284            'slug' => 'foo-unique',
     285        ) );
     286
     287        $this->assertFalse( is_wp_error( $t2 ) );
     288
     289        $t2_term = get_term( $t2['term_id'], 'wptests_tax' );
     290        $this->assertSame( 'foo-unique', $t2_term->slug );
     291        $this->assertSame( 'Foo', $t2_term->name );
     292    }
     293
     294    /**
     295     * @ticket 31328
     296     */
     297    public function test_wp_insert_term_should_not_allow_duplicate_names_when_the_slug_is_not_provided_in_non_hierarchical_taxonomy() {
     298        register_taxonomy( 'wptests_tax', 'post' );
     299        $t1 = $this->factory->term->create( array(
     300            'name' => 'Foo',
     301            'slug' => 'foo',
     302            'taxonomy' => 'wptests_tax',
     303        ) );
     304
     305        $t2 = wp_insert_term( 'Foo', 'wptests_tax' );
     306
     307        $this->assertWPError( $t2 );
     308        $this->assertSame( 'term_exists', $t2->get_error_code() );
     309    }
     310
     311    /**
     312     * @ticket 31328
     313     */
     314    public function test_wp_insert_term_should_not_allow_duplicate_names_when_slug_is_a_duplicate_of_the_same_term_in_hierarchical_taxonomy() {
     315        register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
     316        $t1 = $this->factory->term->create( array(
     317            'name' => 'Foo',
     318            'slug' => 'foo',
     319            'taxonomy' => 'wptests_tax',
     320        ) );
     321
     322        $t2 = wp_insert_term( 'Foo', 'wptests_tax', array(
     323            'slug' => 'foo',
     324        ) );
     325
     326        $this->assertWPError( $t2 );
     327        $this->assertSame( 'term_exists', $t2->get_error_code() );
     328    }
     329
     330    /**
     331     * @ticket 31328
     332     */
     333    public function test_wp_insert_term_should_not_allow_duplicate_names_when_slug_is_a_duplicate_of_a_different_term_at_same_hierarchy_level_in_hierarchical_taxonomy() {
     334        register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
     335        $t1 = $this->factory->term->create( array(
     336            'name' => 'Foo',
     337            'slug' => 'foo',
     338            'taxonomy' => 'wptests_tax',
     339        ) );
     340
     341        $t2 = $this->factory->term->create( array(
     342            'name' => 'Bar',
     343            'slug' => 'bar',
     344            'taxonomy' => 'wptests_tax',
     345        ) );
     346
     347        $t3 = wp_insert_term( 'Foo', 'wptests_tax', array(
     348            'slug' => 'bar',
     349        ) );
     350
     351        $this->assertWPError( $t3 );
     352        $this->assertSame( 'term_exists', $t3->get_error_code() );
     353    }
     354
     355    /**
     356     * @ticket 31328
     357     */
     358    public function test_wp_insert_term_should_allow_duplicate_names_when_slug_is_a_duplicate_of_a_term_at_different_hierarchy_level_in_hierarchical_taxonomy() {
     359        register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
     360        $t1 = $this->factory->term->create( array(
     361            'name' => 'Foo',
     362            'slug' => 'foo',
     363            'taxonomy' => 'wptests_tax',
     364        ) );
     365
     366        $t2 = $this->factory->term->create();
     367
     368        $t3 = $this->factory->term->create( array(
     369            'name' => 'Bar',
     370            'slug' => 'bar',
     371            'parent' => $t2,
     372            'taxonomy' => 'wptests_tax',
     373        ) );
     374
     375        $t4 = wp_insert_term( 'Foo', 'wptests_tax', array(
     376            'slug' => 'bar',
     377        ) );
     378
     379        $this->assertFalse( is_wp_error( $t4 ) );
     380        $t4_term = get_term( $t4['term_id'], 'wptests_tax' );
     381
     382        // `wp_unique_term_slug()` allows term creation but iterates the slug.
     383        $this->assertSame( 'bar-2', $t4_term->slug );
     384        $this->assertSame( 'Foo', $t4_term->name );
     385    }
     386
     387    /**
     388     * @ticket 31328
     389     */
     390    public function test_wp_insert_term_should_allow_duplicate_names_when_a_unique_slug_has_been_provided_in_hierarchical_taxonomy() {
     391        register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
     392        $t1 = $this->factory->term->create( array(
     393            'name' => 'Foo',
     394            'slug' => 'foo',
     395            'taxonomy' => 'wptests_tax',
     396        ) );
     397
     398        $t2 = wp_insert_term( 'Foo', 'wptests_tax', array(
     399            'slug' => 'foo-unique',
     400        ) );
     401
     402        $this->assertFalse( is_wp_error( $t2 ) );
     403
     404        $t2_term = get_term( $t2['term_id'], 'wptests_tax' );
     405        $this->assertSame( 'foo-unique', $t2_term->slug );
     406        $this->assertSame( 'Foo', $t2_term->name );
     407    }
     408
     409    /**
     410     * @ticket 31328
     411     */
     412    public function test_wp_insert_term_should_not_allow_duplicate_names_when_the_slug_is_not_provided_in_hierarchical_taxonomy() {
     413        register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
     414        $t1 = $this->factory->term->create( array(
     415            'name' => 'Foo',
     416            'slug' => 'foo',
     417            'taxonomy' => 'wptests_tax',
     418        ) );
     419
     420        $t2 = wp_insert_term( 'Foo', 'wptests_tax' );
     421
     422        $this->assertWPError( $t2 );
     423        $this->assertSame( 'term_exists', $t2->get_error_code() );
     424    }
     425    /**
    231426     * @ticket 5809
    232427     */
     
    369564
    370565        $this->assertSame( 0, $created_term->term_group );
    371     }
    372 
    373     public function test_wp_insert_term_duplicate_name_slug_non_hierarchical() {
    374         register_taxonomy( 'foo', 'post', array() );
    375 
    376         $existing_term = $this->factory->term->create( array(
    377             'slug' => 'new-term',
    378             'name' => 'New Term',
    379             'taxonomy' => 'foo',
    380         ) );
    381 
    382         $found = wp_insert_term( 'New Term', 'foo', array(
    383             'slug' => 'new-term',
    384         ) );
    385 
    386         _unregister_taxonomy( 'foo' );
    387 
    388         $this->assertTrue( is_wp_error( $found ) );
    389         $this->assertEquals( $existing_term, $found->get_error_data() );
    390     }
    391 
    392     public function test_wp_insert_term_duplicate_name_hierarchical() {
    393         register_taxonomy( 'foo', 'post', array(
    394             'hierarchical' => true,
    395         ) );
    396 
    397         $parent_term = $this->factory->term->create( array(
    398             'taxonomy' => 'foo',
    399         ) );
    400 
    401         $existing_term = $this->factory->term->create( array(
    402             'name' => 'New Term',
    403             'taxonomy' => 'foo',
    404             'parent' => $parent_term,
    405         ) );
    406 
    407         $found = wp_insert_term( 'New Term', 'foo', array(
    408             'parent' => $parent_term,
    409         ) );
    410 
    411         _unregister_taxonomy( 'foo' );
    412 
    413         $this->assertTrue( is_wp_error( $found ) );
    414         $this->assertEquals( $existing_term, $found->get_error_data() );
    415     }
    416 
    417     public function test_wp_insert_term_duplicate_name_slug_hierarchical() {
    418         register_taxonomy( 'foo', 'post', array(
    419             'hierarchical' => true,
    420         ) );
    421 
    422         $parent_term = $this->factory->term->create( array(
    423             'taxonomy' => 'foo',
    424         ) );
    425 
    426         $existing_term = $this->factory->term->create( array(
    427             'name' => 'New Term',
    428             'slug' => 'new-term-slug',
    429             'taxonomy' => 'foo',
    430             'parent' => $parent_term,
    431         ) );
    432 
    433         $found = wp_insert_term( 'New Term', 'foo', array(
    434             'parent' => $parent_term,
    435             'slug' => 'new-term-slug',
    436         ) );
    437 
    438         _unregister_taxonomy( 'foo' );
    439 
    440         $this->assertTrue( is_wp_error( $found ) );
    441         $this->assertEquals( $existing_term, $found->get_error_data() );
    442566    }
    443567
Note: See TracChangeset for help on using the changeset viewer.