Make WordPress Core


Ignore:
Timestamp:
02/11/2015 07:41:54 PM (10 years ago)
Author:
boonebgorges
Message:

Split shared taxonomy terms on term update.

When updating an existing taxonomy term that shares its term_id with
another term, we generate a new row in wp_terms and associate the updated
term_taxonomy_id with the new term. This separates the terms, such that
updating the name of one term does not change the name of any others.

In cases where a plugin or theme stores term IDs in the database, term splitting
can cause backward compatibility issues. The current changeset introduces
two utilities to aid developers with the transition. The 'split_shared_term'
action fires when the split takes place, and should be used to catch changes in
term_id. In cases where 'split_shared_term' cannot be used, the
wp_get_split_term() function gives developers access to data about terms
that have previously been split. Documentation for these functions, with
examples, can be found in the Plugin Developer Handbook. WordPress itself
stores term IDs in this way in two places; _wp_check_split_default_terms()
and _wp_check_split_terms_in_menus() are hooked to 'split_shared_term' to
perform the necessary cleanup.

See [30241] for a previous attempt at the split. It was reverted in [30585]
for 4.1.0.

Props boonebgorges, mboynes.
See #5809.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/term.php

    r31287 r31418  
    761761    }
    762762
     763    /**
     764     * @ticket 5809
     765     */
     766    public function test_wp_update_term_should_split_shared_term() {
     767        global $wpdb;
     768
     769        register_taxonomy( 'wptests_tax', 'post' );
     770        register_taxonomy( 'wptests_tax_2', 'post' );
     771
     772        $t1 = wp_insert_term( 'Foo', 'wptests_tax' );
     773        $t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
     774
     775        // Manually modify because split terms shouldn't naturally occur.
     776        $wpdb->update( $wpdb->term_taxonomy,
     777            array( 'term_id' => $t1['term_id'] ),
     778            array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
     779            array( '%d' ),
     780            array( '%d' )
     781        );
     782
     783        $posts = $this->factory->post->create_many( 2 );
     784        wp_set_object_terms( $posts[0], array( 'Foo' ), 'wptests_tax' );
     785        wp_set_object_terms( $posts[1], array( 'Foo' ), 'wptests_tax_2' );
     786
     787        // Verify that the terms are shared.
     788        $t1_terms = wp_get_object_terms( $posts[0], 'wptests_tax' );
     789        $t2_terms = wp_get_object_terms( $posts[1], 'wptests_tax_2' );
     790        $this->assertSame( $t1_terms[0]->term_id, $t2_terms[0]->term_id );
     791
     792        wp_update_term( $t2_terms[0]->term_id, 'wptests_tax_2', array(
     793            'name' => 'New Foo',
     794        ) );
     795
     796        $t1_terms = wp_get_object_terms( $posts[0], 'wptests_tax' );
     797        $t2_terms = wp_get_object_terms( $posts[1], 'wptests_tax_2' );
     798        $this->assertNotEquals( $t1_terms[0]->term_id, $t2_terms[0]->term_id );
     799    }
     800
     801    /**
     802     * @ticket 5809
     803     */
     804    public function test_wp_update_term_should_not_split_shared_term_before_410_schema_change() {
     805        global $wpdb;
     806
     807        $db_version = get_option( 'db_version' );
     808        update_option( 'db_version', 30055 );
     809
     810        register_taxonomy( 'wptests_tax', 'post' );
     811        register_taxonomy( 'wptests_tax_2', 'post' );
     812
     813        $t1 = wp_insert_term( 'Foo', 'wptests_tax' );
     814        $t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
     815
     816        // Manually modify because split terms shouldn't naturally occur.
     817        $wpdb->update( $wpdb->term_taxonomy,
     818            array( 'term_id' => $t1['term_id'] ),
     819            array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
     820            array( '%d' ),
     821            array( '%d' )
     822        );
     823
     824        $posts = $this->factory->post->create_many( 2 );
     825        wp_set_object_terms( $posts[0], array( 'Foo' ), 'wptests_tax' );
     826        wp_set_object_terms( $posts[1], array( 'Foo' ), 'wptests_tax_2' );
     827
     828        // Verify that the term is shared.
     829        $t1_terms = wp_get_object_terms( $posts[0], 'wptests_tax' );
     830        $t2_terms = wp_get_object_terms( $posts[1], 'wptests_tax_2' );
     831        $this->assertSame( $t1_terms[0]->term_id, $t2_terms[0]->term_id );
     832
     833        wp_update_term( $t2_terms[0]->term_id, 'wptests_tax_2', array(
     834            'name' => 'New Foo',
     835        ) );
     836
     837        // Term should still be shared.
     838        $t1_terms = wp_get_object_terms( $posts[0], 'wptests_tax' );
     839        $t2_terms = wp_get_object_terms( $posts[1], 'wptests_tax_2' );
     840        $this->assertSame( $t1_terms[0]->term_id, $t2_terms[0]->term_id );
     841
     842        update_option( 'db_version', $db_version );
     843    }
     844
    763845    public function test_wp_update_term_alias_of_no_term_group() {
    764846        register_taxonomy( 'wptests_tax', 'post' );
Note: See TracChangeset for help on using the changeset viewer.