diff --git a/plugins/woocommerce/src/Admin/BlockTemplates/BlockInterface.php b/plugins/woocommerce/src/Admin/BlockTemplates/BlockInterface.php index 0302272f0b2..e4c4a382ab9 100644 --- a/plugins/woocommerce/src/Admin/BlockTemplates/BlockInterface.php +++ b/plugins/woocommerce/src/Admin/BlockTemplates/BlockInterface.php @@ -62,22 +62,20 @@ interface BlockInterface { /** * Get the parent container that the block belongs to. - * - * @throws \RuntimeException If the block does not have a parent. */ - public function &get_parent(): ?ContainerInterface; + public function &get_parent(): ContainerInterface; /** * Get the root template that the block belongs to. - * - * @throws \RuntimeException If the block does not have a root template. */ public function &get_root_template(): BlockTemplateInterface; /** - * Detach the block from its parent and root template. + * Check if the block is detached from its parent or root template. + * + * @return bool True if the block is detached from its parent or root template. */ - public function detach(); + public function is_detached(): bool; /** * Get the block configuration as a formatted template. diff --git a/plugins/woocommerce/src/Admin/BlockTemplates/BlockTemplateInterface.php b/plugins/woocommerce/src/Admin/BlockTemplates/BlockTemplateInterface.php index 8e61e853241..3da4a2a1e16 100644 --- a/plugins/woocommerce/src/Admin/BlockTemplates/BlockTemplateInterface.php +++ b/plugins/woocommerce/src/Admin/BlockTemplates/BlockTemplateInterface.php @@ -26,13 +26,6 @@ interface BlockTemplateInterface extends ContainerInterface { */ public function get_area(): string; - /** - * Get a block by ID. - * - * @param string $block_id The block ID. - */ - public function get_block( string $block_id ): ?BlockInterface; - /** * Generate a block ID based on a base. * diff --git a/plugins/woocommerce/src/Admin/BlockTemplates/ContainerInterface.php b/plugins/woocommerce/src/Admin/BlockTemplates/ContainerInterface.php index 3119e67b0c8..32305403183 100644 --- a/plugins/woocommerce/src/Admin/BlockTemplates/ContainerInterface.php +++ b/plugins/woocommerce/src/Admin/BlockTemplates/ContainerInterface.php @@ -16,6 +16,13 @@ interface ContainerInterface { */ public function get_formatted_template(): array; + /** + * Get a block by ID. + * + * @param string $block_id The block ID. + */ + public function get_block( string $block_id ): ?BlockInterface; + /** * Removes a block from the container. * diff --git a/plugins/woocommerce/src/Internal/Admin/BlockTemplates/AbstractBlock.php b/plugins/woocommerce/src/Internal/Admin/BlockTemplates/AbstractBlock.php index 1551b7cd959..0e1266192da 100644 --- a/plugins/woocommerce/src/Internal/Admin/BlockTemplates/AbstractBlock.php +++ b/plugins/woocommerce/src/Internal/Admin/BlockTemplates/AbstractBlock.php @@ -161,38 +161,29 @@ class AbstractBlock implements BlockInterface { /** * Get the template that this block belongs to. - * - * @throws \RuntimeException If the block does not have a root template. */ public function &get_root_template(): BlockTemplateInterface { - if ( is_null( $this->root_template ) ) { - throw new \RuntimeException( 'The block does not have a root template.' ); - } - return $this->root_template; } /** * Get the parent block container. - * - * @throws \RuntimeException If the block does not have a parent. */ public function &get_parent(): ContainerInterface { - if ( is_null( $this->parent ) ) { - throw new \RuntimeException( 'The block does not have a parent.' ); - } - return $this->parent; } /** - * Detach the block from its parent block container and the template it belongs to. + * Check if the block is detached from its parent block container or the template it belongs to. + * + * @return bool True if the block is detached from its parent block container or the template it belongs to. */ - public function detach() { - $this->parent = null; - $this->root_template = null; - } + public function is_detached(): bool { + $is_in_parent = $this->parent->get_block( $this->id ) === $this; + $is_in_root_template = $this->get_root_template()->get_block( $this->id ) === $this; + return ! $is_in_parent || ! $is_in_root_template; + } /** * Get the block configuration as a formatted template. * diff --git a/plugins/woocommerce/src/Internal/Admin/BlockTemplates/BlockContainerTrait.php b/plugins/woocommerce/src/Internal/Admin/BlockTemplates/BlockContainerTrait.php index 11243c847cd..eaaf9171462 100644 --- a/plugins/woocommerce/src/Internal/Admin/BlockTemplates/BlockContainerTrait.php +++ b/plugins/woocommerce/src/Internal/Admin/BlockTemplates/BlockContainerTrait.php @@ -77,6 +77,31 @@ trait BlockContainerTrait { return $this->is_block_descendant( $parent ); } + /** + * Get a block by ID. + * + * @param string $block_id The block ID. + */ + public function get_block( string $block_id ): ?BlockInterface { + foreach ( $this->inner_blocks as $block ) { + if ( $block->get_id() === $block_id ) { + return $block; + } + } + + foreach ( $this->inner_blocks as $block ) { + if ( $block instanceof ContainerInterface ) { + $block = $block->get_block( $block_id ); + + if ( $block ) { + return $block; + } + } + } + + return null; + } + /** * Remove a block from the block container. * @@ -108,10 +133,6 @@ trait BlockContainerTrait { $parent = $block->get_parent(); $parent->remove_inner_block( $block ); - - // Detach block from parent and root template. - $block->detach(); - } /** diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/BlockTemplates/BlockTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/BlockTemplates/BlockTest.php index 2b37a715189..f7283f1f3dc 100644 --- a/plugins/woocommerce/tests/php/src/Internal/Admin/BlockTemplates/BlockTest.php +++ b/plugins/woocommerce/tests/php/src/Internal/Admin/BlockTemplates/BlockTest.php @@ -133,9 +133,15 @@ class BlockTest extends WC_Unit_Test_Case { 'Failed asserting that the child block was removed from the root template.' ); - $this->expectException( \RuntimeException::class ); + $this->assertNull( + $block->get_block( 'test-block-id-2' ), + 'Failed asserting that the child block was removed from the parent.' + ); - $child_block->get_parent(); + $this->assertTrue( + $child_block->is_detached(), + 'Failed asserting that the child block is detached from its parent and root template.' + ); } /** @@ -166,9 +172,15 @@ class BlockTest extends WC_Unit_Test_Case { 'Failed asserting that the nested descendent block was removed from the root template.' ); - $this->expectException( \RuntimeException::class ); + $this->assertNull( + $block->get_block( 'test-block-id-2' ), + 'Failed asserting that the nested descendent block was removed from the parent.' + ); - $child_block->get_parent(); + $this->assertTrue( + $child_block->is_detached(), + 'Failed asserting that the nested descendent block is detached from its parent and root template.' + ); } /** @@ -204,9 +216,20 @@ class BlockTest extends WC_Unit_Test_Case { 'Failed asserting that the nested descendent block was removed from the root template.' ); - $this->expectException( \RuntimeException::class ); + $this->assertNull( + $block->get_block( 'test-block-id-2' ), + 'Failed asserting that the child block was removed from the parent.' + ); - $child_block->get_parent(); + $this->assertTrue( + $block->is_detached(), + 'Failed asserting that the block is detached from its parent and root template.' + ); + + $this->assertTrue( + $child_block->is_detached(), + 'Failed asserting that the child block is detached from its parent and root template.' + ); } /**