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: Refactor the PHP render function to make it easier to make changes in the future #55605

Merged
merged 61 commits into from Nov 9, 2023

Conversation

scruffian
Copy link
Contributor

@scruffian scruffian commented Oct 25, 2023

What?

This refactors the PHP render function for the navigation block.

Why?

The aims are:

  1. To make the code easier to grok.
  2. To keep variables contained to the context in which they are used
  3. To make it easier to change the code in the future.

How?

Creates a new class called WP_Navigation_Block so that the new functions can be kept private.

Testing Instructions

Check that the navigation block continues to behave as before.

Note

This removed the .is-fallback CSS class from the navigation block when it's in a fallback state. We don't use this class in core and I can't see a value to it for themes or users.

@scruffian scruffian added [Type] Code Quality Issues or PRs that relate to code quality [Block] Navigation Affects the Navigation Block labels Oct 25, 2023
@scruffian scruffian self-assigned this Oct 25, 2023
/**
* Returns whether or not a navigation has a submenu.
*/
private static function does_navigation_have_submenus( $inner_blocks ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

My main concern is that this function is now called several times so its probably slightly less performant.

Copy link
Contributor

Choose a reason for hiding this comment

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

We could exit the loop early and return from the method if a submenu is found. I think continue will do that 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

now called several times

Why is this different than before?

probably slightly less performant.

Also this is likely to be marginal. Is it a big concern?

Copy link
Contributor

@getdave getdave Oct 26, 2023

Choose a reason for hiding this comment

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

Let's create an instance variable to cache the result of the function. Then we can check if the instance variable has already been assigned and exit early with that result.

Actually it's a static class so doing this makes no sense. The class doesn't not represent a block instance.

I'm now wondering if the class should not be static. The instance represents a Navigation and the class is a blue print for hanlding that Nav

Copy link
Contributor Author

@scruffian scruffian Oct 26, 2023

Choose a reason for hiding this comment

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

Why is this different than before?

Before it was called in the render function and saved in a variable.

Also this is likely to be marginal. Is it a big concern?

No

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.

Good PR 👍

Initial thoughts...

packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
/**
* Returns whether or not a navigation has a submenu.
*/
private static function does_navigation_have_submenus( $inner_blocks ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We could exit the loop early and return from the method if a submenu is found. I think continue will do that 🤔

/**
* Returns whether or not a navigation has a submenu.
*/
private static function does_navigation_have_submenus( $inner_blocks ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

now called several times

Why is this different than before?

probably slightly less performant.

Also this is likely to be marginal. Is it a big concern?

/**
* Returns whether or not a navigation has a submenu.
*/
private static function does_navigation_have_submenus( $inner_blocks ) {
Copy link
Contributor

@getdave getdave Oct 26, 2023

Choose a reason for hiding this comment

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

Let's create an instance variable to cache the result of the function. Then we can check if the instance variable has already been assigned and exit early with that result.

Actually it's a static class so doing this makes no sense. The class doesn't not represent a block instance.

I'm now wondering if the class should not be static. The instance represents a Navigation and the class is a blue print for hanlding that Nav

$responsive_container_markup,
$nav_element_directives
);
return WP_Navigation_Block::render( $attributes, $content, $block );
Copy link
Contributor

Choose a reason for hiding this comment

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

So clean 🏅

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.

More comments..

packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
Comment on lines 524 to 527
/**
* Returns the markup for the navigation block.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm looking at this thinking...

How is this different from render?

😕 Is there a better name?

packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
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.

The thing I dislike about the PR is that we're refactoring without any test coverage. So the only way we will know if refactoring broke something is when a bug is found 😬

But given the lack of existing tests I don't see much option.

I think we should add unit tests for a select few methods at least,

@github-actions
Copy link

github-actions bot commented Oct 26, 2023

Flaky tests detected in 0e63a3a.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/6785723162
📝 Reported issues:

Copy link
Contributor

@MaggieCabrera MaggieCabrera left a comment

Choose a reason for hiding this comment

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

Besides the unit tests that we included on this PR, I've tested this comparing the markup generated for a navigation block that has:

  • a submenu
  • a site title block
  • a logo block
  • social icons

The markup generated on trunk and with this PR is exactly the same except for the is-fallback class that has been removed. I think this is good to go!

@scruffian scruffian merged commit f3bb6d5 into trunk Nov 9, 2023
50 checks passed
@scruffian scruffian deleted the refacotor/navigation-render branch November 9, 2023 12:13
@github-actions github-actions bot added this to the Gutenberg 17.1 milestone Nov 9, 2023
@scruffian
Copy link
Contributor Author

I decided to merge this so that we don't end up with messy rebases when changes get made to the navigation render function. I expect there are still opportunities to improve this code though, so please leave more reviews and I'll follow up with more improvements. I'll also submit a core patch now so that we can get reviews from core committers.

@scruffian
Copy link
Contributor Author

I opened a patch in core for this here: https://core.trac.wordpress.org/ticket/59867

@Mamaduka
Copy link
Member

What's the strategy for patching bugs or making enhancements for this class after it ships in the core?

I'm asking because we started discouraging Gutenberg_ prefixed classes and functions in the block-library package, as they can easily slip in during package sync and break the core.

@tellthemachines
Copy link
Contributor

What's the strategy for patching bugs or making enhancements for this class after it ships in the core?

What we've done previously with e.g. the theme json class is make a copy of the whole class in Gutenberg, namespaced so it doesn't conflict with the core one, and use it in the plugin instead of the core class. If we're using the class directly in the block library PHP files that makes things a little more complicated 😅 but I'm sure we can come up with some auto-renaming script that will switch the core class with the gutenberg one at build time.

cbravobernal pushed a commit that referenced this pull request Nov 14, 2023
…e changes in the future (#55605)

* Navigation: Refactor the PHP render function to make it easier to make changes in the future

* move code to get_inner_blocks_html

* remove is-fallback class

* allow multiple menus

* add some comments

* refactor directives to a different function

* fix submenus

* refactor responseive navigation function

* remove a passed param

* create a function for get_styles

* dont pass the container_attributes as a param

* handle view script loading

* reorder code

* simplify the return

* tidy up the wrapper attributes

* remove one dependence on has_submenu

* remove the should load view script variable

* more simplification

* Update packages/block-library/src/navigation/index.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* rename class

* remname is_responsive_navigation

* rename does_navigation_have_submenus

* rename get_inner_blocks_for_navigation

* rename get_layout_class_for_navigation

* Update packages/block-library/src/navigation/index.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* Update packages/block-library/src/navigation/index.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* change name of get_nav_markup

* split get_inner_blocks into smaller functions

* add comment

* remove unnecessary spaces

* update docs

* reverse parameter order

* reverse parameter order

* reverse parameter order

* move the class to a new file

* add docs

* rename  to

* move function that's only used by the plugin into that section of the code

* fix linter

* reference the class internally using static

* move variable to static variables

* Update lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* Update lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* move the logic for inner block rendering to a separate function

* test for navigation link markup

* test for site title markup

* removed comments, changed assertSame to assertEquals

* format php

* hide the condition in a function

* hide the condition in a function

* return early from has_submenus

* comments for the tests

* create a function to get the name

* rename variable to nav_blocks_wrapped_in_list_item

* phpcs

* phpcs

* Update phpunit/class-wp-navigation-block-renderer-test.php

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* Update phpunit/class-wp-navigation-block-renderer-test.php

* Update phpunit/class-wp-navigation-block-renderer-test.php

* Apply suggestions from code review

Co-authored-by: Dave Smith <getdavemail@gmail.com>

* dynamic url for links on test

---------

Co-authored-by: Dave Smith <getdavemail@gmail.com>
Co-authored-by: MaggieCabrera <maggie.cabrera@automattic.com>
}

$menu_items_by_parent_id = block_core_navigation_sort_menu_items_by_parent_id( $menu_items );
$parsed_blocks = block_core_navigation_parse_blocks_from_menu_items( $menu_items_by_parent_id[0], $menu_items_by_parent_id );
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm seeing a warning Deprecated: Function gutenberg_block_core_navigation_parse_blocks_from_menu_items is deprecated since version 6.3.0! Use WP_Navigation_Fallback::parse_blocks_from_menu_items instead. in /var/www/html/wp-includes/functions.php on line 6031 on trunk when using a hybrid theme with some legacy Navigation blocks in it. Would it be possible to use WP_Navigation_Fallback::parse_blocks_from_menu_items here?

* @package Gutenberg
*/

class WP_Navigation_Block_Renderer_Test extends WP_UnitTestCase {
Copy link
Contributor

Choose a reason for hiding this comment

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

@scruffian I think we should move this test into the phpunit/blocks directory. It is specific to a specific block and thus should be managed within the Gutenberg repo.

See https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/code/back-merging-to-wp-core.md#ignored-directoriesfiles

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in #58247

@getdave
Copy link
Contributor

getdave commented Jan 25, 2024

Noting that the renderer file code was moved into the block-library package in #57979 and thus should be automatically handled by the packages sync process.

However, the phpunit test should be moved into phpunit/blocks to avoid the need to backport to WP Core.

@oandregal
Copy link
Member

👋 We need a follow-up to address some performance issues. I've prepared #58506 to demonstrate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block [Type] Code Quality Issues or PRs that relate to code quality
Projects
Development

Successfully merging this pull request may close these issues.

None yet

8 participants