-
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: Recursively remove Navigation block’s from appearing inside Navigation block on front of site #46279
Conversation
I can confirm that this fixes the bug following the testing steps, I'm going to try with more blocks |
return isset( $block['blockName'] ); | ||
} | ||
function( $carry, $block ) { | ||
if ( isset( $block['blockName'] ) && 'core/navigation' !== $block['blockName'] ) { |
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.
Should we use an array of allowedBlocks here? There's this array.
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.
Updated...but is there any danger of breaking sites that might utilise 3rd party blocks here?
@@ -595,7 +607,8 @@ function render_block_core_navigation( $attributes, $content, $block ) { | |||
|
|||
// 'parse_blocks' includes a null block with '\n\n' as the content when | |||
// it encounters whitespace. This code strips it. |
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.
We should update this comment.
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.
Actually this comment is fine, now I read it more carefully.
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.
LGTM
Size Change: +92 B (0%) Total Size: 1.33 MB
ℹ️ View Unchanged
|
…n block on front of site (WordPress#46279) * Recursively remove Navigation block’s from appearing inside Navigation block content * Fix lint * Use whitelist approach * add a dupliation warning comment * Update packages/block-library/src/navigation/index.php * pacify linter Co-authored-by: Ben Dwyer <[email protected]>
* Revert "Handle innerContent too when removing innerBlocks (#46377)" This reverts commit 181b383. * Revert "Add social link singular to list of blocks to be allowed (#46374)" This reverts commit 394590b. * Revert "Recursively remove Navigation block’s from appearing inside Navigation block on front of site (#46279)" This reverts commit afc8b42. * Refactor ul code for readability * Refactor li wrapper conditional * Prevent rendering nav refs that have already been seen * Fix PHP lint
@getdave I'm guessing it wasn't obvious there's a mechanism built-in to block rendering that lets us accomplish block filtering without writing our own recursive iterators and without mangling the blocks, but as per my comment in WordPress/wordpress-develop#3731, I might suggest we try using As a note, function block_core_navigation_restrictor( $pre_render, $block ) {
switch ( $block['blockName' ) {
case 'core/navigation-link':
case 'core/search':
case 'core/social-links':
case 'core/page-list':
case 'core/spacer':
case 'core/home-link':
case 'core/site-title':
case 'core/site-logo':
case 'core/navigation-submenu':
// don't touch these blocks
return null;
}
// erase any other block
return '';
}
function render_block_core_navigation( $attributes, $content, $block ) {
// Prevent unintentional infinite loops and reject attempts to
// use the nav block in a way we didn't prescribe or anticipate.
add_filter( 'pre_render_block', 'block_core_navigation_restrictor', 10, 2 );
$rendered = block_core_navigation_render_for_real( $attributes, $content, $block );
remove_filter( 'pre_render_block', 'block_core_navigation_restrictor' );
return $rendered;
} I didn't try this code, but I hope it demonstrates enough to look at an alternative approach. The filters in the render pipeline are each designed to augment the rendering process to support things like what you are wanting and to do so safely. |
return isset( $block['blockName'] ); | ||
} | ||
function( $carry, $block ) use ( $allowed_blocks ) { | ||
if ( isset( $block['blockName'] ) && in_array( $block['blockName'], $allowed_blocks, true ) ) { |
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 is I guess performing the intended job, but this not only eliminates those "null" blocks but also any raw HTML someone has entered into the post/template. those \n\n
come from the fact that Gutenberg allows arbitrary HTML in its posts and the block serializer chooses to add whitespace, but if someone wants to add a special logo, custom element, or other HTML to their menu, this will also wipe that out.
What?
Fixes potential rendering recursion (infinite loop) whereby
core/navigation
blocks appear within the post_content ofwp_navigation
posts.Why?
It shouldn't be possible for this to happen as Navigation block's aren't valid as inner blocks of Navigation block's
However things do happen...
When this occurs it results in the potential scenario whereby the block recursively renders because it parses the block's from the
wp_navigation
which contain a reference to itself.For example if I created a
wp_navigation
post containing acore/navigation
block with itsref
attribute set to the ID of thewp_navigation
post I just created then it will continually re-render itself.How?
This PR recursively filters out
core/navigation
from the list of block's that are allowed to be parsed fromwp_navigation
posts. This ensures this scenario cannot occur as the block is removed before it can be rendered.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