diff --git a/docs/reference-guides/block-api/block-patterns.md b/docs/reference-guides/block-api/block-patterns.md index 12fac7b479361a..2d387630ea1176 100644 --- a/docs/reference-guides/block-api/block-patterns.md +++ b/docs/reference-guides/block-api/block-patterns.md @@ -34,6 +34,7 @@ The properties available for block patterns are: - `viewportWidth` (optional): An integer specifying the intended width of the pattern to allow for a scaled preview of the pattern in the inserter. - `blockTypes` (optional): An array of block types that the pattern is intended to be used with. Each value needs to be the declared block's `name`. - `postTypes` (optional): An array of post types that the pattern is restricted to be used with. The pattern will only be available when editing one of the post types passed on the array, for all the other post types the pattern is not available at all. +- `templateTypes` (optional): An array of template types where the pattern makes sense e.g: '404' if the pattern is for a 404 page, single-post if the pattern is for showing a single post. - `inserter` (optional): By default, all patterns will appear in the inserter. To hide a pattern so that it can only be inserted programmatically, set the `inserter` to `false`. The following code sample registers a block pattern named 'my-plugin/my-awesome-pattern': diff --git a/lib/compat/wordpress-6.2/block-patterns.php b/lib/compat/wordpress-6.2/block-patterns.php index 1e529faf963210..13d9af96220494 100644 --- a/lib/compat/wordpress-6.2/block-patterns.php +++ b/lib/compat/wordpress-6.2/block-patterns.php @@ -225,6 +225,7 @@ function gutenberg_register_theme_block_patterns() { 'blockTypes' => 'Block Types', 'postTypes' => 'Post Types', 'inserter' => 'Inserter', + 'templateTypes' => 'Template Types', ); /* @@ -294,7 +295,7 @@ function gutenberg_register_theme_block_patterns() { } // For properties of type array, parse data as comma-separated. - foreach ( array( 'categories', 'keywords', 'blockTypes', 'postTypes' ) as $property ) { + foreach ( array( 'categories', 'keywords', 'blockTypes', 'postTypes', 'templateTypes' ) as $property ) { if ( ! empty( $pattern_data[ $property ] ) ) { $pattern_data[ $property ] = array_filter( preg_split( diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php index d34160edb2af0b..604818fcd30a70 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-block-patterns-controller-6-2.php @@ -34,6 +34,128 @@ class Gutenberg_REST_Block_Patterns_Controller_6_2 extends Gutenberg_REST_Block_ 'query' => 'posts', ); + /** + * Prepare a raw block pattern before it gets output in a REST API response. + * + * @since 6.0.0 + * + * @param array $item Raw pattern as registered, before any changes. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response( $item, $request ) { + $fields = $this->get_fields_for_response( $request ); + $keys = array( + 'name' => 'name', + 'title' => 'title', + 'description' => 'description', + 'viewportWidth' => 'viewport_width', + 'blockTypes' => 'block_types', + 'postTypes' => 'post_types', + 'categories' => 'categories', + 'keywords' => 'keywords', + 'content' => 'content', + 'inserter' => 'inserter', + 'templateTypes' => 'template_types', + ); + $data = array(); + foreach ( $keys as $item_key => $rest_key ) { + if ( isset( $item[ $item_key ] ) && rest_is_field_included( $rest_key, $fields ) ) { + $data[ $rest_key ] = $item[ $item_key ]; + } + } + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $data = $this->add_additional_fields_to_object( $data, $request ); + $data = $this->filter_response_by_context( $data, $context ); + return rest_ensure_response( $data ); + } + + /** + * Retrieves the block pattern schema, conforming to JSON Schema. + * + * @since 6.0.0 + * @since 6.1.0 Added `post_types` property. + * + * @return array Item schema data. + */ + public function get_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'block-pattern', + 'type' => 'object', + 'properties' => array( + 'name' => array( + 'description' => __( 'The pattern name.', 'gutenberg' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'title' => array( + 'description' => __( 'The pattern title, in human readable format.', 'gutenberg' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'description' => array( + 'description' => __( 'The pattern detailed description.', 'gutenberg' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'viewport_width' => array( + 'description' => __( 'The pattern viewport width for inserter preview.', 'gutenberg' ), + 'type' => 'number', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'block_types' => array( + 'description' => __( 'Block types that the pattern is intended to be used with.', 'gutenberg' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'post_types' => array( + 'description' => __( 'An array of post types that the pattern is restricted to be used with.', 'gutenberg' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'categories' => array( + 'description' => __( 'The pattern category slugs.', 'gutenberg' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'keywords' => array( + 'description' => __( 'The pattern keywords.', 'gutenberg' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'template_types' => array( + 'description' => __( 'An array of template types where the pattern fits.', 'gutenberg' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'content' => array( + 'description' => __( 'The pattern content.', 'gutenberg' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'inserter' => array( + 'description' => __( 'Determines whether the pattern is visible in inserter.', 'gutenberg' ), + 'type' => 'boolean', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } + /** * Registers the routes for the objects of the controller. * diff --git a/lib/compat/wordpress-6.2/rest-api.php b/lib/compat/wordpress-6.2/rest-api.php index 12f7afda3b4d5d..a557a38e490de1 100644 --- a/lib/compat/wordpress-6.2/rest-api.php +++ b/lib/compat/wordpress-6.2/rest-api.php @@ -116,3 +116,15 @@ function gutenberg_modify_rest_sidebars_response( $response ) { return $response; } add_filter( 'rest_prepare_sidebar', 'gutenberg_modify_rest_sidebars_response' ); + + +register_block_pattern( + 'query/template-type-test', + array( + 'title' => __( 'Template type test', 'gutenberg' ), + 'templateTypes' => array( '404' ), + 'content' => ' +
404
+ ', + ) +); diff --git a/phpunit/class-gutenberg-rest-block-patterns-controller-test.php b/phpunit/class-gutenberg-rest-block-patterns-controller-test.php index 9f9cf60f0572a6..34d5f10970c6c6 100644 --- a/phpunit/class-gutenberg-rest-block-patterns-controller-test.php +++ b/phpunit/class-gutenberg-rest-block-patterns-controller-test.php @@ -67,24 +67,27 @@ public static function wpSetUpBeforeClass( $factory ) { 'categories' => array( 'test' ), 'viewportWidth' => 1440, 'content' => 'Two
', + 'title' => 'Pattern Two', + 'categories' => array( 'test' ), + 'content' => 'Two
', + 'templateTypes' => array( 'single' ), ) ); $test_registry->register( 'test/three', array( - 'title' => 'Pattern Three', - 'categories' => array( 'test', 'buttons', 'query' ), - 'content' => 'Three
', + 'title' => 'Pattern Three', + 'categories' => array( 'test', 'buttons', 'query' ), + 'content' => 'Three
', + 'templateTypes' => array( '404' ), ) ); } @@ -147,7 +150,21 @@ public function test_register_routes() { $this->markTestIncomplete(); } public function test_get_items() { - $this->markTestIncomplete(); + wp_set_current_user( self::$admin_id ); + + $expected_names = array( 'test/one', 'test/two', 'test/three' ); + $expected_fields = array( 'name', 'content', 'template_types' ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/block-patterns/patterns' ); + $request['_fields'] = 'name,content,template_types'; + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertCount( count( $expected_names ), $data ); + foreach ( $data as $idx => $item ) { + $this->assertEquals( $expected_names[ $idx ], $item['name'] ); + $this->assertEquals( $expected_fields, array_keys( $item ) ); + } } public function test_context_param() { $this->markTestIncomplete();