Make WordPress Core

Changeset 30240


Ignore:
Timestamp:
11/05/2014 01:41:58 AM (12 years ago)
Author:
boonebgorges
Message:

Do not create shared taxonomy terms.

A "shared" term occurs when two entries in the wp_term_taxonomy table share a
single term_id, and thereby correspond to the same row in wp_terms. This
changeset stops the practice of creating shared terms: each new row in
wp_term_taxonomy will receive its own row in wp_terms. The new strategy
for term creation depends on whether the installation's database schema is up
to date for 4.1:

  • If so, terms are allowed to be created with the same slug as an existing term, as long as they are in different taxonomies and do not share a parent. Thus, a new tag with the slug 'wordpress' can exist alongside a category with the slug 'wordpress'.
  • If not, new terms will be forced to have unique slugs. Thus, on an installation containing a category with the slug 'wordpress', a new tag 'WordPress' will get the slug 'wordpress-2'.

Fixes #21950. See #5809.

Location:
trunk
Files:
2 edited

Legend:

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

    r30239 r30240  
    28462846        }
    28472847
    2848         if ( $term_id = term_exists($slug) ) {
    2849                 $existing_term = $wpdb->get_row( $wpdb->prepare( "SELECT name FROM $wpdb->terms WHERE term_id = %d", $term_id), ARRAY_A );
    2850                 // We've got an existing term in the same taxonomy, which matches the name of the new term:
    2851                 if ( is_taxonomy_hierarchical($taxonomy) && $existing_term['name'] == $name && $exists = term_exists( (int) $term_id, $taxonomy ) ) {
    2852                         // Hierarchical, and it matches an existing term, Do not allow same "name" in the same level.
    2853                         $siblings = get_terms($taxonomy, array('fields' => 'names', 'get' => 'all', 'parent' => $parent ) );
    2854                         if ( in_array($name, $siblings) ) {
    2855                                 if ( $slug_provided ) {
    2856                                         return new WP_Error( 'term_exists', __( 'A term with the name and slug provided already exists with this parent.' ), $exists['term_id'] );
    2857                                 } else {
    2858                                         return new WP_Error( 'term_exists', __( 'A term with the name provided already exists with this parent.' ), $exists['term_id'] );
     2848        // Terms with duplicate names are not allowed at the same level of a taxonomy hierarchy.
     2849        if ( $exists = term_exists( $slug, $taxonomy ) ) {
     2850                $existing_term = get_term( $exists['term_id'], $taxonomy );
     2851
     2852                if ( $name === $existing_term->name ) {
     2853
     2854                        if ( is_taxonomy_hierarchical( $taxonomy ) ) {
     2855                                $siblings = get_terms( $taxonomy, array( 'fields' => 'names', 'get' => 'all', 'parent' => $parent ) );
     2856                                if ( in_array( $name, $siblings ) ) {
     2857                                        return new WP_Error( 'term_exists', __( 'A term with the name and slug already exists with this parent.' ), $exists['term_id'] );
    28592858                                }
     2859
    28602860                        } else {
    2861                                 $slug = wp_unique_term_slug($slug, (object) $args);
    2862                                 if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) {
    2863                                         return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error);
    2864                                 }
    2865                                 $term_id = (int) $wpdb->insert_id;
     2861                                return new WP_Error( 'term_exists', __( 'A term with the name and slug already exists in this taxonomy.' ), $exists['term_id'] );
    28662862                        }
    2867                 } elseif ( $existing_term['name'] != $name ) {
    2868                         // We've got an existing term, with a different name, Create the new term.
    2869                         $slug = wp_unique_term_slug($slug, (object) $args);
    2870                         if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) {
    2871                                 return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error);
    2872                         }
    2873                         $term_id = (int) $wpdb->insert_id;
    2874                 } elseif ( $exists = term_exists( (int) $term_id, $taxonomy ) )  {
    2875                         // Same name, same slug.
    2876                         return new WP_Error( 'term_exists', __( 'A term with the name and slug provided already exists.' ), $exists['term_id'] );
    2877                 }
    2878         } else {
    2879                 // This term does not exist at all in the database, Create it.
    2880                 $slug = wp_unique_term_slug($slug, (object) $args);
    2881                 if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) {
    2882                         return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error);
    2883                 }
    2884                 $term_id = (int) $wpdb->insert_id;
    2885         }
     2863                }
     2864        }
     2865
     2866        $slug = wp_unique_term_slug( $slug, (object) $args );
     2867
     2868        if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) {
     2869                return new WP_Error( 'db_insert_error', __( 'Could not insert term into the database' ), $wpdb->last_error );
     2870        }
     2871
     2872        $term_id = (int) $wpdb->insert_id;
    28862873
    28872874        // Seems unreachable, However, Is used in the case that a term name is provided, which sanitizes to an empty string.
     
    32303217        if ( ! term_exists( $slug ) )
    32313218                return $slug;
     3219
     3220        // As of 4.1, duplicate slugs are allowed as long as they're in different taxonomies.
     3221        if ( get_option( 'db_version' ) >= 30133 && ! get_term_by( 'slug', $slug, $term->taxonomy ) ) {
     3222                return $slug;
     3223        }
    32323224
    32333225        // If the taxonomy supports hierarchy and the term has a parent, make the slug unique
  • trunk/tests/phpunit/tests/term.php

    r30118 r30240  
    227227        }
    228228
     229        /**
     230         * @ticket 5809
     231         */
     232        public function test_wp_insert_term_duplicate_slug_same_taxonomy() {
     233                register_taxonomy( 'wptests_tax', 'post' );
     234                $t = $this->factory->term->create( array(
     235                        'name' => 'Foo',
     236                        'slug' => 'foo',
     237                        'taxonomy' => 'wptests_tax',
     238                ) );
     239
     240                $term = get_term( $t, 'wptests_tax' );
     241
     242                $created = wp_insert_term( 'Foo 2', 'wptests_tax', array(
     243                        'slug' => 'foo',
     244                ) );
     245
     246                $created_term = get_term( $created['term_id'], 'wptests_tax' );
     247                $this->assertSame( 'foo-2', $created_term->slug );
     248
     249                _unregister_taxonomy( 'wptests_tax', 'post' );
     250        }
     251
     252        /**
     253         * @ticket 5809
     254         */
     255        public function test_wp_insert_term_duplicate_slug_different_taxonomy() {
     256                register_taxonomy( 'wptests_tax', 'post' );
     257                register_taxonomy( 'wptests_tax_2', 'post' );
     258                $t = $this->factory->term->create( array(
     259                        'name' => 'Foo',
     260                        'slug' => 'foo',
     261                        'taxonomy' => 'wptests_tax',
     262                ) );
     263
     264                $term = get_term( $t, 'wptests_tax' );
     265
     266                $created = wp_insert_term( 'Foo 2', 'wptests_tax_2', array(
     267                        'slug' => 'foo',
     268                ) );
     269
     270                $this->assertFalse( is_wp_error( $created ) );
     271
     272                $new_term = get_term( $created['term_id'], 'wptests_tax_2' );
     273
     274                $this->assertSame( 'foo', $new_term->slug );
     275
     276                _unregister_taxonomy( 'wptests_tax', 'post' );
     277        }
     278
     279        /**
     280         * @ticket 5809
     281         */
     282        public function test_wp_insert_term_duplicate_slug_different_taxonomy_before_410_schema_change() {
     283
     284                $db_version = get_option( 'db_version' );
     285                update_option( 'db_version', 30055 );
     286
     287                register_taxonomy( 'wptests_tax', 'post' );
     288                register_taxonomy( 'wptests_tax_2', 'post' );
     289                $t = $this->factory->term->create( array(
     290                        'name' => 'Foo',
     291                        'slug' => 'foo',
     292                        'taxonomy' => 'wptests_tax',
     293                ) );
     294
     295                $term = get_term( $t, 'wptests_tax' );
     296
     297                $created = wp_insert_term( 'Foo 2', 'wptests_tax_2', array(
     298                        'slug' => 'foo',
     299                ) );
     300
     301                $this->assertFalse( is_wp_error( $created ) );
     302
     303                $new_term = get_term( $created['term_id'], 'wptests_tax_2' );
     304
     305                /*
     306                 * As of 4.1, we no longer create a shared term, but we also do not
     307                 * allow for duplicate slugs.
     308                 */
     309                $this->assertSame( 'foo-2', $new_term->slug );
     310                $this->assertNotEquals( $new_term->term_id, $term->term_id );
     311
     312                _unregister_taxonomy( 'wptests_tax', 'post' );
     313                update_option( 'db_version', $db_version );
     314        }
     315
    229316        public function test_wp_insert_term_alias_of_no_term_group() {
    230317                register_taxonomy( 'wptests_tax', 'post' );
     
    352439                $this->assertTrue( is_wp_error( $found ) );
    353440                $this->assertEquals( $existing_term, $found->get_error_data() );
     441        }
     442
     443        /**
     444         * @ticket 5809
     445         */
     446        public function test_wp_insert_term_should_not_create_shared_term() {
     447                register_taxonomy( 'wptests_tax', 'post' );
     448                register_taxonomy( 'wptests_tax_2', 'post' );
     449
     450                $t1 = wp_insert_term( 'Foo', 'wptests_tax' );
     451                $t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
     452
     453                $this->assertNotEquals( $t1['term_id'], $t2['term_id'] );
    354454        }
    355455
Note: See TracChangeset for help on using the changeset viewer.