-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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 Block: Prevent circular references in navigation block rendering #46387
Navigation Block: Prevent circular references in navigation block rendering #46387
Conversation
7668d55
to
cc64fd6
Compare
if ( in_array( $attributes['ref'], $seen_ref, true ) ) { | ||
return ''; | ||
} | ||
$seen_ref[] = $attributes['ref']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be smarter and keep track of the parent rather than a flat array so you could have two identical sibling navigation blocks, but Navigation blocks probably shouldn't be nested inside other navigation blocks in the first place, so it's probably fine this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ended up not being fine. #47085
$list_item_nav_blocks = array( | ||
'core/navigation-link', | ||
'core/home-link', | ||
'core/site-title', | ||
'core/site-logo', | ||
'core/navigation-submenu', | ||
); | ||
|
||
$needs_list_item_wrapper = array( | ||
'core/site-title', | ||
'core/site-logo', | ||
); | ||
|
||
$inner_blocks_html = ''; | ||
$is_list_open = false; | ||
foreach ( $inner_blocks as $inner_block ) { | ||
if ( ( 'core/navigation-link' === $inner_block->name || 'core/home-link' === $inner_block->name || 'core/site-title' === $inner_block->name || 'core/site-logo' === $inner_block->name || 'core/navigation-submenu' === $inner_block->name ) && ! $is_list_open ) { | ||
$is_list_item = in_array( $inner_block->name, $list_item_nav_blocks, true ); | ||
|
||
if ( $is_list_item && ! $is_list_open ) { | ||
$is_list_open = true; | ||
$inner_blocks_html .= '<ul class="wp-block-navigation__container">'; | ||
} | ||
if ( 'core/navigation-link' !== $inner_block->name && 'core/home-link' !== $inner_block->name && 'core/site-title' !== $inner_block->name && 'core/site-logo' !== $inner_block->name && 'core/navigation-submenu' !== $inner_block->name && $is_list_open ) { | ||
|
||
if ( ! $is_list_item && $is_list_open ) { | ||
$is_list_open = false; | ||
$inner_blocks_html .= '</ul>'; | ||
} | ||
|
||
$inner_block_content = $inner_block->render(); | ||
if ( 'core/site-title' === $inner_block->name || ( 'core/site-logo' === $inner_block->name && $inner_block_content ) ) { | ||
$inner_blocks_html .= '<li class="wp-block-navigation-item">' . $inner_block_content . '</li>'; | ||
} else { | ||
$inner_blocks_html .= $inner_block_content; | ||
if ( ! empty( $inner_block_content ) ) { | ||
if ( in_array( $inner_block->name, $needs_list_item_wrapper, true ) ) { | ||
$inner_blocks_html .= '<li class="wp-block-navigation-item">' . $inner_block_content . '</li>'; | ||
} else { | ||
$inner_blocks_html .= $inner_block_content; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of this is refactoring as I was trying to make sense of the render function.
Size Change: +289 B (0%) Total Size: 1.32 MB
ℹ️ View Unchanged
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent work @ajlende This PR fixes recursion in terms of a navigation block containing the same navigation block but unlike the PR it reverts it allows a different navigation block to be nested. However this should be OK, since in my testing if the ref of the nested navigation block is different it will just render, no errors triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a much cleaner solution 👏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for improving the code 👏
What?
Alternative to #46279. Fixes potential infinite recursion due to a circular reference while rendering
core/navigation
blocks that reference themselves within the post_content of thewp_navigation
post.Why?
This approach doesn't modify block content while rendering.
How?
Testing Instructions
Before (validate the bug)
wp_navigation
posts and Classic Menus from your sitepost_content
of yourwp_navigation
post with the following content, being sure to replace%%REPLACE_ME%%
with the ID of thewp_navigation
post YOU just created:After (validate the bug)
Please try this with variations of content being sure that it contains the self-referential Nav block issue.
Testing Instructions for Keyboard
Screenshots or screencast