From 2a494ac363749eb534c6912e0a12869dd3f1e886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=83=C2=B3=C3=85=E2=80=9Akowski?= Date: Fri, 2 Feb 2024 12:59:21 +0000 Subject: [PATCH] Editor: Add `allowed_blocks` field to block registration and REST API There is a new block.json field called allowedBlocks, added in Gutenberg in https://github.com/WordPress/gutenberg/pull/58262. This adds support for this new field also on the server. Props: gziolo, jsnajdr. Fixes #60403. git-svn-id: https://develop.svn.wordpress.org/trunk@57521 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/post.php | 1 + src/wp-includes/blocks.php | 3 ++- src/wp-includes/class-wp-block-type.php | 9 +++++++++ .../class-wp-rest-block-types-controller.php | 12 ++++++++++++ .../tests/rest-api/rest-block-type-controller.php | 9 ++++++++- 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index c93ac71bec525..90aaf2228e371 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -2303,6 +2303,7 @@ function get_block_editor_server_block_settings() { 'keywords' => 'keywords', 'example' => 'example', 'variations' => 'variations', + 'allowed_blocks' => 'allowedBlocks', ); foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) { diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index fdf97545f72d7..51d05a0846160 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -327,7 +327,7 @@ function get_block_metadata_i18n_schema() { * @since 6.1.0 Added support for `render` field. * @since 6.3.0 Added `selectors` field. * @since 6.4.0 Added support for `blockHooks` field. - * @since 6.5.0 Added support for `viewStyle` field. + * @since 6.5.0 Added support for `allowedBlocks` and `viewStyle` fields. * * @param string $file_or_folder Path to the JSON file with metadata definition for * the block or path to the folder where the `block.json` file is located. @@ -424,6 +424,7 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) { 'styles' => 'styles', 'variations' => 'variations', 'example' => 'example', + 'allowedBlocks' => 'allowed_blocks', ); $textdomain = ! empty( $metadata['textdomain'] ) ? $metadata['textdomain'] : null; $i18n_schema = get_block_metadata_i18n_schema(); diff --git a/src/wp-includes/class-wp-block-type.php b/src/wp-includes/class-wp-block-type.php index 5bdcee1504824..33825a7888320 100644 --- a/src/wp-includes/class-wp-block-type.php +++ b/src/wp-includes/class-wp-block-type.php @@ -68,6 +68,14 @@ class WP_Block_Type { */ public $ancestor = null; + /** + * Limits which block types can be inserted as children of this block type. + * + * @since 6.5.0 + * @var string[]|null + */ + public $allowed_blocks = null; + /** * Block type icon. * @@ -303,6 +311,7 @@ class WP_Block_Type { * available when nested within the specified blocks. * @type string[]|null $ancestor Setting ancestor makes a block available only inside the specified * block types at any position of the ancestor's block subtree. + * @type string[]|null $allowed_blocks Limits which block types can be inserted as children of this block type. * @type string|null $icon Block type icon. * @type string $description A detailed block type description. * @type string[] $keywords Additional keywords to produce block type as diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php index 9e8ba9e9299e3..7bf2f6af4af2e 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php @@ -280,6 +280,7 @@ public function prepare_item_for_response( $item, $request ) { 'keywords', 'parent', 'ancestor', + 'allowed_blocks', 'provides_context', 'uses_context', 'selectors', @@ -723,6 +724,17 @@ public function get_item_schema() { 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), + 'allowed_blocks' => array( + 'description' => __( 'Allowed child block types.' ), + 'type' => array( 'array', 'null' ), + 'items' => array( + 'type' => 'string', + 'pattern' => self::NAME_PATTERN, + ), + 'default' => null, + 'context' => array( 'embed', 'view', 'edit' ), + 'readonly' => true, + ), 'keywords' => $keywords_definition, 'example' => $example_definition, 'block_hooks' => array( diff --git a/tests/phpunit/tests/rest-api/rest-block-type-controller.php b/tests/phpunit/tests/rest-api/rest-block-type-controller.php index eca0e64a5fb55..6e314e6af4ab7 100644 --- a/tests/phpunit/tests/rest-api/rest-block-type-controller.php +++ b/tests/phpunit/tests/rest-api/rest-block-type-controller.php @@ -207,6 +207,7 @@ public function test_get_item_invalid() { 'category' => true, 'parent' => 'invalid_parent', 'ancestor' => 'invalid_ancestor', + 'allowed_blocks' => 'invalid_allowed_blocks', 'icon' => true, 'description' => true, 'keywords' => 'invalid_keywords', @@ -237,6 +238,7 @@ public function test_get_item_invalid() { $this->assertNull( $data['category'] ); $this->assertSameSets( array( 'invalid_parent' ), $data['parent'] ); $this->assertSameSets( array( 'invalid_ancestor' ), $data['ancestor'] ); + $this->assertSameSets( array( 'invalid_allowed_blocks' ), $data['allowed_blocks'] ); $this->assertNull( $data['icon'] ); $this->assertSame( '1', $data['description'] ); $this->assertSameSets( array( 'invalid_keywords' ), $data['keywords'] ); @@ -283,6 +285,7 @@ public function test_get_item_defaults() { 'category' => false, 'parent' => false, 'ancestor' => false, + 'allowed_blocks' => false, 'icon' => false, 'description' => false, 'keywords' => false, @@ -313,6 +316,7 @@ public function test_get_item_defaults() { $this->assertNull( $data['category'] ); $this->assertSameSets( array(), $data['parent'] ); $this->assertSameSets( array(), $data['ancestor'] ); + $this->assertSameSets( array(), $data['allowed_blocks'] ); $this->assertNull( $data['icon'] ); $this->assertSame( '', $data['description'] ); $this->assertSameSets( array(), $data['keywords'] ); @@ -550,6 +554,7 @@ public function test_get_variation() { * @ticket 47620 * @ticket 57585 * @ticket 59346 + * @ticket 60403 */ public function test_get_item_schema() { wp_set_current_user( self::$admin_id ); @@ -557,13 +562,14 @@ public function test_get_item_schema() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertCount( 31, $properties ); + $this->assertCount( 32, $properties ); $this->assertArrayHasKey( 'api_version', $properties ); $this->assertArrayHasKey( 'name', $properties ); $this->assertArrayHasKey( 'title', $properties ); $this->assertArrayHasKey( 'category', $properties ); $this->assertArrayHasKey( 'parent', $properties ); $this->assertArrayHasKey( 'ancestor', $properties ); + $this->assertArrayHasKey( 'allowed_blocks', $properties ); $this->assertArrayHasKey( 'icon', $properties ); $this->assertArrayHasKey( 'description', $properties ); $this->assertArrayHasKey( 'keywords', $properties ); @@ -696,6 +702,7 @@ protected function check_block_type_object( $block_type, $data, $links ) { 'category', 'parent', 'ancestor', + 'allowedBlocks', 'icon', 'description', 'keywords',