From eafbcb3b6e6333ad098f91c3c4ff8b535ec2938d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 9 Jan 2016 14:57:22 +0000 Subject: [PATCH] Taxonomy: Introduce `unregister_taxonomy()`. This new function can be used to completely unregister non built-in taxonomies. Fixes #35227. git-svn-id: https://develop.svn.wordpress.org/trunk@36243 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/taxonomy.php | 56 +++++++++++++++++ tests/phpunit/includes/utils.php | 2 +- tests/phpunit/tests/taxonomy.php | 102 +++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 78dd52ced9..3c73094726 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -475,6 +475,62 @@ function register_taxonomy( $taxonomy, $object_type, $args = array() ) { do_action( 'registered_taxonomy', $taxonomy, $object_type, $args ); } +/** + * Unregister a taxonomy. + * + * Can not be used to unregister built-in taxonomies. + * + * @since 4.5.0 + * + * @global WP $wp Current WordPress environment instance. + * @global array $wp_taxonomies List of taxonomies. + * + * @param string $taxonomy Taxonomy name. + * @return bool|WP_Error True on success, WP_Error on failure. + */ +function unregister_taxonomy( $taxonomy ) { + if ( ! taxonomy_exists( $taxonomy ) ) { + return new WP_Error( 'invalid_taxonomy', __( 'Invalid Taxonomy' ) ); + } + + $taxonomy_args = get_taxonomy( $taxonomy ); + + // Do not allow unregistering internal taxonomies. + if ( $taxonomy_args->_builtin ) { + return new WP_Error( 'invalid_taxonomy', __( 'Unregistering a built-in taxonomy is not allowed' ) ); + } + + global $wp, $wp_taxonomies; + + // Remove query var. + if ( false !== $taxonomy_args->query_var ) { + $wp->remove_query_var( $taxonomy_args->query_var ); + } + + // Remove rewrite tags and permastructs. + if ( false !== $taxonomy_args->rewrite ) { + remove_rewrite_tag( "%$taxonomy%" ); + remove_permastruct( $taxonomy ); + } + + // Unregister callback handling for metabox. + remove_filter( 'wp_ajax_add-' . $taxonomy, '_wp_ajax_add_hierarchical_term' ); + + // Remove the taxonomy. + unset( $wp_taxonomies[ $taxonomy ] ); + + /** + * Fires after a taxonomy is unregistered. + * + * @since 4.5.0 + * + * @param string $taxonomy Taxonomy name. + */ + do_action( 'unregistered_taxonomy', $taxonomy ); + + return true; +} + /** * Builds an object with all taxonomy labels out of a taxonomy object * diff --git a/tests/phpunit/includes/utils.php b/tests/phpunit/includes/utils.php index 0a6dfc13a4..00d1b32852 100644 --- a/tests/phpunit/includes/utils.php +++ b/tests/phpunit/includes/utils.php @@ -334,7 +334,7 @@ function _unregister_post_type( $cpt_name ) { } function _unregister_taxonomy( $taxonomy_name ) { - unset( $GLOBALS['wp_taxonomies'][$taxonomy_name] ); + unregister_taxonomy( $taxonomy_name ); } /** diff --git a/tests/phpunit/tests/taxonomy.php b/tests/phpunit/tests/taxonomy.php index 0cf65169e1..86cf6226f3 100644 --- a/tests/phpunit/tests/taxonomy.php +++ b/tests/phpunit/tests/taxonomy.php @@ -530,4 +530,106 @@ class Tests_Taxonomy extends WP_UnitTestCase { $tax = get_taxonomy( 'wptests_tax' ); $this->assertFalse( $tax->query_var ); } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_unknown_taxonomy() { + $this->assertWPError( unregister_taxonomy( 'foo' ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_twice() { + register_taxonomy( 'foo', 'post' ); + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + $this->assertWPError( unregister_taxonomy( 'foo' ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_disallow_builtin_taxonomy() { + $this->assertWPError( unregister_taxonomy( 'post_tag' ) ); + $this->assertWPError( unregister_taxonomy( 'category' ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_removes_query_vars() { + global $wp; + + register_taxonomy( 'foo', 'post', array( 'query_var' => 'bar' ) ); + + $this->assertInternalType( 'int', array_search( 'bar', $wp->public_query_vars ) ); + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + $this->assertFalse( array_search( 'bar', $wp->public_query_vars ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_removes_permastruct() { + $this->set_permalink_structure( '/%postname%' ); + + global $wp_rewrite; + + register_taxonomy( 'foo', 'post', array( 'query_var' => 'bar', 'rewrite' => true ) ); + + $this->assertInternalType( 'array', $wp_rewrite->extra_permastructs['foo'] ); + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + $this->assertFalse( isset($wp_rewrite->extra_permastructs['foo'] ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_removes_rewrite_rules() { + $this->set_permalink_structure( '/%postname%' ); + + global $wp_rewrite; + + register_taxonomy( 'foo', 'post', array( 'query_var' => 'bar' ) ); + + $count_before = count( $wp_rewrite->rewritereplace ); + + $this->assertContains( '%foo%', $wp_rewrite->rewritecode ); + $this->assertContains( 'bar=', $wp_rewrite->queryreplace ); + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + $this->assertNotContains( '%foo%', $wp_rewrite->rewritecode ); + $this->assertNotContains( 'bar=', $wp_rewrite->queryreplace ); + $this->assertSame( --$count_before, count( $wp_rewrite->rewritereplace ) ); // Array was reduced by one value. + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_removes_taxonomy_from_global() { + global $wp_taxonomies; + + register_taxonomy( 'foo', 'post' ); + + $this->assertInternalType( 'object', $wp_taxonomies['foo'] ); + $this->assertInternalType( 'object', get_taxonomy( 'foo' ) ); + + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + + $this->assertFalse( isset( $wp_taxonomies['foo'] ) ); + $this->assertFalse( get_taxonomy( 'foo' ) ); + } + + /** + * @ticket 35227 + */ + public function test_unregister_taxonomy_removes_meta_box_callback() { + global $wp_filter; + + register_taxonomy( 'foo', 'post' ); + + $this->assertSame( 1, count( $wp_filter['wp_ajax_add-foo'] ) ); + $this->assertTrue( unregister_taxonomy( 'foo' ) ); + $this->assertSame( array(), $wp_filter['wp_ajax_add-foo'] ); + } }