diff --git a/packages/block-library/src/navigation-link/index.php b/packages/block-library/src/navigation-link/index.php index 1165ce94b5921..f7c26afd1f88d 100644 --- a/packages/block-library/src/navigation-link/index.php +++ b/packages/block-library/src/navigation-link/index.php @@ -1,6 +1,6 @@ get_registered( 'core/navigation-link' ); @@ -341,6 +341,31 @@ function register_block_core_navigation_link_variation( $variation ) { $navigation_block_type->variations[] = $variation; } +/** + * Unregister a variation for a post type / taxonomy for the navigation link block. + * + * @param string $name Name of the post type / taxonomy (which was used as variation name). + * @return void + */ +function block_core_navigation_link_unregister_variation( $name ) { + // Directly get the variations from the registered block type + // because there's no server side (un)registration for variations (see #47170). + $navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' ); + // If the block is not registered (yet), there's no need to remove a variation. + if ( ! $navigation_block_type || empty( $navigation_block_type->variations ) ) { + return; + } + // Search for the variation and remove it from the array. + foreach ( $navigation_block_type->variations as $i => $variation ) { + if ( $variation['name'] === $name ) { + unset( $navigation_block_type->variations[ $i ] ); + break; + } + } + // Reindex array after removing one variation. + $navigation_block_type->variations = array_values( $navigation_block_type->variations ); +} + /** * Register the navigation link block. * @@ -393,21 +418,24 @@ function register_block_core_navigation_link() { add_action( 'init', 'register_block_core_navigation_link' ); // Register actions for all post types and taxonomies, to add variations when they are registered. // All post types/taxonomies registered before register_block_core_navigation_link, will be handled by that function. -add_action( 'registered_post_type', 'register_block_core_navigation_link_post_type_variation', 10, 2 ); -add_action( 'registered_taxonomy', 'register_block_core_navigation_link_taxonomy_variation', 10, 3 ); +add_action( 'registered_post_type', 'block_core_navigation_link_register_post_type_variation', 10, 2 ); +add_action( 'registered_taxonomy', 'block_core_navigation_link_register_taxonomy_variation', 10, 3 ); +// Handle unregistering of post types and taxonomies and remove the variations. +add_action( 'unregistered_post_type', 'block_core_navigation_link_unregister_post_type_variation' ); +add_action( 'unregistered_taxonomy', 'block_core_navigation_link_unregister_taxonomy_variation' ); /** * Register custom post type variations for navigation link on post type registration * Handles all post types registered after the block is registered in register_navigation_link_post_type_variations * - * @param string $post_type The post type name passed from registered_post_type filter. + * @param string $post_type The post type name passed from registered_post_type action hook. * @param WP_Post_Type $post_type_object The post type object passed from registered_post_type. * @return void */ -function register_block_core_navigation_link_post_type_variation( $post_type, $post_type_object ) { +function block_core_navigation_link_register_post_type_variation( $post_type, $post_type_object ) { if ( $post_type_object->show_in_nav_menus ) { $variation = build_variation_for_navigation_link( $post_type_object, 'post-type' ); - register_block_core_navigation_link_variation( $variation ); + block_core_navigation_link_register_variation( $variation ); } } @@ -420,9 +448,29 @@ function register_block_core_navigation_link_post_type_variation( $post_type, $p * @param array $args Array of taxonomy registration arguments. * @return void */ -function register_block_core_navigation_link_taxonomy_variation( $taxonomy, $object_type, $args ) { +function block_core_navigation_link_register_taxonomy_variation( $taxonomy, $object_type, $args ) { if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) { $variation = build_variation_for_navigation_link( (object) $args, 'post-type' ); - register_block_core_navigation_link_variation( $variation ); + block_core_navigation_link_register_variation( $variation ); } } + +/** + * Unregisters a custom post type variation for navigation link on post type unregistration. + * + * @param string $post_type The post type name passed from unregistered_post_type action hook. + * @return void + */ +function block_core_navigation_link_unregister_post_type_variation( $post_type ) { + block_core_navigation_link_unregister_variation( $post_type ); +} + +/** + * Unregisters a custom taxonomy variation for navigation link on taxonomy unregistration. + * + * @param string $taxonomy The taxonomy name passed from unregistered_taxonomy action hook. + * @return void + */ +function block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) { + block_core_navigation_link_unregister_variation( $taxonomy ); +} diff --git a/phpunit/blocks/block-navigation-link-variations-test.php b/phpunit/blocks/block-navigation-link-variations-test.php index c5082e0f4c878..8eef5c393148b 100644 --- a/phpunit/blocks/block-navigation-link-variations-test.php +++ b/phpunit/blocks/block-navigation-link-variations-test.php @@ -1,6 +1,6 @@ true, ) ); + register_post_type( + 'private_custom_book', + array( + 'labels' => array( + 'item_link' => 'Custom Book', + ), + 'public' => false, + 'show_in_rest' => true, + 'show_in_nav_menus' => false, + ) + ); register_taxonomy( 'book_type', 'custom_book', @@ -35,40 +46,131 @@ public function set_up() { 'show_in_nav_menus' => true, ) ); + register_taxonomy( + 'private_book_type', + 'private_custom_book', + array( + 'labels' => array( + 'item_link' => 'Book Type', + ), + 'show_in_nav_menus' => false, + ) + ); } public function tear_down() { unregister_post_type( 'custom_book' ); + unregister_post_type( 'private_custom_book' ); unregister_taxonomy( 'book_type' ); + unregister_taxonomy( 'private_book_type' ); + unregister_post_type( 'temp_custom_book' ); + unregister_taxonomy( 'temp_book_type' ); parent::tear_down(); } /** - * @covers ::register_block_core_navigation_link_post_type_variation + * @covers ::block_core_navigation_link_register_post_type_variation */ public function test_navigation_link_variations_custom_post_type() { $registry = WP_Block_Type_Registry::get_instance(); $nav_link_block = $registry->get_registered( 'core/navigation-link' ); $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); $variation = $this->get_variation_by_name( 'custom_book', $nav_link_block->variations ); - $this->assertIsArray( $variation, 'Block variation is not an array' ); + $this->assertIsArray( $variation, 'Block variation does not exist' ); $this->assertArrayHasKey( 'title', $variation, 'Block variation has no title' ); $this->assertEquals( 'Custom Book', $variation['title'], 'Variation title is different than the post type label' ); } /** - * @covers ::register_block_core_navigation_link_taxonomy_variation + * @covers ::block_core_navigation_link_register_post_type_variation + */ + public function test_navigation_link_variations_private_custom_post_type() { + $registry = WP_Block_Type_Registry::get_instance(); + $nav_link_block = $registry->get_registered( 'core/navigation-link' ); + $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); + $variation = $this->get_variation_by_name( 'private_custom_book', $nav_link_block->variations ); + $this->assertEmpty( $variation, 'Block variation for private post type exists.' ); + } + + /** + * @covers ::block_core_navigation_link_register_taxonomy_variation */ public function test_navigation_link_variations_custom_taxonomy() { $registry = WP_Block_Type_Registry::get_instance(); $nav_link_block = $registry->get_registered( 'core/navigation-link' ); $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); $variation = $this->get_variation_by_name( 'book_type', $nav_link_block->variations ); - $this->assertIsArray( $variation, 'Block variation is not an array' ); + $this->assertIsArray( $variation, 'Block variation does not exist' ); $this->assertArrayHasKey( 'title', $variation, 'Block variation has no title' ); $this->assertEquals( 'Book Type', $variation['title'], 'Variation title is different than the post type label' ); } + /** + * @covers ::block_core_navigation_link_register_taxonomy_variation + */ + public function test_navigation_link_variations_private_custom_taxonomy() { + $registry = WP_Block_Type_Registry::get_instance(); + $nav_link_block = $registry->get_registered( 'core/navigation-link' ); + $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); + $variation = $this->get_variation_by_name( 'private_book_type', $nav_link_block->variations ); + $this->assertEmpty( $variation, 'Block variation for private taxonomy exists.' ); + } + + /** + * @covers ::block_core_navigation_link_unregister_post_type_variation + */ + public function test_navigation_link_variations_unregister_post_type() { + register_post_type( + 'temp_custom_book', + array( + 'labels' => array( + 'item_link' => 'Custom Book', + ), + 'public' => true, + 'show_in_rest' => true, + 'show_in_nav_menus' => true, + ) + ); + + $registry = WP_Block_Type_Registry::get_instance(); + $nav_link_block = $registry->get_registered( 'core/navigation-link' ); + $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); + $variation = $this->get_variation_by_name( 'temp_custom_book', $nav_link_block->variations ); + $this->assertIsArray( $variation, 'Block variation does not exist' ); + + unregister_post_type( 'temp_custom_book' ); + + $variation = $this->get_variation_by_name( 'temp_custom_book', $nav_link_block->variations ); + $this->assertEmpty( $variation, 'Block variation still exists' ); + } + + /** + * @covers ::block_core_navigation_link_unregister_taxonomy_variation + */ + public function test_navigation_link_variations_unregister_taxonomy() { + register_taxonomy( + 'temp_book_type', + 'custom_book', + array( + 'labels' => array( + 'item_link' => 'Book Type', + ), + 'show_in_nav_menus' => true, + ) + ); + + $registry = WP_Block_Type_Registry::get_instance(); + $nav_link_block = $registry->get_registered( 'core/navigation-link' ); + $this->assertNotEmpty( $nav_link_block->variations, 'Block has no variations' ); + $variation = $this->get_variation_by_name( 'temp_book_type', $nav_link_block->variations ); + $this->assertIsArray( $variation, 'Block variation does not exist' ); + + unregister_taxonomy( 'temp_book_type' ); + + $variation = $this->get_variation_by_name( 'temp_book_type', $nav_link_block->variations ); + $this->assertEmpty( $variation, 'Block variation still exists' ); + } + /** * Get a variation by its name from an array of variations. *