wordpress-develop/tests/phpunit/tests/term/splitSharedTerm.php
Boone Gorges ed639b408a 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.

git-svn-id: https://develop.svn.wordpress.org/trunk@31418 602fd350-edb4-49c9-b593-d223f7449a82
2015-02-11 19:41:54 +00:00

214 lines
6.9 KiB
PHP

<?php
/**
* @group taxonomy
*/
class Tests_Term_SplitSharedTerm extends WP_UnitTestCase {
protected $terms = array();
/**
* Sets up a number of split terms for testing. Terms are as follows.
*
* - `$this->terms['t1']` is an array of the 'term_id' and 'term_taxonomy_id' of a term in the 'wptests_tax'
* taxonomy. Pre-split, the term_id of t1 (`$this->terms['t1']['term_id']`) was shared by t1, t2, and t3.
* - `$this->terms['t2']` is an array of the 'term_id' and 'term_taxonomy_id' of a term in the 'wptests_tax_2'
* taxonomy. Pre-split, the term_id of t2 was `$this->terms['t1']['term_id']`.
* - `$this->terms['t3']` is an array of the 'term_id' and 'term_taxonomy_id' of a term in the 'wptests_tax_3'
* taxonomy. Pre-split, the term_id of t2 was `$this->terms['t1']['term_id']`.
* - `$this->terms['t2_child']` is an array of the 'term_id' and 'term_taxonomy_id' of a term in the
* 'wptests_tax_2' taxonomy. This term is a child of t2, and is used to test parent/child relationships
* after term splitting.
*/
public function setUp() {
global $wpdb;
parent::setUp();
register_taxonomy( 'wptests_tax', 'post' );
register_taxonomy( 'wptests_tax_2', 'post', array(
'hierarchical' => true,
) );
register_taxonomy( 'wptests_tax_3', 'post' );
$t1 = wp_insert_term( 'Foo', 'wptests_tax' );
$t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
$t3 = wp_insert_term( 'Foo', 'wptests_tax_3' );
// Manually modify because split terms shouldn't naturally occur.
$wpdb->update( $wpdb->term_taxonomy,
array( 'term_id' => $t1['term_id'] ),
array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
array( '%d' ),
array( '%d' )
);
$wpdb->update( $wpdb->term_taxonomy,
array( 'term_id' => $t1['term_id'] ),
array( 'term_taxonomy_id' => $t3['term_taxonomy_id'] ),
array( '%d' ),
array( '%d' )
);
$t2_child = wp_insert_term( 'Foo Child', 'wptests_tax_2', array(
'parent' => $t1['term_id'],
) );
// Split the terms and store the new term IDs.
$t2['term_id'] = _split_shared_term( $t1['term_id'], $t2['term_taxonomy_id'] );
$t3['term_id'] = _split_shared_term( $t1['term_id'], $t3['term_taxonomy_id'] );
$this->terms = array(
't1' => $t1,
't2' => $t2,
't3' => $t3,
't2_child' => $t2_child,
);
}
/**
* @ticket 5809
*/
public function test_should_create_new_term_ids() {
$t1_term = get_term_by( 'term_taxonomy_id', $this->terms['t1']['term_taxonomy_id'], 'wptests_tax' );
$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
$t3_term = get_term_by( 'term_taxonomy_id', $this->terms['t3']['term_taxonomy_id'], 'wptests_tax_3' );
$this->assertNotEquals( $t1_term->term_id, $t2_term->term_id );
$this->assertNotEquals( $t1_term->term_id, $t3_term->term_id );
$this->assertNotEquals( $t2_term->term_id, $t3_term->term_id );
}
/**
* @ticket 5809
*/
public function test_should_retain_child_terms_when_using_get_terms_parent() {
$children = get_terms( 'wptests_tax_2', array(
'parent' => $this->terms['t2']['term_id'],
'hide_empty' => false,
) );
$this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
}
/**
* @ticket 5809
*/
public function test_should_retain_child_terms_when_using_get_terms_child_of() {
$children = get_terms( 'wptests_tax_2', array(
'child_of' => $this->terms['t2']['term_id'],
'hide_empty' => false,
) );
$this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
}
/**
* @ticket 30335
*/
public function test_should_rebuild_split_term_taxonomy_hierarchy() {
global $wpdb;
register_taxonomy( 'wptests_tax_3', 'post' );
register_taxonomy( 'wptests_tax_4', 'post', array(
'hierarchical' => true,
) );
$t1 = wp_insert_term( 'Foo1', 'wptests_tax_3' );
$t2 = wp_insert_term( 'Foo1 Parent', 'wptests_tax_4' );
$t3 = wp_insert_term( 'Foo1', 'wptests_tax_4', array(
'parent' => $t2['term_id'],
) );
// Manually modify because split terms shouldn't naturally occur.
$wpdb->update( $wpdb->term_taxonomy,
array( 'term_id' => $t1['term_id'] ),
array( 'term_taxonomy_id' => $t3['term_taxonomy_id'] ),
array( '%d' ),
array( '%d' )
);
$th = _get_term_hierarchy( 'wptests_tax_4' );
$new_term_id = _split_shared_term( $t1['term_id'], $t3['term_taxonomy_id'] );
$t2_children = get_term_children( $t2['term_id'], 'wptests_tax_4' );
$this->assertEquals( array( $new_term_id ), $t2_children );
}
/**
* @ticket 30335
*/
public function test_should_update_default_category_on_term_split() {
global $wpdb;
$t1 = wp_insert_term( 'Foo Default', 'category' );
update_option( 'default_category', $t1['term_id'] );
register_taxonomy( 'wptests_tax_5', 'post' );
$t2 = wp_insert_term( 'Foo Default', 'wptests_tax_5' );
// Manually modify because split terms shouldn't naturally occur.
$wpdb->update( $wpdb->term_taxonomy,
array( 'term_id' => $t1['term_id'] ),
array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
array( '%d' ),
array( '%d' )
);
$this->assertEquals( $t1['term_id'], get_option( 'default_category', -1 ) );
$new_term_id = _split_shared_term( $t1['term_id'], $t1['term_taxonomy_id'] );
$this->assertNotEquals( $new_term_id, $t1['term_id'] );
$this->assertEquals( $new_term_id, get_option( 'default_category', -1 ) );
}
/**
* @ticket 30335
*/
public function test_should_update_menus_on_term_split() {
global $wpdb;
$t1 = wp_insert_term( 'Foo Menu', 'category' );
register_taxonomy( 'wptests_tax_6', 'post' );
$t2 = wp_insert_term( 'Foo Menu', 'wptests_tax_6' );
// Manually modify because split terms shouldn't naturally occur.
$wpdb->update( $wpdb->term_taxonomy,
array( 'term_id' => $t1['term_id'] ),
array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
array( '%d' ),
array( '%d' )
);
$menu_id = wp_create_nav_menu( rand_str() );
$cat_menu_item = wp_update_nav_menu_item( $menu_id, 0, array(
'menu-item-type' => 'taxonomy',
'menu-item-object' => 'category',
'menu-item-object-id' => $t1['term_id'],
'menu-item-status' => 'publish'
) );
$this->assertEquals( $t1['term_id'], get_post_meta( $cat_menu_item, '_menu_item_object_id', true ) );
$new_term_id = _split_shared_term( $t1['term_id'], $t1['term_taxonomy_id'] );
$this->assertNotEquals( $new_term_id, $t1['term_id'] );
$this->assertEquals( $new_term_id, get_post_meta( $cat_menu_item, '_menu_item_object_id', true ) );
}
public function test_wp_get_split_terms() {
$found = wp_get_split_terms( $this->terms['t1']['term_id'] );
$expected = array(
'wptests_tax_2' => $this->terms['t2']['term_id'],
'wptests_tax_3' => $this->terms['t3']['term_id'],
);
$this->assertEqualSets( $expected, $found );
}
public function test_wp_get_split_term() {
$found = wp_get_split_term( $this->terms['t1']['term_id'], 'wptests_tax_3' );
$this->assertEquals( $this->terms['t3']['term_id'], $found );
}
}