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

Create a fallback navigation menu as one time operation on install and Theme switch #48625

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1e5412a
Navigation: Always create a fallback navigation menu on every page load
scruffian Mar 1, 2023
78ae0b1
Add basic unit tests
getdave Mar 1, 2023
83d1ac3
Fix Classic Meny fallback to use Menu title not slug
getdave Mar 1, 2023
d68c93a
Add tests for Classic Menu
getdave Mar 1, 2023
a139d85
Refactor assertions to expected actual format
getdave Mar 1, 2023
5e254c1
Cleanup test file
getdave Mar 1, 2023
238d956
Add checks for total Navigation Posts created
getdave Mar 1, 2023
ef16a4c
Add test to cover prefering existing Nav Menu over Classic Menu
getdave Mar 1, 2023
4c8f78d
Rename and improve function comment
getdave Mar 1, 2023
fc8991d
Add tests for retrieving fallback blocks
getdave Mar 1, 2023
ff12582
Ensure different post_content for different menus
getdave Mar 1, 2023
c20ec7b
Test filtering empty blocks
getdave Mar 1, 2023
1138e30
Fix parse error in unit tests
getdave Mar 1, 2023
1a82aaf
Fix PHP CS warnings
getdave Mar 1, 2023
a31eec4
Fix more PHPCS warnings
getdave Mar 1, 2023
ec6d2ad
fix linting issues'
scruffian Mar 2, 2023
5665b74
change the hooks we create the fallback on
scruffian Mar 2, 2023
e13b4f3
Move hooks to run on one time operations and ensure only run for bloc…
getdave Mar 3, 2023
da7f46d
Fix tests
getdave Mar 3, 2023
a5a3651
Add tests for theme switch hook auto-creation
getdave Mar 3, 2023
84bd746
Check that there are no menus before Theme switch test
getdave Mar 3, 2023
f6dab81
Add test for wp_install
getdave Mar 6, 2023
641a0ed
Update comment to indicate page list is not an ideal scenario
getdave Mar 6, 2023
02c1353
Add test to validate menus not created when switching to a block Theme
getdave Mar 6, 2023
11ab9db
Revert whitespace changes
getdave Mar 6, 2023
3a64b4d
Apply PHPUnit annotations from review
getdave Mar 6, 2023
d59cde3
Remove unnecessary return and annotation function
getdave Mar 6, 2023
a9c7248
Try adding messages to all assertions
getdave Mar 6, 2023
e0d8d7c
Add @covers annotation
getdave Mar 6, 2023
dff1682
Apply correct annotations to test class
getdave Mar 6, 2023
8604f51
Rename test file and add group annotation
getdave Mar 6, 2023
249fd74
Fix PHPCS unused variable
getdave Mar 6, 2023
2b2795e
Normalise assertion
getdave Mar 6, 2023
61f9a8e
Fix tests
getdave Mar 6, 2023
0c8bbe2
Refactor to avoid requiring a return value from the hooked creation f…
getdave Mar 6, 2023
3f164c7
Refactor creation functions to SRP.
getdave Mar 6, 2023
7722010
Improve doc blocks
getdave Mar 6, 2023
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
66 changes: 0 additions & 66 deletions packages/block-library/src/navigation/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { speak } from '@wordpress/a11y';
import { createBlock, getBlockType } from '@wordpress/blocks';
import { close, Icon } from '@wordpress/icons';

/**
Expand Down Expand Up @@ -308,71 +307,6 @@ function Navigation( {
// that automatically saves the menu as an entity when changes are made to the inner blocks.
const hasUnsavedBlocks = hasUncontrolledInnerBlocks && ! isEntityAvailable;

useEffect( () => {
if (
ref ||
! hasResolvedNavigationMenus ||
isConvertingClassicMenu ||
fallbackNavigationMenus?.length > 0 ||
hasUnsavedBlocks
) {
return;
}

// If there's non fallback navigation menus and
// a classic menu with a `primary` location or slug,
// then create a new navigation menu based on it.
// Otherwise, use the most recently created classic menu.
if ( classicMenus?.length ) {
const primaryMenus = classicMenus.filter(
( classicMenu ) =>
classicMenu.locations.includes( 'primary' ) ||
classicMenu.slug === 'primary'
);

if ( primaryMenus.length ) {
convertClassicMenu(
primaryMenus[ 0 ].id,
primaryMenus[ 0 ].name,
'publish'
);
} else {
classicMenus.sort( ( a, b ) => {
return b.id - a.id;
} );
convertClassicMenu(
classicMenus[ 0 ].id,
classicMenus[ 0 ].name,
'publish'
);
}
} else {
// If there are no fallback navigation menus and no classic menus,
// then create a new navigation menu.

// Check that we have a page-list block type.
let defaultBlocks = [];
if ( getBlockType( 'core/page-list' ) ) {
defaultBlocks = [ createBlock( 'core/page-list' ) ];
}

createNavigationMenu(
'Navigation', // TODO - use the template slug in future
defaultBlocks,
'publish'
);
}
}, [
hasResolvedNavigationMenus,
hasUnsavedBlocks,
classicMenus,
convertClassicMenu,
createNavigationMenu,
fallbackNavigationMenus?.length,
isConvertingClassicMenu,
ref,
] );

const navRef = useRef();

// The standard HTML5 tag for the block wrapper.
Expand Down
100 changes: 68 additions & 32 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,26 +325,31 @@ function block_core_navigation_get_classic_menu_fallback_blocks( $classic_nav_me
}

/**
* If there's a the classic menu then use it as a fallback.
* Checks for a Classic Menu and attempts to convert into a block-based
* Navigation menu.
*
* @return array the normalized parsed blocks.
* @return int|WP_Error The Navigation menu post ID on success. A WP_Error on failure.
*/
function block_core_navigation_maybe_use_classic_menu_fallback() {
// See if we have a classic menu.
function block_core_navigation_create_classic_menu_fallback() {
// See if we have a Classic menu.
$classic_nav_menu = block_core_navigation_get_classic_menu_fallback();

// Exit early if one does not exist.
if ( ! $classic_nav_menu ) {
return;
return new WP_Error( 'no_classic_menu', __( 'No classic menu exists to convert to a block.' ) );
}

// If we have a classic menu then convert it to blocks.
// If we have a Classic menu then convert it to blocks.
$classic_nav_menu_blocks = block_core_navigation_get_classic_menu_fallback_blocks( $classic_nav_menu );

// If it's empty then exit early.
if ( empty( $classic_nav_menu_blocks ) ) {
return;
return new WP_Error( 'no_classic_menu', __( 'Classic menu is empty or could not be converted to blocks.' ) );
}

// Create a new navigation menu from the classic menu.
$return_errors = true;

// Create a new Navigation menu from the Classic menu blocks.
$wp_insert_post_result = wp_insert_post(
array(
'post_content' => $classic_nav_menu_blocks,
Expand All @@ -353,15 +358,10 @@ function block_core_navigation_maybe_use_classic_menu_fallback() {
'post_status' => 'publish',
'post_type' => 'wp_navigation',
),
true // So that we can check whether the result is an error.
$return_errors // So that we can check whether the result is an error.
);

if ( is_wp_error( $wp_insert_post_result ) ) {
return;
}

// Fetch the most recently published navigation which will be the classic one created above.
return block_core_navigation_get_most_recently_published_navigation();
return $wp_insert_post_result;
}

/**
Expand Down Expand Up @@ -432,11 +432,12 @@ function block_core_navigation_block_contains_core_navigation( $inner_blocks ) {
}

/**
* Create and returns a navigation menu containing a page-list as a fallback.
* Creates a navigation menu containing default fallback content.
* (a page-list if registered).
*
* @return array the newly created navigation menu.
* @return int|WP_Error The post ID on success. A WP_Error on failure.
*/
function block_core_navigation_get_default_pages_fallback() {
function block_core_navigation_create_default_fallback() {
$registry = WP_Block_Type_Registry::get_instance();

// If `core/page-list` is not registered then use empty blocks.
Expand All @@ -454,13 +455,59 @@ function block_core_navigation_get_default_pages_fallback() {
true // So that we can check whether the result is an error.
);

if ( is_wp_error( $wp_insert_post_result ) ) {
return $wp_insert_post_result;
}

/**
* Creates an appropriate fallback Navigation Menu (`wp_navigation` Post)
* to be used by the Navigation block.
*
* Behaviour:
* 1. If there is a Navigation menu already then use it.
* 2. If there is a Classic menu then convert it to a Navigation menu.
* 3. If there is no Navigation menu and no Classic menu then create a default menu.
*
* The fallback menu is only created if the theme is a block theme.
*
* @return void
*/
function block_core_navigation_create_fallback() {
$should_skip = apply_filters( 'block_core_navigation_skip_fallback', false );
getdave marked this conversation as resolved.
Show resolved Hide resolved

if ( $should_skip ) {
return;
}

// Fetch the most recently published navigation which will be the default one created above.
return block_core_navigation_get_most_recently_published_navigation();
// Don't create a fallback if the theme is not a block theme.
if ( ! wp_is_block_theme() ) {
return;
}

// Get the most recently published Navigation menu.
$existing_navigation_menu = block_core_navigation_get_most_recently_published_navigation();

// If there is already a Navigation menu then exit.
if ( $existing_navigation_menu ) {
return;
}

// If there are no Navigation menus then try to find a Classic menu
// and attempt to convert it into a Navigation menu.
$converted_classic_menu_id = block_core_navigation_create_classic_menu_fallback();

// If the conversion + creation was successful then exit.
if ( ! is_wp_error( $converted_classic_menu_id ) ) {
return;
}

// If the Classic menu process did not result in a post
// then default to creating a default fallback Navigaiton menu.
block_core_navigation_create_default_fallback();
}
// Run on switching Theme and when installing WP for the first time.
add_action( 'switch_theme', 'block_core_navigation_create_fallback' );
add_action( 'wp_install', 'block_core_navigation_create_fallback' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Discussing away from Github with @azaozz I'm concerned that hooking to wp_install might be a bad option because it's likely to mean all sites will get a wp_navigation even if no block Theme is active.



/**
* Retrieves the appropriate fallback to be used on the front of the
Expand All @@ -475,17 +522,6 @@ function block_core_navigation_get_fallback_blocks() {
// Get the most recently published Navigation post.
$navigation_post = block_core_navigation_get_most_recently_published_navigation();

// If there are no navigation posts then try to find a classic menu
// and convert it into a block based navigation menu.
if ( ! $navigation_post ) {
$navigation_post = block_core_navigation_maybe_use_classic_menu_fallback();
}

// If there are no navigation posts then default to a list of Pages.
if ( ! $navigation_post ) {
$navigation_post = block_core_navigation_get_default_pages_fallback();
}

// Use the first non-empty Navigation as fallback, there should always be one.
if ( $navigation_post ) {
$parsed_blocks = parse_blocks( $navigation_post->post_content );
Expand Down
Loading