From e5b6b78b4cf2a78f747797eff71c2286bef2ddfe Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Mon, 4 Mar 2024 16:56:18 +0100 Subject: [PATCH 1/9] Navigation Block: Add basic test coverage for Block Hooks --- .../block-navigation-block-hooks-test.php | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 phpunit/blocks/block-navigation-block-hooks-test.php diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php new file mode 100644 index 0000000000000..c5edada375f01 --- /dev/null +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -0,0 +1,76 @@ +'; + + self::$navigation_post = self::factory()->post->create_and_get( + array( + 'post_type' => 'wp_navigation', + 'post_title' => 'Navigation Menu', + 'post_content' => self::$original_markup, + ) + ); + } + + /** + * Tear down each test method. + */ + public function tear_down() { + $registry = WP_Block_Type_Registry::get_instance(); + + if ( $registry->is_registered( 'tests/my-block' ) ) { + $registry->unregister( 'tests/my-block' ); + } + + parent::tear_down(); + } + + /** + * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta + */ + public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { + register_block_type( + 'tests/my-block', + array( + 'block_hooks' => array( + 'core/navigation' => 'last_child', + ), + ) + ); + + $post = get_post( self::$navigation_post ); + + gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); + $this->assertSame( self::$original_markup . '', $post->post_content ); + $this->assertSame( array( 'tests/my-block' ), get_post_meta( $post, '_wp_ignored_hooked_blocks' ) ); + } +} From 25285414a0420e58d94a6546faae1c86ee84a47d Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 09:14:08 +0100 Subject: [PATCH 2/9] Fix post meta assertion --- phpunit/blocks/block-navigation-block-hooks-test.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index c5edada375f01..cf0796253fcb9 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -70,7 +70,11 @@ public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { $post = get_post( self::$navigation_post ); gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); + $this->assertSame( self::$original_markup . '', $post->post_content ); - $this->assertSame( array( 'tests/my-block' ), get_post_meta( $post, '_wp_ignored_hooked_blocks' ) ); + $this->assertSame( + array( 'tests/my-block' ), + json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ) + ); } } From 911d113447c02931aaaa45ed71122be3cf7e3778 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 09:32:23 +0100 Subject: [PATCH 3/9] Get assertion to pass --- phpunit/blocks/block-navigation-block-hooks-test.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index cf0796253fcb9..c22307278a9a6 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -71,7 +71,10 @@ public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); - $this->assertSame( self::$original_markup . '', $post->post_content ); + // We expect the '&' character to be replaced with its unicode representation. + $expected_markup = str_replace( '&', '\u0026amp;', self::$original_markup ); + + $this->assertSame( $expected_markup, $post->post_content ); $this->assertSame( array( 'tests/my-block' ), json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ) From d08b830b7193629856c1f32e4bdd29f31ecf8846 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 09:33:17 +0100 Subject: [PATCH 4/9] Add assertion for get_the_content() --- phpunit/blocks/block-navigation-block-hooks-test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index c22307278a9a6..a4b53ee79c56c 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -75,6 +75,7 @@ public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { $expected_markup = str_replace( '&', '\u0026amp;', self::$original_markup ); $this->assertSame( $expected_markup, $post->post_content ); + $this->assertSame( $expected_markup, get_the_content( null, false, self::$navigation_post->ID ) ); $this->assertSame( array( 'tests/my-block' ), json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ) From 89ecc65474ee86dc3ad915a2ca2c7d0f774c14ff Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 11:45:17 +0100 Subject: [PATCH 5/9] Use filter instead of action to avoid calling wp_update_post twice --- .../block-library/src/navigation/index.php | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index 1d73d09bbd1fb..cc3ee08e78202 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1458,7 +1458,7 @@ function block_core_navigation_set_ignored_hooked_blocks_metadata( $inner_blocks /** * 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. + * @param stdClass $post Post object. */ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { // We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into @@ -1480,14 +1480,8 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { update_post_meta( $post->ID, '_wp_ignored_hooked_blocks', json_encode( $ignored_hooked_blocks ) ); } - $serialized_inner_blocks = block_core_navigation_remove_serialized_parent_block( $markup ); - - wp_update_post( - array( - 'ID' => $post->ID, - 'post_content' => $serialized_inner_blocks, - ) - ); + $post->post_content = block_core_navigation_remove_serialized_parent_block( $markup ); + return $post; } // Before adding our filter, we verify if it's already added in Core. @@ -1497,8 +1491,15 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { // Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5 // that are not present in Gutenberg's WP 6.5 compatibility layer. -if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { - add_action( 'rest_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 3 ); +if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { + add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 2 ); +} + +// Previous versions of Gutenberg and WordPress 6.5 Betas were attaching the block_core_navigation_update_ignore_hooked_blocks_meta +// function to the `rest_insert_wp_navigation` _action_ (rather than the `rest_pre_insert_wp_navigation` _filter_). +// To avoid collisions, we need to remove the filter from that action if it's present. +if ( has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { + remove_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback, 10 ); } /** From 6b263d44fc69ee5fd09b52f250bd3f1a01184de5 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 12:08:29 +0100 Subject: [PATCH 6/9] Pass WP_Post object as context --- packages/block-library/src/navigation/index.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index cc3ee08e78202..b4bda262495bc 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1464,7 +1464,12 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { // We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into // all anchor blocks. For the root level, we create a mock Navigation and extract them from there. $blocks = parse_blocks( $post->post_content ); - $markup = block_core_navigation_set_ignored_hooked_blocks_metadata( $blocks, $post ); + + // Block Hooks logic requires a `WP_Post` object (rather than the `stdClass` with the updates that + // we're getting from the `rest_pre_insert_wp_navigation` filter) as its second argument (to be + // used as context for hooked blocks insertion). + // We thus have to look it up from the DB,based on `$post->ID`. + $markup = block_core_navigation_set_ignored_hooked_blocks_metadata( $blocks, get_post( $post->ID ) ); $root_nav_block = parse_blocks( $markup )[0]; $ignored_hooked_blocks = isset( $root_nav_block['attrs']['metadata']['ignoredHookedBlocks'] ) From 97f900eb395e9f0c3bad452a231fca4943787d8b Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:28:27 +0100 Subject: [PATCH 7/9] Set accepted_args to default of 1 --- packages/block-library/src/navigation/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php index b4bda262495bc..18637d9ad3ee4 100644 --- a/packages/block-library/src/navigation/index.php +++ b/packages/block-library/src/navigation/index.php @@ -1497,7 +1497,7 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) { // Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5 // that are not present in Gutenberg's WP 6.5 compatibility layer. if ( function_exists( 'set_ignored_hooked_blocks_metadata' ) && ! has_filter( 'rest_pre_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) { - add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 2 ); + add_filter( 'rest_pre_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10 ); } // Previous versions of Gutenberg and WordPress 6.5 Betas were attaching the block_core_navigation_update_ignore_hooked_blocks_meta From 68fe05348ab68bd35c959297c4db8cbc06b61841 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 12:48:28 +0100 Subject: [PATCH 8/9] Fix unit test --- .../block-navigation-block-hooks-test.php | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index a4b53ee79c56c..765700653650c 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -30,13 +30,13 @@ class Block_Navigation_Block_Hooks_Test extends WP_UnitTestCase { * Setup method. */ public static function wpSetUpBeforeClass() { - self::$original_markup = ''; + //self::$original_markup = ''; self::$navigation_post = self::factory()->post->create_and_get( array( 'post_type' => 'wp_navigation', 'post_title' => 'Navigation Menu', - 'post_content' => self::$original_markup, + 'post_content' => 'Original content', ) ); } @@ -57,7 +57,7 @@ public function tear_down() { /** * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta */ - public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { + public function test_block_core_navigation_update_ignore_hooked_blocks_meta_preserves_entities() { register_block_type( 'tests/my-block', array( @@ -67,18 +67,25 @@ public function test_block_core_navigation_update_ignore_hooked_blocks_meta() { ) ); - $post = get_post( self::$navigation_post ); + $original_markup = ''; + $post = new stdClass(); + $post->ID = self::$navigation_post->ID; + $post->post_content = $original_markup; - gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); + $post = gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta( $post ); // We expect the '&' character to be replaced with its unicode representation. - $expected_markup = str_replace( '&', '\u0026amp;', self::$original_markup ); + $expected_markup = str_replace( '&', '\u0026', $original_markup ); - $this->assertSame( $expected_markup, $post->post_content ); - $this->assertSame( $expected_markup, get_the_content( null, false, self::$navigation_post->ID ) ); + $this->assertSame( + $expected_markup, + $post->post_content, + 'Post content did not match expected markup with entities escaped.' + ); $this->assertSame( array( 'tests/my-block' ), - json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ) + json_decode( get_post_meta( self::$navigation_post->ID, '_wp_ignored_hooked_blocks', true ), true ), + 'Block was not added to ignored hooked blocks metadata.' ); } } From b0a04e9580c4bcce28bacd6cbf9355209a701fe2 Mon Sep 17 00:00:00 2001 From: Bernie Reiter Date: Tue, 5 Mar 2024 12:52:35 +0100 Subject: [PATCH 9/9] Skip test on old WP versions --- phpunit/blocks/block-navigation-block-hooks-test.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpunit/blocks/block-navigation-block-hooks-test.php b/phpunit/blocks/block-navigation-block-hooks-test.php index 765700653650c..e0e7bd45cfc17 100644 --- a/phpunit/blocks/block-navigation-block-hooks-test.php +++ b/phpunit/blocks/block-navigation-block-hooks-test.php @@ -58,6 +58,10 @@ public function tear_down() { * @covers ::gutenberg_block_core_navigation_update_ignore_hooked_blocks_meta */ public function test_block_core_navigation_update_ignore_hooked_blocks_meta_preserves_entities() { + if ( ! function_exists( 'set_ignored_hooked_blocks_metadata' ) ) { + $this->markTestSkipped( 'Test skipped on WordPress versions that do not included required Block Hooks functionalit.' ); + } + register_block_type( 'tests/my-block', array(