Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation Link: use get_block_type_variations to register variations #58389

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions lib/compat/wordpress-6.5/navigation-block-variations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

/**
* Workaround for Core versions < 6.5 to register navigation link variations on registration
*
* @param array $args The block type arguments.
* @return array The updated block type arguments.
*/
function gutenberg_navigation_link_variations_compat( $args ) {

if ( 'core/navigation-link' !== $args['name'] || ! empty( $args['variation_callback'] ) ) {
return $args;
}
$args['variation_callback'] = 'build_navigation_link_block_variations';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compat code doesn't work because the build_navigation_link_block_variations function does not exist.

The consequence is that in WordPress 6.4 the Navigation Link variations for post types (Post Link, Page Link) are not registered, we have only "Custom Link" available in the editor.

I was seeing strange Playwright e2e failures in my PR #59064 and I tracked them down to this. The e2e tests for the core/navigation block are failing because they expect "Page Link" components, but they see only "Custom Link" ones. See for example this code:

await expect(
listView
.getByRole( 'gridcell', {
name: 'Page Link',
} )
.filter( {
hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description.
} )
.getByText( 'Top Level Item 1' )
).toBeVisible();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh gosh, this PR (or my work on it) seems to be cursed 🙈
You are right, the functions name should be gutenberg_block_core_navigation_link_build_variations - since that's the prefixed name after building.
If I change it to that and use WP 6.4 locally, I get "Page Link" and "Post Link" variations correctly.
I wonder why no other tests caught that, but since the function is just passed as a callback it's not called directly and therefore doesn't trigger an error - probably that's why.

I've created a PR to fix that here: #59126

return $args;
}

if ( ! method_exists( 'WP_Block_Type', 'get_variations' ) ) {
add_filter( 'register_block_type_args', 'gutenberg_navigation_link_variations_compat', 9 );
}

/**
* Registers 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
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @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.
*/
function gutenberg_block_core_navigation_link_register_post_type_variation( $post_type, $post_type_object ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
if ( $post_type_object->show_in_nav_menus ) {
$variation = build_variation_for_navigation_link( $post_type_object, 'post-type' );
gutenberg_block_core_navigation_link_register_variation( $variation );
}
}

/**
* Registers a custom taxonomy variation for navigation link on taxonomy registration
* Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
*/
function gutenberg_block_core_navigation_link_register_taxonomy_variation( $taxonomy, $object_type, $args ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) {
$variation = build_variation_for_navigation_link( (object) $args, 'post-type' );
gutenberg_block_core_navigation_link_register_variation( $variation );
}
}

/**
* Unregisters a custom post type variation for navigation link on post type unregistration.
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @param string $post_type The post type name passed from unregistered_post_type action hook.
*/
function gutenberg_block_core_navigation_link_unregister_post_type_variation( $post_type ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
gutenberg_block_core_navigation_link_unregister_variation( $post_type );
}

/**
* Unregisters a custom taxonomy variation for navigation link on taxonomy unregistration.
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @param string $taxonomy The taxonomy name passed from unregistered_taxonomy action hook.
*/
function gutenberg_block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
gutenberg_block_core_navigation_link_unregister_variation( $taxonomy );
}

/**
* Registers a variation for a post type / taxonomy for the navigation link block.
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @param array $variation Variation array from build_variation_for_navigation_link.
*/
function gutenberg_block_core_navigation_link_register_variation( $variation ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
/*
* Directly set the variations on the registered block type
* because there's no server side 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, bail early.
* Variation will be registered in register_block_core_navigation_link then.
*/
if ( ! $navigation_block_type ) {
return;
}

$navigation_block_type->variations = array_merge(
$navigation_block_type->variations,
array( $variation )
);
}

/**
* Unregisters a variation for a post type / taxonomy for the navigation link block.
*
* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* @param string $name Name of the post type / taxonomy (which was used as variation name).
*/
function gutenberg_block_core_navigation_link_unregister_variation( $name ) {
_deprecated_function( __FUNCTION__, '6.5.0', 'WP_Block_Type::get_variations' );
/*
* 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;
}
$variations = $navigation_block_type->variations;
// Search for the variation and remove it from the array.
foreach ( $variations as $i => $variation ) {
if ( $variation['name'] === $name ) {
unset( $variations[ $i ] );
break;
}
}
// Reindex array after removing one variation.
$navigation_block_type->variations = array_values( $variations );
}
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.5/interactivity-api/interactivity-api.php';
require __DIR__ . '/compat/wordpress-6.5/class-wp-script-modules.php';
require __DIR__ . '/compat/wordpress-6.5/scripts-modules.php';
require __DIR__ . '/compat/wordpress-6.5/navigation-block-variations.php';
if ( ! class_exists( 'WP_Block_Bindings_Source' ) ) {
require __DIR__ . '/compat/wordpress-6.5/block-bindings/class-wp-block-bindings-source.php';
}
Expand Down
134 changes: 26 additions & 108 deletions packages/block-library/src/navigation-link/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,69 +327,40 @@ function build_variation_for_navigation_link( $entity, $kind ) {
}

/**
* Register a variation for a post type / taxonomy for the navigation link block.
* Filters the registered variations for a block type.
* Returns the dynamically built variations for all post-types and taxonomies.
*
* @param array $variation Variation array from build_variation_for_navigation_link.
* @return void
*/
function block_core_navigation_link_register_variation( $variation ) {
// Directly set the variations on the registered block type
// because there's no server side 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, bail early.
// Variation will be registered in register_block_core_navigation_link then.
if ( ! $navigation_block_type ) {
return;
}

$navigation_block_type->variations = array_merge(
$navigation_block_type->variations,
array( $variation )
);
}

/**
* Unregister a variation for a post type / taxonomy for the navigation link block.
* @since 6.5.0
*
* @param string $name Name of the post type / taxonomy (which was used as variation name).
* @return void
* @param array $variations Array of registered variations for a block type.
* @param WP_Block_Type $block_type The full block type object.
*/
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;
}
$variations = $navigation_block_type->variations;
// Search for the variation and remove it from the array.
foreach ( $variations as $i => $variation ) {
if ( $variation['name'] === $name ) {
unset( $variations[ $i ] );
break;
}
function block_core_navigation_link_filter_variations( $variations, $block_type ) {
if ( 'core/navigation-link' !== $block_type->name ) {
return $variations;
}
// Reindex array after removing one variation.
$navigation_block_type->variations = array_values( $variations );

$generated_variations = block_core_navigation_link_build_variations();
return array_merge( $variations, $generated_variations );
}

/**
* Returns an array of variations for the navigation link block.
*
* @since 6.5.0
*
* @return array
*/
function block_core_navigation_link_build_variations() {
// This will only handle post types and taxonomies registered until this point (init on priority 9).
// See action hooks below for other post types and taxonomies.
// See https://github.com/WordPress/gutenberg/issues/53826 for details.
$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );

// Use two separate arrays as a way to order the variations in the UI.
// Known variations (like Post Link and Page Link) are added to the
// `built_ins` array. Variations for custom post types and taxonomies are
// added to the `variations` array and will always appear after `built-ins.
/*
* Use two separate arrays as a way to order the variations in the UI.
* Known variations (like Post Link and Page Link) are added to the
* `built_ins` array. Variations for custom post types and taxonomies are
* added to the `variations` array and will always appear after `built-ins.
*/
$built_ins = array();
$variations = array();

Expand Down Expand Up @@ -418,76 +389,23 @@ function block_core_navigation_link_build_variations() {
}

/**
* Register the navigation link block.
* Registers the navigation link block.
*
* @uses render_block_core_navigation()
* @uses render_block_core_navigation_link()
* @uses build_navigation_link_block_variations()
* @throws WP_Error An WP_Error exception parsing the block definition.
*/
function register_block_core_navigation_link() {
register_block_type_from_metadata(
__DIR__ . '/navigation-link',
array(
'render_callback' => 'render_block_core_navigation_link',
'variation_callback' => 'block_core_navigation_link_build_variations',
'render_callback' => 'render_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', '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 action hook.
* @param WP_Post_Type $post_type_object The post type object passed from registered_post_type.
* @return void
*/
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' );
block_core_navigation_link_register_variation( $variation );
}
}

/**
* Register a custom taxonomy variation for navigation link on taxonomy registration
* Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
* @return void
*/
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' );
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
* Creates all variations for post types / taxonomies dynamically (= each time when variations are requested).
* Do not use variation_callback, to also account for unregistering post types/taxonomies later on.
*/
function block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) {
block_core_navigation_link_unregister_variation( $taxonomy );
}
add_action( 'get_block_type_variations', 'block_core_navigation_link_filter_variations', 10, 2 );
Loading
Loading