diff --git a/.changeset/tiny-news-warn.md b/.changeset/tiny-news-warn.md new file mode 100644 index 00000000..0c106145 --- /dev/null +++ b/.changeset/tiny-news-warn.md @@ -0,0 +1,5 @@ +--- +"@wpengine/wp-graphql-content-blocks": minor +--- + +feat: add support for resolving Block Patterns diff --git a/includes/Data/ContentBlocksResolver.php b/includes/Data/ContentBlocksResolver.php index 2a61e6c1..fbf07786 100644 --- a/includes/Data/ContentBlocksResolver.php +++ b/includes/Data/ContentBlocksResolver.php @@ -151,6 +151,8 @@ private static function handle_do_block( array $block ): ?array { $block = self::populate_reusable_blocks( $block ); + $block = self::populate_pattern_inner_blocks( $block ); + // Prepare innerBlocks. if ( ! empty( $block['innerBlocks'] ) ) { $block['innerBlocks'] = self::handle_do_blocks( $block['innerBlocks'] ); @@ -208,6 +210,32 @@ private static function populate_reusable_blocks( array $block ): array { return array_merge( ...$parsed_blocks ); } + /** + * Populates the pattern innerBlocks with the blocks from the pattern. + * + * @param array $block The block to populate. + * @return array The populated block. + */ + private static function populate_pattern_inner_blocks( array $block ): array { + // Bail if not WP 6.6 or later. + if ( ! function_exists( 'resolve_pattern_blocks' ) ) { + return $block; + } + + if ( 'core/pattern' !== $block['blockName'] || ! isset( $block['attrs']['slug'] ) ) { + return $block; + } + + $resolved_patterns = resolve_pattern_blocks( [ $block ] ); + + if ( empty( $resolved_patterns ) ) { + return $block; + } + + $block['innerBlocks'] = $resolved_patterns; + return $block; + } + /** * Flattens a list blocks into a single array * diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index e9331a02..ad509119 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -349,4 +349,68 @@ protected function assertEqualBlocks( $expected, $actual, $message = '' ) { $this->assertEqualBlocks( $expected_inner_block, $actual_inner_blocks[ $index ], $message ); } } + + /** + * Tests that pattern inner blocks are resolved correctly. + */ + public function test_resolve_content_blocks_resolves_pattern_inner_blocks() { + // Skip if pattern resolution functionality is not supported. + if ( ! function_exists( 'resolve_pattern_blocks' ) ) { + $this->markTestSkipped( 'Pattern block resolution not supported in this WordPress version.' ); + } + + // Create a pattern + $pattern_name = 'test/pattern-blocks'; + $pattern_content = ' + +

Pattern Paragraph

+ + +

Pattern Heading

+ + '; + + // Register the pattern. + register_block_pattern( + $pattern_name, + [ + 'title' => 'Test Pattern', + 'content' => $pattern_content, + ] + ); + + // Update post content to include pattern block. + $post_content = ' + + '; + + wp_update_post( + [ + 'ID' => $this->post_id, + 'post_content' => $post_content, + ] + ); + + $post_model = new Post( get_post( $this->post_id ) ); + + // Resolve blocks as nested. + $resolved_blocks = $this->instance->resolve_content_blocks( $post_model, [ 'flat' => false ] ); + + $this->assertCount( 1, $resolved_blocks, 'There should be only one top-level block (pattern).' ); + $this->assertEquals( 'core/pattern', $resolved_blocks[0]['blockName'] ); + $this->assertCount( 2, $resolved_blocks[0]['innerBlocks'], 'There should be two inner blocks in the pattern.' ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['innerBlocks'][0]['blockName'] ); + $this->assertEquals( 'core/heading', $resolved_blocks[0]['innerBlocks'][1]['blockName'] ); + + // Resolve blocks as flat. + $resolved_flat_blocks = $this->instance->resolve_content_blocks( $post_model, [ 'flat' => true ] ); + + $this->assertCount( 3, $resolved_flat_blocks, 'There should be three blocks when flattened.' ); + $this->assertEquals( 'core/pattern', $resolved_flat_blocks[0]['blockName'] ); + $this->assertEquals( 'core/paragraph', $resolved_flat_blocks[1]['blockName'] ); + $this->assertEquals( 'core/heading', $resolved_flat_blocks[2]['blockName'] ); + + // Cleanup: Unregistering the pattern. + unregister_block_pattern( $pattern_name ); + } }