Skip to content

Commit

Permalink
fix: reusable block isn't resolved inside inner blocks (#251)
Browse files Browse the repository at this point in the history
* fix: reusable block isn't resolved inside inner blocks

* style: phpcs fix

* style: add return type in TraverseHelpers

* style: use TraverseHelpers::class
  • Loading branch information
theodesp authored Jul 2, 2024
1 parent a3e32d5 commit 5c21ce3
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-jars-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wpengine/wp-graphql-content-blocks": patch
---

Bug fix. Reusable block isn't resolved inside innerBlocks.
22 changes: 3 additions & 19 deletions includes/Data/ContentBlocksResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace WPGraphQL\ContentBlocks\Data;

use WPGraphQL\ContentBlocks\Utilities\TraverseHelpers;
use WPGraphQL\Model\Post;

/**
Expand Down Expand Up @@ -54,23 +55,6 @@ public static function resolve_content_blocks( $node, $args, $allowed_block_name
return [];
}

// Resolve reusable blocks - replaces "core/block" with the corresponding block(s) from the reusable ref ID
$new_parsed_blocks = [];
foreach ( $parsed_blocks as $block ) {
if ( 'core/block' === $block['blockName'] && $block['attrs']['ref'] ) {
$post = get_post( $block['attrs']['ref'] );
$reusable_blocks = ! empty( $post->post_content ) ? parse_blocks( $post->post_content ) : null;

if ( ! empty( $reusable_blocks ) ) {
array_push( $new_parsed_blocks, ...$reusable_blocks );
}
} else {
$new_parsed_blocks[] = $block;
}
}

$parsed_blocks = $new_parsed_blocks;

// 1st Level filtering of blocks that are empty
$parsed_blocks = array_filter(
$parsed_blocks,
Expand Down Expand Up @@ -99,12 +83,12 @@ static function ( $parsed_block ) {
},
$parsed_blocks
);

// Resolve reusable blocks - replaces "core/block" with the corresponding block(s) from the reusable ref ID
TraverseHelpers::traverse_blocks( $parsed_blocks, [ TraverseHelpers::class, 'replace_reusable_blocks' ], 0, PHP_INT_MAX );
// Flatten block list here if requested or if 'flat' value is not selected (default)
if ( ! isset( $args['flat'] ) || 'true' == $args['flat'] ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
$parsed_blocks = self::flatten_block_list( $parsed_blocks );
}

// Final level of filtering out blocks not in the allowed list
if ( ! empty( $allowed_block_names ) ) {
$parsed_blocks = array_filter(
Expand Down
48 changes: 48 additions & 0 deletions includes/Utilities/TraverseHelpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Helper functions for traversing the list of blocks
*
* @package WPGraphQL\ContentBlocks\Utilities
*/

namespace WPGraphQL\ContentBlocks\Utilities;

/**
* Class TraverseHelpers
*
* Provides utility functions to traverse and manipulate blocks.
*/
final class TraverseHelpers {
/**
* Traverse blocks and apply a callback with optional depth limit.
*
* @param array &$blocks The blocks to traverse.
* @param callable $callback The callback function to apply to each block.
* @param int $depth The current depth of traversal.
* @param int $max_depth The maximum depth to traverse.
*/
public static function traverse_blocks( &$blocks, $callback, $depth = 0, $max_depth = PHP_INT_MAX ): void {
foreach ( $blocks as &$block ) {
$callback( $block );
if ( ! empty( $block['innerBlocks'] ) && $depth < $max_depth ) {
self::traverse_blocks( $block['innerBlocks'], $callback, $depth + 1, $max_depth );
}
}
}

/**
* Example callback function to replace reusable blocks.
*
* @param array $block The block to potentially replace.
*/
public static function replace_reusable_blocks( &$block ): void {
if ( 'core/block' === $block['blockName'] && isset( $block['attrs']['ref'] ) ) {
$post = get_post( $block['attrs']['ref'] );
$reusable_blocks = ! empty( $post->post_content ) ? parse_blocks( $post->post_content ) : null;

if ( ! empty( $reusable_blocks ) ) {
$block = array_merge( ...$reusable_blocks );
}
}
}
}
2 changes: 1 addition & 1 deletion tests/unit/ContentBlocksResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function tearDown(): void {
public function test_resolve_content_blocks_resolves_reusable_blocks() {
$post_model = new Post( get_post( $this->reusable_post_id ) );
$actual = $this->instance->resolve_content_blocks( $post_model, array( 'flat' => true ) );

// There should return only the non-empty blocks
$this->assertEquals( 3, count( $actual ) );
$this->assertEquals( 'core/columns', $actual[0]['blockName'] );
Expand Down
85 changes: 85 additions & 0 deletions tests/unit/TraverseHelpersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace WPGraphQL\ContentBlocks\Unit;

use PHPUnit\Framework\TestCase;
use WPGraphQL\ContentBlocks\Utilities\TraverseHelpers;

class TraverseHelpersTest extends PluginTestCase {
public $post_id;
public function setUp(): void {
parent::setUp();
global $wpdb;

$this->post_id = wp_insert_post(
array(
'post_title' => 'Post Title',
'post_content' => preg_replace(
'/\s+/',
' ',
trim(
'
<!-- wp:paragraph -->
<p class="has-background" style="background-color:#a62929">Test</p>
<!-- /wp:paragraph -->'
)
),
'post_status' => 'publish',
)
);
}

public function tearDown(): void {
// your tear down methods here
parent::tearDown();
wp_delete_post( $this->post_id, true );
}
public function testTraverseBlocks() {
// Sample blocks data
$blocks = [
[
'blockName' => 'core/group',
'attrs' => [],
'innerBlocks' => [
[
'blockName' => 'core/block',
'attrs' => [ 'ref' => $this->post_id ],
'innerBlocks' => []
]
]
],
[
'blockName' => 'core/block',
'attrs' => [ 'ref' => $this->post_id ],
'innerBlocks' => []
]
];

// Expected result after replacing reusable blocks
$expected = [
[
'blockName' => 'core/group',
'attrs' => [],
'innerBlocks' => [
[
'blockName' => 'core/paragraph',
'attrs' => [],
'innerBlocks' => [],
'innerHTML' => ' <p class="has-background" style="background-color:#a62929">Test</p> ',
'innerContent' => [ 0 => ' <p class="has-background" style="background-color:#a62929">Test</p> ']
]
]
],
[
'blockName' => 'core/paragraph',
'attrs' => [],
'innerBlocks' => [],
'innerHTML' => ' <p class="has-background" style="background-color:#a62929">Test</p> ',
'innerContent' => [ 0 => ' <p class="has-background" style="background-color:#a62929">Test</p> ']
]
];

TraverseHelpers::traverse_blocks( $blocks, [ TraverseHelpers::class, 'replace_reusable_blocks' ], 0, PHP_INT_MAX );
$this->assertEquals( $expected, $blocks );
}
}

0 comments on commit 5c21ce3

Please sign in to comment.