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

Conversation

gaambo
Copy link
Contributor

@gaambo gaambo commented Jan 29, 2024

This is an exploration to follow up to #54801, but using the new get_block_type_variations filter to register those variations.
This has performance benefits (see #56952) and also should fix the phpunit timeouts happening after merging the original PR and merging that into core.

Why?

How?

Instead of using the registered_post_type and registered_taxonomy hooks (which lead to timeouts an can be a performance issue on sites with many CPTs/taxonomies), this uses the new get_block_type_variations filter.
Since Gutenberg has to support the last two core versions and the old functions have been in Gutenberg since November, those were kept in and marked deprecated (I've still added a @since and a @deprecated tag).
The unit tests use the old deprecated methods on core versions <6.5 so unit tests work on older and new versions.

This way:

  • Core versions < 6.5 have the same experience as before the changes in november: CPTs/taxonomies registered after init#10 don't have a variation)
  • Core versions >= 6.5 have the added performance boost of using get_block_type_variations

Alternatives tried
Using the variation_callback instead of the filter was tried, and would register CPTs/taxonomies registered after init#10. But unregistering them would not unregister those variations, since the callback is only called once per request.

Testing Instructions

Automated testing

Run npm run test:unit:php:base -- --filter Block_Navigation_Link_Variations_Test

Manual Testing

Post Type

  1. Register a custom post type (example code from developer.wordpress.org).
add_action('init', function () {
    register_post_type(
        'wporg_product',
        array(
            'labels'      => array(
                'name'          => __('Products', 'textdomain'),
                'singular_name' => __('Product', 'textdomain'),
                'item_link' => __('Product Link', 'textdomain')
            ),
            'public'      => true,
            'has_archive' => true,
            'show_in_rest' => true,
            'show_in_nav_menus' => true
        )
    );
}, 11);

Important: Set the item_link label or the block variation is called Post Link.
Important: change add_action priority to something higher than 10 (eg 11) - when using something lower it already works in trunk.
2. Go into site-editor and add a navigation block
3. try to search for a block named like the custom taxonomy (eg "Product Link").
4. Block is available

Taxonomy

  1. Register a custom taxonomy (example code from developer.wordpress.org)
add_action('init', function() {
	 $args   = array(
		 'labels'            => array(
		     'link_item'         => __( 'Course' ),
	         ),
		 'show_in_nav_menus' => true
	 );
	 register_taxonomy( 'course', [ 'post' ], $args );
});

Important: Set the item_link label or the block variation is called Post Link.
Important: change add_action priority to something higher than 10 (eg 11) - when using something lower it already works in trunk.
3. Go into site-editor and add a navigation block
4. try to search for a block named like the custom taxonomy (eg "Product Link").
5. Block is available

Testing unregistering

Post Type
  1. Register a custom post type (example code from developer.wordpress.org).
add_action('init', function () {
    register_post_type(
        'wporg_product',
        array(
            'labels'      => array(
                'name'          => __('Products', 'textdomain'),
                'singular_name' => __('Product', 'textdomain'),
                'item_link' => __('Product Link', 'textdomain')
            ),
            'public'      => true,
            'has_archive' => true,
            'show_in_rest' => true,
            'show_in_nav_menus' => true
        )
    );
}, 11);

Important: Set the item_link label or the block variation is called Post Link.
Important: change add_action priority to something higher than 10 (eg 11) - when using something lower it already works in trunk.
2. Unregister the custom post type after the navigation link block is registered and the variation is created:

add_action('init', function () {
    unregister_post_type('wporg_product');
}, 100);
  1. Go into site-editor and add a navigation block
  2. try to search for a block named like the custom taxonomy (eg "Product Link").
  3. Block variation should not be available
Taxonomy
  1. Register a custom taxonomy (example code from developer.wordpress.org)
add_action('init', function() {
	 $args   = array(
		 'labels'            => array(
		     'link_item'         => __( 'Course' ),
	         ),
		 'show_in_nav_menus' => true
	 );
	 register_taxonomy( 'course', [ 'post' ], $args );
}, 11);

Important: Set the item_link label or the block variation is called Post Link.
Important: change add_action priority to something higher than 10 (eg 11) - when using something lower it already works in trunk.
2. Unregister the custom taxonomy after the navigation link block is registered and the variation is created:

add_action('init', function () {
    unregister_taxonomy('course');
}, 100);
  1. Go into site-editor and add a navigation block
  2. try to search for a block named like the custom taxonomy (eg "Course Link").
  3. Block variation should not be available

Co-authored-by: gaambo gaambo@git.wordpress.org
Co-authored-by: getdave get_dave@git.wordpress.org
Co-authored-by: youknowriad youknowriad@git.wordpress.org
Co-authored-by: Andrei Draganescu 107534+draganescu@users.noreply.github.com

@getdave
Copy link
Contributor

getdave commented Jan 29, 2024

I tested this by applying the code directly from this diff to WordPress/wordpress-develop#5967.

Now all the PHPUnit tests pass without timeout which makes me think this is the culprit of the issue there.

Let's look to bring this in.

@gaambo
Copy link
Contributor Author

gaambo commented Jan 29, 2024

Regarding backwards-compatibility:

  • The changes causing the timeout have been in Gutenberg since November, so the two functions register_block_core_navigation_link_post_type_variation and register_block_core_navigation_link_taxonomy_variation have been in there. But they haven't been in any core version yet. Do we have to keep them? What's the rule here?
  • Up until core 6.4 variations are registered on block type registration, therefore at least core CPTs/taxonomies and all registered up to init#10 have their variations created. Only CPTs/taxonomies registered later don't have a variation created.
  • The new way using the get_block_type_variations will only work in WordPress 6.5, because this filter was only added there
  • If the code will only use the new filter, and does not register variations on block type registration, there will be no CPT/taxonomy variations created on older versions using this newer Gutenberg version.
  • As a workaround, I could keep the code on block type registration to register all variations known until there and then on get_block_type_variations register all newly added CPTs/taxonomies - like so:
register_block_type_from_metadata(
		__DIR__ . '/navigation-link',
		array(
			'render_callback' => 'render_block_core_navigation_link',
			'variations'      => build_navigation_link_block_variations(),
		)
	);

BUT that would mean, all the performance benefits of the variations_callback will not be used in this block.

  • I could instead check if the get_block_type_variations filter is available and then use that OR set the variations property for older WordPress versions. But is there any precedent for that? Would it be okay to check the version from ABSPATH . WPINC . '/version.php';
  • Unit testes would need to be adapted whether get_variations is available or not. The best way would probably to not use unit tests, but instead use e2e tests in the editor to check the availability of those variations?

@gaambo
Copy link
Contributor Author

gaambo commented Jan 29, 2024

After trying some things out, I came to the following conclusions

  • We can't fix the original bug for core versions prior to 6.5. Because all shims and workarounds would still run on block type registration and therefore only register variations for previously registered CPTs/taxonomies. The only way to fix this bug was by hooking into registered_post_type/registered_taxonomy.
  • We can only try to fix it for WP 6.5 and newer versions which have the get_block_type_variations filter.
  • Therefore, the unit tests in Block_Navigation_Link_Variations_Test should therefore actually only run on WordPress 6.5+ - since the test set_up function runs after block type registration. Is that possible? Otherwise they will constantly fail.

If anybody else has some ideas, that would be great 😅

@youknowriad
Copy link
Contributor

I don't know much about the problem but I can answer some of the questions above.

The changes causing the timeout have been in Gutenberg since November, so the two functions register_block_core_navigation_link_post_type_variation and register_block_core_navigation_link_taxonomy_variation have been in there. But they haven't been in any core version yet. Do we have to keep them? What's the rule here?

Ideally we deprecate and remove since they were not in Core but if we think that it's very unlikely that these things are used by third-party code, I believe it's fine to just remove them.

If the code will only use the new filter, and does not register variations on block type registration, there will be no CPT/taxonomy variations created on older versions using this newer Gutenberg version.

I think that's fine personally. What would it take to support previous core versions? (6.4 and 6.3), if it's possible to do so somehow, we can potentially add this code to lib/compact/wordpress-6.5 folder or something (so it doesn't get included into core but only runs in the plugin with an additional version check for this code)

@gaambo
Copy link
Contributor Author

gaambo commented Jan 30, 2024

@youknowriad thank you for your input!

I just pushed a commit which

  • deprecates the functions in navigation-block/index.php (which leads to them having a since and deprecated docblock with the same version 😅)
  • adds to-dos that these functions can be removed in core 6.7/when gutenberg does not need to support core versions <6.5 anymore. (I can create issues for them and assign myself and make a reminder).
  • fixes the unit tests for core versions < 6.5 (by using the deprecated methods above and expecting them).

I've also updated the PR description with all this new information.

This should also include the code style changes from #58385 (so i closed that one).

@gaambo gaambo marked this pull request as ready for review January 30, 2024 08:57
@gaambo gaambo mentioned this pull request Jan 30, 2024
@youknowriad youknowriad requested a review from desrosj January 30, 2024 09:02
@gaambo gaambo force-pushed the try/navigation-link-variations-filter branch from b129d29 to 35585bd Compare February 1, 2024 16:13
@gaambo
Copy link
Contributor Author

gaambo commented Feb 5, 2024

@getdave should we try bringing this in for the next release, or do you think the workaround with disabling the filters in unit tests is enough for now?
For the future, I still think using the new get_block_type_variations should definitely be done, since it was implemented exactly for a use case like this.

Copy link

github-actions bot commented Feb 5, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: gaambo <gaambo@git.wordpress.org>
Co-authored-by: getdave <get_dave@git.wordpress.org>
Co-authored-by: draganescu <andraganescu@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@getdave
Copy link
Contributor

getdave commented Feb 6, 2024

@gaambo I'm going to review this as a priority tomorrow and try and catch up here.

@getdave
Copy link
Contributor

getdave commented Feb 8, 2024

Looking now

@getdave
Copy link
Contributor

getdave commented Feb 8, 2024

OPTIONAL - Confirm if PHP changes require backporting to WordPress Core / Detect PHP changes (pull_request) Failing after 1m

I can confirm these changes will not need backporting to WP 6.5 so long as this PR lands in time for the Gutenberg Plugin 17.7.0 RC release on Friday 9th Feb 2024.

Copy link
Contributor

@getdave getdave left a comment

Choose a reason for hiding this comment

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

Let's bring this in. A few nits.

Thank you for all the work on this 🙇

packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
phpunit/blocks/block-navigation-link-variations-test.php Outdated Show resolved Hide resolved
Copy link
Contributor

@draganescu draganescu left a comment

Choose a reason for hiding this comment

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

Did not test but the code updates LGTM apart from some nits.

packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation-link/index.php Outdated Show resolved Hide resolved
@gaambo gaambo force-pushed the try/navigation-link-variations-filter branch from 35585bd to a142a17 Compare February 8, 2024 12:32
@gaambo
Copy link
Contributor Author

gaambo commented Feb 8, 2024

Thanks for the feedback. I applied it and rebased :)

@getdave
Copy link
Contributor

getdave commented Feb 9, 2024

I restarted all the tests. We've had some trouble in trunk with test failures due to mismatched packages and things so let's check if these failures are legit.

@getdave
Copy link
Contributor

getdave commented Feb 9, 2024

@youknowriad Please could I get a confidence check here that:

  • e2e failures are the Synced Pattern problems and not related to this PR?
  • PHPUNit failures are Interactivity API failures that we've been seeing elsewhere

I don't think any of the tests are faling due to changes in this PR. It @gaambo can sync his fork and then rebase this PR the tests should pass but that might not be possible prior to the 17.7.0 RC today. If not then I'd like to force merge here.

@gaambo gaambo force-pushed the try/navigation-link-variations-filter branch from 0471b9c to ab2afaf Compare February 9, 2024 12:17
@gaambo
Copy link
Contributor Author

gaambo commented Feb 9, 2024

Just rebased the PR, so let's see if tests go through now :)

@youknowriad
Copy link
Contributor

Aside the performance tests that are still failing on trunk, everything should be passing.

* @since 6.5.0
* @deprecated 6.5.0 Use WP_Block_Type::get_variations / get_block_type_variations filter instead.
*
* TODO: After two WP versions (6.7), we can remove this.
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is here only to ensure compatibility with previous versions in the Gutenberg plugin, can we define these functions outside the "block-library" package or no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's there for two reasons:

  • The functions have been in Gutenberg since November (but no core version)
  • They provide backwards-compatibility when the Gutenberg plugin is used with WP versions < 6.5

Do you mean, I could move them into the lib/compat/wordpress-6.5 directory?

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mean, I could move them into the lib/compat/wordpress-6.5 directory?

Yes, since these functions are "Gutenberg specific" and shouldn't "run" in Core. I was wondering if there's a way to keep the "navigation" block code "core only" and add the compat code from the compat folder. The reason is that the navigation block code will be copied as is into Core.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@youknowriad I understand.
I did that in dd6857c
I disabled the phpcs rules for these functions, since they were never in core and therefore imho shouldn't need a guarded clause. But if that thought was wrong, let me know.
Tests are passing locally. Only two other tests related to WP_Style_Engine_CSS_Rule_Gutenberg::set_at_rule are failing locally - but let's see what the GitHub tests say.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe I'm missing something the functions are still in the navigation-link/index.php file?

@gaambo gaambo force-pushed the try/navigation-link-variations-filter branch from ab2afaf to dd6857c Compare February 9, 2024 13:22
@gaambo gaambo requested a review from spacedmonkey as a code owner February 9, 2024 13:22
@getdave
Copy link
Contributor

getdave commented Feb 9, 2024

PHPUnit failure:

Fatal error: Cannot redeclare block_core_navigation_link_unregister_taxonomy_variation() (previously declared in /var/www/html/wp-includes/blocks/navigation-link.php:488) in /var/www/html/wp-content/plugins/gutenberg/lib/compat/wordpress-6.5/navigation-block-variations.php on line 80

It's likely because the code already existed in trunk and was merged into WP Core trunk during the initial packages sync. However, I understand that it will be removed if/when we merge this PR and perform the final packages sync following the Gutenberg 17.7.0 RC today.

We could add a guard clause for safety? 🤷

@gaambo Not sure if you already did this but you might find it easier to:

  • update your fork with the upstream Gutenberg repo.
  • rebase this PR against the updated trunk.

That way we should bring in any fixes from trunk for the failing PHPUNit and e2e tests and that will give us a clearer picture of legit vs false failures 🙏

@gaambo
Copy link
Contributor Author

gaambo commented Feb 9, 2024

Oh, because the code was already once synced into core in the previous packages update. Yeah, of course - I'll just add the guard clause.

@youknowriad
Copy link
Contributor

@gaambo not really, we should not guard but just use prefixes functions gutenberg_ now that the code has moved to the 6.5 folder.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

So I didn't test but the diff looks good to me.

@youknowriad youknowriad merged commit 544b315 into WordPress:trunk Feb 9, 2024
53 of 54 checks passed
@github-actions github-actions bot added this to the Gutenberg 17.7 milestone Feb 9, 2024
@getdave
Copy link
Contributor

getdave commented Feb 9, 2024

🎉 🎉 🎉

@draganescu
Copy link
Contributor

Huzzah!

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Link Affects the Navigation Link Block [Type] Bug An existing feature does not function as intended
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants