From bababb94e2dc4e113ca952a8c3e4fe697c25fef5 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Wed, 24 Jan 2024 17:10:09 +0100 Subject: [PATCH] Update Navigation block to render hooked inner blocks --- .../wordpress-6.5/navigation-block-hooks.php | 112 ++++++++++++++++++ lib/load.php | 1 + .../block-library/src/navigation/index.php | 25 +++- 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 lib/compat/wordpress-6.5/navigation-block-hooks.php diff --git a/lib/compat/wordpress-6.5/navigation-block-hooks.php b/lib/compat/wordpress-6.5/navigation-block-hooks.php new file mode 100644 index 0000000000000..d7a0e888622d2 --- /dev/null +++ b/lib/compat/wordpress-6.5/navigation-block-hooks.php @@ -0,0 +1,112 @@ += 6.4 +// that have not yet been included in Gutenberg's compatibility layer (lib/compat/wordpress-6.4/block-hooks.php). +if ( function_exists( 'get_hooked_blocks' ) ) { + add_filter( 'rest_prepare_wp_navigation', 'gutenberg_hook_blocks_into_core_navigation_rest_response', 10, 3 ); + add_action( 'rest_insert_wp_navigation', 'gutenberg_update_ignore_hooked_blocks_meta_core_navigation', 10, 3 ); +} + +/** + * Updates the post meta with the list of ignored hooked blocks when the navigation is created or updated via the REST API. + * + * @param WP_Post $post Post object. + */ +function gutenberg_update_ignore_hooked_blocks_meta_core_navigation( $post ) { + if ( ! isset( $post->ID ) ) { + return; + } + + // We run the Block Hooks mechanism so it will return the list of ignored hooked blocks + // in the mock root Navigation block's metadata attribute. + // We ignore the rest of the returned `$markup`; `$post->post_content` already has the hooked + // blocks inserted, whereas `$markup` will have them inserted twice. + $blocks = parse_blocks( $post->post_content ); + $markup = gutenberg_insert_hooked_blocks_into_navigation_block( $blocks, $post ); + $root_nav_block = parse_blocks( $markup )[0]; + $ignored_hooked_blocks = isset( $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] ) + ? $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] + : array(); + + if ( ! empty( $ignored_hooked_blocks ) ) { + $existing_ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true ); + if ( ! empty( $existing_ignored_hooked_blocks ) ) { + $existing_ignored_hooked_blocks = json_decode( $existing_ignored_hooked_blocks, true ); + $ignored_hooked_blocks = array_unique( array_merge( $ignored_hooked_blocks, $existing_ignored_hooked_blocks ) ); + } + update_post_meta( $post->ID, '_wp_ignored_hooked_blocks', json_encode( $ignored_hooked_blocks ) ); + } +} + +/** + * Hooks into the REST API response for the core/navigation block and adds the first and last inner blocks. + * + * @param WP_REST_Response $response The response object. + * @param WP_Post $post Post object. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response The response object. + */ +function gutenberg_hook_blocks_into_core_navigation_rest_response( $response, $post ) { + if ( ! isset( $response->data['content']['raw'] ) || ! isset( $response->data['content']['rendered'] ) ) { + return $response; + } + $parsed_blocks = parse_blocks( $response->data['content']['raw'] ); + $content = gutenberg_insert_hooked_blocks_into_navigation_block( $parsed_blocks, $post ); + + // Remove mock Navigation block wrapper. + $start = strpos( $content, '-->' ) + strlen( '-->' ); + $end = strrpos( $content, '