diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index f79c95428d056..c13f2f75921a0 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -2232,6 +2232,7 @@ function get_block_editor_server_block_settings() { 'styles' => 'styles', 'textdomain' => 'textdomain', 'parent' => 'parent', + 'ancestor' => 'ancestor', 'keywords' => 'keywords', 'example' => 'example', 'variations' => 'variations', diff --git a/src/wp-includes/class-wp-block-type.php b/src/wp-includes/class-wp-block-type.php index b3700e8d2e856..47e6619fe2b86 100644 --- a/src/wp-includes/class-wp-block-type.php +++ b/src/wp-includes/class-wp-block-type.php @@ -58,6 +58,15 @@ class WP_Block_Type { */ public $parent = null; + /** + * Setting ancestor makes a block available only inside the specified + * block types at any position of the ancestor's block subtree. + * + * @since 6.0.0 + * @var array|null + */ + public $ancestor = null; + /** * Block type icon. * @@ -207,6 +216,7 @@ class WP_Block_Type { * @since 5.6.0 Added the `api_version` property. * @since 5.8.0 Added the `variations` property. * @since 5.9.0 Added the `view_script` property. + * @since 6.0.0 Added the `ancestor` property. * * @see register_block_type() * @@ -221,6 +231,8 @@ class WP_Block_Type { * search interfaces to arrange block types by category. * @type array|null $parent Setting parent lets a block require that it is only * available when nested within the specified blocks. + * @type array|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 $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 c546a3082a3d4..95b12e388a776 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 @@ -266,6 +266,7 @@ public function prepare_item_for_response( $item, $request ) { 'category', 'keywords', 'parent', + 'ancestor', 'provides_context', 'uses_context', 'supports', @@ -645,6 +646,16 @@ public function get_item_schema() { 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), + 'ancestor' => array( + 'description' => __( 'Ancestor blocks.' ), + 'type' => array( 'array', 'null' ), + 'items' => array( + 'type' => 'string', + ), + 'default' => null, + 'context' => array( 'embed', 'view', 'edit' ), + 'readonly' => true, + ), 'keywords' => $keywords_definition, 'example' => $example_definition, ), diff --git a/tests/phpunit/tests/admin/includesPost.php b/tests/phpunit/tests/admin/includesPost.php index 5f3ec7451d947..bb0ed75c83c93 100644 --- a/tests/phpunit/tests/admin/includesPost.php +++ b/tests/phpunit/tests/admin/includesPost.php @@ -828,6 +828,7 @@ public function test_get_block_editor_server_block_settings() { 'icon' => 'text', 'category' => 'common', 'render_callback' => 'foo', + 'ancestor' => array( 'core/test-ancestor' ), ); register_block_type( $name, $settings ); @@ -846,6 +847,7 @@ public function test_get_block_editor_server_block_settings() { 'usesContext' => array(), 'category' => 'common', 'styles' => array(), + 'ancestor' => array( 'core/test-ancestor' ), 'keywords' => array(), 'variations' => 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 a774b9be1fc71..15738397ac263 100644 --- a/tests/phpunit/tests/rest-api/rest-block-type-controller.php +++ b/tests/phpunit/tests/rest-api/rest-block-type-controller.php @@ -221,6 +221,7 @@ public function test_get_item_invalid() { 'keywords' => 'invalid_keywords', 'example' => 'invalid_example', 'parent' => 'invalid_parent', + 'ancestor' => 'invalid_ancestor', 'supports' => 'invalid_supports', 'styles' => 'invalid_styles', 'render_callback' => 'invalid_callback', @@ -246,6 +247,7 @@ public function test_get_item_invalid() { $this->assertSameSets( array( 'invalid_uses_context' ), $data['uses_context'] ); $this->assertSameSets( array( 'invalid_keywords' ), $data['keywords'] ); $this->assertSameSets( array( 'invalid_parent' ), $data['parent'] ); + $this->assertSameSets( array( 'invalid_ancestor' ), $data['ancestor'] ); $this->assertSameSets( array(), $data['supports'] ); $this->assertSameSets( array(), $data['styles'] ); $this->assertNull( $data['example'] ); @@ -275,6 +277,7 @@ public function test_get_item_defaults() { 'style' => false, 'keywords' => false, 'parent' => false, + 'ancestor' => false, 'supports' => false, 'styles' => false, 'render_callback' => false, @@ -301,6 +304,7 @@ public function test_get_item_defaults() { $this->assertSameSets( array(), $data['uses_context'] ); $this->assertSameSets( array(), $data['keywords'] ); $this->assertSameSets( array(), $data['parent'] ); + $this->assertSameSets( array(), $data['ancestor'] ); $this->assertSameSets( array(), $data['supports'] ); $this->assertSameSets( array(), $data['styles'] ); $this->assertNull( $data['example'] ); @@ -378,7 +382,7 @@ public function test_get_item_schema() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertCount( 22, $properties ); + $this->assertCount( 23, $properties ); $this->assertArrayHasKey( 'api_version', $properties ); $this->assertArrayHasKey( 'title', $properties ); $this->assertArrayHasKey( 'icon', $properties ); @@ -401,6 +405,7 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'uses_context', $properties ); $this->assertArrayHasKey( 'provides_context', $properties ); $this->assertArrayHasKey( 'variations', $properties ); + $this->assertArrayHasKey( 'ancestor', $properties ); } /**