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 Block: Recursively remove Navigation block’s from appearing inside Navigation block on front of site #46279

Merged
merged 6 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useMemo } from '@wordpress/element';
*/
import PlaceholderPreview from './placeholder/placeholder-preview';

// This list is duplicated in packages/block-library/src/navigation/index.php
const ALLOWED_BLOCKS = [
'core/navigation-link',
'core/search',
Expand Down
48 changes: 37 additions & 11 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -384,20 +384,45 @@ function block_core_navigation_get_most_recently_published_navigation() {
}

/**
* Filter out empty "null" blocks from the block list.
* 'parse_blocks' includes a null block with '\n\n' as the content when
* Recursively filter out blocks from the block list that are not whitelisted.
* This list of exclusions includes:
* - The Navigation block itself (results in recursion).
* - empty "null" blocks from the block list.
* - other blocks that are not yet handled.
*
* Note: 'parse_blocks' includes a null block with '\n\n' as the content when
* it encounters whitespace. This is not a bug but rather how the parser
* is designed.
*
* @param array $parsed_blocks the parsed blocks to be normalized.
* @return array the normalized parsed blocks.
* @param array $parsed_blocks the parsed blocks to be filtered.
* @return array the filtered parsed blocks.
*/
function block_core_navigation_filter_out_empty_blocks( $parsed_blocks ) {
$filtered = array_filter(
function block_core_navigation_filter_out_invalid_blocks( $parsed_blocks ) {
// This list is duplicated in /packages/block-library/src/navigation/edit/inner-blocks.js
$allowed_blocks = array(
'core/navigation-link',
'core/search',
'core/social-links',
'core/page-list',
'core/spacer',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
);

$filtered = array_reduce(
$parsed_blocks,
function( $block ) {
return isset( $block['blockName'] );
}
function( $carry, $block ) use ( $allowed_blocks ) {
if ( isset( $block['blockName'] ) && in_array( $block['blockName'], $allowed_blocks, true ) ) {
Copy link
Member

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.

if ( $block['innerBlocks'] ) {
$block['innerBlocks'] = block_core_navigation_filter_out_invalid_blocks( $block['innerBlocks'] );
}
$carry[] = $block;
}
return $carry;
},
array()
);

// Reset keys.
Expand Down Expand Up @@ -437,7 +462,8 @@ function block_core_navigation_get_fallback_blocks() {

// Use the first non-empty Navigation as fallback if available.
if ( $navigation_post ) {
$maybe_fallback = block_core_navigation_filter_out_empty_blocks( parse_blocks( $navigation_post->post_content ) );

$maybe_fallback = block_core_navigation_filter_out_invalid_blocks( parse_blocks( $navigation_post->post_content ) );

// Normalizing blocks may result in an empty array of blocks if they were all `null` blocks.
// In this case default to the (Page List) fallback.
Expand Down Expand Up @@ -595,7 +621,7 @@ 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.
Copy link
Contributor

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.

Copy link
Contributor

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.

$compacted_blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
$compacted_blocks = block_core_navigation_filter_out_invalid_blocks( $parsed_blocks );

// TODO - this uses the full navigation block attributes for the
// context which could be refined.
Expand Down