From 68a36de46043bc6ebc5cffe114d7d2d694b388a6 Mon Sep 17 00:00:00 2001 From: gziolo Date: Tue, 12 Apr 2022 09:26:16 +0000 Subject: [PATCH] REST API: Bring new endpoints for Block Patterns from Gutenberg plugin Related Gutenberg issue: https://github.com/WordPress/gutenberg/issues/39889. Backporting changes from the Gutenberg plugin: - new Block Patterns REST API endpoint - new Block Pattern Categories REST API endpoint - updates to Query Loop related patterns - support for custom taxonomies in Query Loop block Props hellofromtonya, peterwilsoncc, ntsekouras, zieladam, ironprogrammer, spacedmonkey, timothyblynjacobs, antonvlasenko, jsnajdr. See #55505. Built from https://develop.svn.wordpress.org/trunk@53152 git-svn-id: http://core.svn.wordpress.org/trunk@52741 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/block-patterns.php | 214 +++++++++++++++++- .../block-patterns/query-grid-posts.php | 2 +- .../query-large-title-posts.php | 2 +- .../block-patterns/query-medium-posts.php | 2 +- .../block-patterns/query-offset-posts.php | 4 +- .../block-patterns/query-small-posts.php | 2 +- .../block-patterns/query-standard-posts.php | 2 +- wp-includes/blocks.php | 40 +++- wp-includes/rest-api.php | 8 + ...st-block-pattern-categories-controller.php | 150 ++++++++++++ ...lass-wp-rest-block-patterns-controller.php | 198 ++++++++++++++++ ...s-wp-rest-pattern-directory-controller.php | 22 +- wp-includes/version.php | 2 +- wp-settings.php | 2 + 14 files changed, 623 insertions(+), 27 deletions(-) create mode 100644 wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php create mode 100644 wp-includes/rest-api/endpoints/class-wp-rest-block-patterns-controller.php diff --git a/wp-includes/block-patterns.php b/wp-includes/block-patterns.php index 0d4eacd1a3..0498db7e01 100644 --- a/wp-includes/block-patterns.php +++ b/wp-includes/block-patterns.php @@ -12,7 +12,7 @@ add_theme_support( 'core-block-patterns' ); * Registers the core block patterns and categories. * * @since 5.5.0 - * @private + * @access private */ function _register_core_block_patterns_and_categories() { $should_register_core_patterns = get_theme_support( 'core-block-patterns' ); @@ -127,3 +127,215 @@ function _load_remote_featured_patterns() { } } } + +/** + * Registers patterns from Pattern Directory provided by a theme's + * `theme.json` file. + * + * @since 6.0.0 + * @access private + */ +function _register_remote_theme_patterns() { + if ( ! get_theme_support( 'core-block-patterns' ) ) { + return; + } + + /** This filter is documented in wp-includes/block-patterns.php */ + if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) { + return; + } + + if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + return; + } + + $pattern_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_patterns(); + if ( empty( $pattern_settings ) ) { + return; + } + + $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); + $request['slug'] = implode( ',', $pattern_settings ); + $response = rest_do_request( $request ); + if ( $response->is_error() ) { + return; + } + $patterns = $response->get_data(); + $patterns_registry = WP_Block_Patterns_Registry::get_instance(); + foreach ( $patterns as $pattern ) { + $pattern_name = sanitize_title( $pattern['title'] ); + // Some patterns might be already registered as core patterns with the `core` prefix. + $is_registered = $patterns_registry->is_registered( $pattern_name ) || $patterns_registry->is_registered( "core/$pattern_name" ); + if ( ! $is_registered ) { + register_block_pattern( $pattern_name, (array) $pattern ); + } + } +} + +/** + * Register any patterns that the active theme may provide under its + * `./patterns/` directory. Each pattern is defined as a PHP file and defines + * its metadata using plugin-style headers. The minimum required definition is: + * + * /** + * * Title: My Pattern + * * Slug: my-theme/my-pattern + * * + * + * The output of the PHP source corresponds to the content of the pattern, e.g.: + * + *

+ * + * If applicable, this will collect from both parent and child theme. + * + * Other settable fields include: + * + * - Description + * - Viewport Width + * - Categories (comma-separated values) + * - Keywords (comma-separated values) + * - Block Types (comma-separated values) + * - Inserter (yes/no) + * + * @since 6.0.0 + * @access private + */ +function _register_theme_block_patterns() { + $default_headers = array( + 'title' => 'Title', + 'slug' => 'Slug', + 'description' => 'Description', + 'viewportWidth' => 'Viewport Width', + 'categories' => 'Categories', + 'keywords' => 'Keywords', + 'blockTypes' => 'Block Types', + 'inserter' => 'Inserter', + ); + + /* + * Register patterns for the active theme. If the theme is a child theme, + * let it override any patterns from the parent theme that shares the same slug. + */ + $themes = array(); + $stylesheet = get_stylesheet(); + $template = get_template(); + if ( $stylesheet !== $template ) { + $themes[] = wp_get_theme( $stylesheet ); + } + $themes[] = wp_get_theme( $template ); + + foreach ( $themes as $theme ) { + $dirpath = $theme->get_stylesheet_directory() . '/patterns/'; + if ( ! is_dir( $dirpath ) || ! is_readable( $dirpath ) ) { + continue; + } + if ( file_exists( $dirpath ) ) { + $files = glob( $dirpath . '*.php' ); + if ( $files ) { + foreach ( $files as $file ) { + $pattern_data = get_file_data( $file, $default_headers ); + + if ( empty( $pattern_data['slug'] ) ) { + _doing_it_wrong( + '_register_theme_block_patterns', + sprintf( + /* translators: %s: file name. */ + __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ), + $file + ), + '6.0.0' + ); + continue; + } + + if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern_data['slug'] ) ) { + _doing_it_wrong( + '_register_theme_block_patterns', + sprintf( + /* translators: %1s: file name; %2s: slug value found. */ + __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ), + $file, + $pattern_data['slug'] + ), + '6.0.0' + ); + } + + if ( WP_Block_Patterns_Registry::get_instance()->is_registered( $pattern_data['slug'] ) ) { + continue; + } + + // Title is a required property. + if ( ! $pattern_data['title'] ) { + _doing_it_wrong( + '_register_theme_block_patterns', + sprintf( + /* translators: %1s: file name; %2s: slug value found. */ + __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ), + $file + ), + '6.0.0' + ); + continue; + } + + // For properties of type array, parse data as comma-separated. + foreach ( array( 'categories', 'keywords', 'blockTypes' ) as $property ) { + if ( ! empty( $pattern_data[ $property ] ) ) { + $pattern_data[ $property ] = array_filter( + preg_split( + '/[\s,]+/', + (string) $pattern_data[ $property ] + ) + ); + } else { + unset( $pattern_data[ $property ] ); + } + } + + // Parse properties of type int. + foreach ( array( 'viewportWidth' ) as $property ) { + if ( ! empty( $pattern_data[ $property ] ) ) { + $pattern_data[ $property ] = (int) $pattern_data[ $property ]; + } else { + unset( $pattern_data[ $property ] ); + } + } + + // Parse properties of type bool. + foreach ( array( 'inserter' ) as $property ) { + if ( ! empty( $pattern_data[ $property ] ) ) { + $pattern_data[ $property ] = in_array( + strtolower( $pattern_data[ $property ] ), + array( 'yes', 'true' ), + true + ); + } else { + unset( $pattern_data[ $property ] ); + } + } + + // Translate the pattern metadata. + $text_domain = $theme->get( 'TextDomain' ); + //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction + $pattern_data['title'] = translate_with_gettext_context( $pattern_data['title'], 'Pattern title', $text_domain ); + if ( ! empty( $pattern_data['description'] ) ) { + //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction + $pattern_data['description'] = translate_with_gettext_context( $pattern_data['description'], 'Pattern description', $text_domain ); + } + + // The actual pattern content is the output of the file. + ob_start(); + include $file; + $pattern_data['content'] = ob_get_clean(); + if ( ! $pattern_data['content'] ) { + continue; + } + + register_block_pattern( $pattern_data['slug'], $pattern_data ); + } + } + } + } +} +add_action( 'init', '_register_theme_block_patterns' ); diff --git a/wp-includes/block-patterns/query-grid-posts.php b/wp-includes/block-patterns/query-grid-posts.php index 50e707a88b..27a0b1d6a7 100644 --- a/wp-includes/block-patterns/query-grid-posts.php +++ b/wp-includes/block-patterns/query-grid-posts.php @@ -9,7 +9,7 @@ return array( 'title' => _x( 'Grid', 'Block pattern title' ), 'blockTypes' => array( 'core/query' ), 'categories' => array( 'query' ), - 'content' => ' + 'content' => '
diff --git a/wp-includes/block-patterns/query-large-title-posts.php b/wp-includes/block-patterns/query-large-title-posts.php index f2d09e6987..0adf63aced 100644 --- a/wp-includes/block-patterns/query-large-title-posts.php +++ b/wp-includes/block-patterns/query-large-title-posts.php @@ -10,7 +10,7 @@ return array( 'blockTypes' => array( 'core/query' ), 'categories' => array( 'query' ), 'content' => ' -
+

diff --git a/wp-includes/block-patterns/query-medium-posts.php b/wp-includes/block-patterns/query-medium-posts.php index bd564ebe43..125ffd3010 100644 --- a/wp-includes/block-patterns/query-medium-posts.php +++ b/wp-includes/block-patterns/query-medium-posts.php @@ -9,7 +9,7 @@ return array( 'title' => _x( 'Image at left', 'Block pattern title' ), 'blockTypes' => array( 'core/query' ), 'categories' => array( 'query' ), - 'content' => ' + 'content' => '
diff --git a/wp-includes/block-patterns/query-offset-posts.php b/wp-includes/block-patterns/query-offset-posts.php index 34eeb0efac..139a4cb7f0 100644 --- a/wp-includes/block-patterns/query-offset-posts.php +++ b/wp-includes/block-patterns/query-offset-posts.php @@ -12,7 +12,7 @@ return array( 'content' => '
-
+
@@ -24,7 +24,7 @@ return array(
-
+
diff --git a/wp-includes/block-patterns/query-small-posts.php b/wp-includes/block-patterns/query-small-posts.php index 2f165c1b8b..66d57fcf68 100644 --- a/wp-includes/block-patterns/query-small-posts.php +++ b/wp-includes/block-patterns/query-small-posts.php @@ -9,7 +9,7 @@ return array( 'title' => _x( 'Small image and title', 'Block pattern title' ), 'blockTypes' => array( 'core/query' ), 'categories' => array( 'query' ), - 'content' => ' + 'content' => '
diff --git a/wp-includes/block-patterns/query-standard-posts.php b/wp-includes/block-patterns/query-standard-posts.php index c05ace98db..c6fde304e7 100644 --- a/wp-includes/block-patterns/query-standard-posts.php +++ b/wp-includes/block-patterns/query-standard-posts.php @@ -9,7 +9,7 @@ return array( 'title' => _x( 'Standard', 'Block pattern title' ), 'blockTypes' => array( 'core/query' ), 'categories' => array( 'query' ), - 'content' => ' + 'content' => '
diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php index dea94f173e..3be427e866 100644 --- a/wp-includes/blocks.php +++ b/wp-includes/blocks.php @@ -955,9 +955,8 @@ function do_blocks( $content ) { * If do_blocks() needs to remove wpautop() from the `the_content` filter, this re-adds it afterwards, * for subsequent `the_content` usage. * - * @access private - * * @since 5.0.0 + * @access private * * @param string $content The post content running through this filter. * @return string The unmodified content. @@ -1142,15 +1141,36 @@ function build_query_vars_from_query_block( $block, $page ) { $query['offset'] = ( $per_page * ( $page - 1 ) ) + $offset; $query['posts_per_page'] = $per_page; } - if ( ! empty( $block->context['query']['categoryIds'] ) ) { - $term_ids = array_map( 'intval', $block->context['query']['categoryIds'] ); - $term_ids = array_filter( $term_ids ); - $query['category__in'] = $term_ids; + // Migrate `categoryIds` and `tagIds` to `tax_query` for backwards compatibility. + if ( ! empty( $block->context['query']['categoryIds'] ) || ! empty( $block->context['query']['tagIds'] ) ) { + $tax_query = array(); + if ( ! empty( $block->context['query']['categoryIds'] ) ) { + $tax_query[] = array( + 'taxonomy' => 'category', + 'terms' => array_filter( array_map( 'intval', $block->context['query']['categoryIds'] ) ), + 'include_children' => false, + ); + } + if ( ! empty( $block->context['query']['tagIds'] ) ) { + $tax_query[] = array( + 'taxonomy' => 'post_tag', + 'terms' => array_filter( array_map( 'intval', $block->context['query']['tagIds'] ) ), + 'include_children' => false, + ); + } + $query['tax_query'] = $tax_query; } - if ( ! empty( $block->context['query']['tagIds'] ) ) { - $term_ids = array_map( 'intval', $block->context['query']['tagIds'] ); - $term_ids = array_filter( $term_ids ); - $query['tag__in'] = $term_ids; + if ( ! empty( $block->context['query']['taxQuery'] ) ) { + $query['tax_query'] = array(); + foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) { + if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) { + $query['tax_query'][] = array( + 'taxonomy' => $taxonomy, + 'terms' => array_filter( array_map( 'intval', $terms ) ), + 'include_children' => false, + ); + } + } } if ( isset( $block->context['query']['order'] ) && diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php index a7cd0178b0..941aa25f12 100644 --- a/wp-includes/rest-api.php +++ b/wp-includes/rest-api.php @@ -337,6 +337,14 @@ function create_initial_rest_routes() { $controller = new WP_REST_Pattern_Directory_Controller(); $controller->register_routes(); + // Block Patterns. + $controller = new WP_REST_Block_Patterns_Controller(); + $controller->register_routes(); + + // Block Pattern Categories. + $controller = new WP_REST_Block_Pattern_Categories_Controller(); + $controller->register_routes(); + // Site Health. $site_health = WP_Site_Health::get_instance(); $controller = new WP_REST_Site_Health_Controller( $site_health ); diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php new file mode 100644 index 0000000000..693bb7514f --- /dev/null +++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php @@ -0,0 +1,150 @@ +namespace = 'wp/v2'; + $this->rest_base = 'block-patterns/categories'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @since 6.0.0 + */ + public function register_routes() { + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( $this, 'get_items_permissions_check' ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * Checks whether a given request has permission to read block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check( $request ) { + if ( current_user_can( 'edit_posts' ) ) { + return true; + } + + foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { + if ( current_user_can( $post_type->cap->edit_posts ) ) { + return true; + } + } + + return new WP_Error( + 'rest_cannot_view', + __( 'Sorry, you are not allowed to view the registered block pattern categories.' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + /** + * Retrieves all block pattern categories. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + $response = array(); + $categories = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(); + foreach ( $categories as $category ) { + $prepared_category = $this->prepare_item_for_response( $category, $request ); + $response[] = $this->prepare_response_for_collection( $prepared_category ); + } + + return rest_ensure_response( $response ); + } + + /** + * Prepare a raw block pattern category before it gets output in a REST API response. + * + * @since 6.0.0 + * + * @param object $item Raw category 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', 'label' ); + $data = array(); + foreach ( $keys as $key ) { + if ( rest_is_field_included( $key, $fields ) ) { + $data[ $key ] = $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 category schema, conforming to JSON Schema. + * + * @since 6.0.0 + * + * @return array Item schema data. + */ + public function get_item_schema() { + $schema = array( + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'block-pattern-category', + 'type' => 'object', + 'properties' => array( + 'name' => array( + 'description' => __( 'The category name.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'label' => array( + 'description' => __( 'The category label, in human readable format.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } +} diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-patterns-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-patterns-controller.php new file mode 100644 index 0000000000..a96aa9e98d --- /dev/null +++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-patterns-controller.php @@ -0,0 +1,198 @@ +namespace = 'wp/v2'; + $this->rest_base = 'block-patterns/patterns'; + } + + /** + * Registers the routes for the objects of the controller. + * + * @since 6.0.0 + */ + public function register_routes() { + register_rest_route( + $this->namespace, + '/' . $this->rest_base, + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_items' ), + 'permission_callback' => array( $this, 'get_items_permissions_check' ), + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); + } + + /** + * Checks whether a given request has permission to read block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return true|WP_Error True if the request has read access, WP_Error object otherwise. + */ + public function get_items_permissions_check( $request ) { + if ( current_user_can( 'edit_posts' ) ) { + return true; + } + + foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { + if ( current_user_can( $post_type->cap->edit_posts ) ) { + return true; + } + } + + return new WP_Error( + 'rest_cannot_view', + __( 'Sorry, you are not allowed to view the registered block patterns.' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + + /** + * Retrieves all block patterns. + * + * @since 6.0.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_items( $request ) { + // Load block patterns from w.org. + _load_remote_block_patterns(); // Patterns with the `core` keyword. + _load_remote_featured_patterns(); // Patterns in the `featured` category. + _register_remote_theme_patterns(); // Patterns requested by current theme. + + $response = array(); + $patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered(); + foreach ( $patterns as $pattern ) { + $prepared_pattern = $this->prepare_item_for_response( $pattern, $request ); + $response[] = $this->prepare_response_for_collection( $prepared_pattern ); + } + return rest_ensure_response( $response ); + } + + /** + * Prepare a raw block pattern before it gets output in a REST API response. + * + * @since 6.0.0 + * + * @param object $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', + 'title', + 'description', + 'viewportWidth', + 'blockTypes', + 'categories', + 'keywords', + 'content', + ); + $data = array(); + foreach ( $keys as $key ) { + if ( isset( $item[ $key ] ) && rest_is_field_included( $key, $fields ) ) { + $data[ $key ] = $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 + * + * @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.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'title' => array( + 'description' => __( 'The pattern title, in human readable format.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'description' => array( + 'description' => __( 'The pattern detailed description.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'viewportWidth' => array( + 'description' => __( 'The pattern viewport width for inserter preview.' ), + 'type' => 'number', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'blockTypes' => array( + 'description' => __( 'Block types that the pattern is intended to be used with.' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'categories' => array( + 'description' => __( 'The pattern category slugs.' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'keywords' => array( + 'description' => __( 'The pattern keywords.' ), + 'type' => 'array', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + 'content' => array( + 'description' => __( 'The pattern content.' ), + 'type' => 'string', + 'readonly' => true, + 'context' => array( 'view', 'edit', 'embed' ), + ), + ), + ); + + return $this->add_additional_fields_schema( $schema ); + } +} diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php index 186387d8c0..2deb3c7e7a 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php @@ -80,6 +80,7 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { * Search and retrieve block patterns metadata * * @since 5.8.0 + * @since 6.0.0 Added 'slug' to request. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. @@ -100,6 +101,7 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { $category_id = $request['category']; $keyword_id = $request['keyword']; $search_term = $request['search']; + $slug = $request['slug']; if ( $category_id ) { $query_args['pattern-categories'] = $category_id; @@ -113,6 +115,10 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { $query_args['search'] = $search_term; } + if ( $slug ) { + $query_args['slug'] = $slug; + } + /* * Include a hash of the query args, so that different requests are stored in * separate caches. @@ -159,7 +165,7 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { $raw_patterns = new WP_Error( 'pattern_api_failed', sprintf( - /* translators: %s: Support forums URL. */ + /* translators: %s: Support forums URL. */ __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), __( 'https://wordpress.org/support/forums/' ) ), @@ -255,21 +261,21 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { 'description' => __( 'The pattern ID.' ), 'type' => 'integer', 'minimum' => 1, - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'title' => array( 'description' => __( 'The pattern title, in human readable format.' ), 'type' => 'string', 'minLength' => 1, - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'content' => array( 'description' => __( 'The pattern content.' ), 'type' => 'string', 'minLength' => 1, - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'categories' => array( @@ -277,7 +283,7 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { 'type' => 'array', 'uniqueItems' => true, 'items' => array( 'type' => 'string' ), - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'keywords' => array( @@ -285,20 +291,20 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller { 'type' => 'array', 'uniqueItems' => true, 'items' => array( 'type' => 'string' ), - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'description' => array( 'description' => __( 'A description of the pattern.' ), 'type' => 'string', 'minLength' => 1, - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), 'viewport_width' => array( 'description' => __( 'The preferred width of the viewport when previewing a pattern, in pixels.' ), 'type' => 'integer', - 'context' => array( 'view', 'embed' ), + 'context' => array( 'view', 'edit', 'embed' ), ), ), ); diff --git a/wp-includes/version.php b/wp-includes/version.php index 80a6a8c6e0..0f9443b49d 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.0-alpha-53151'; +$wp_version = '6.0-alpha-53152'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. diff --git a/wp-settings.php b/wp-settings.php index c1bab688c0..ffe047b1ec 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -277,6 +277,8 @@ require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-plugins-controller. require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-block-directory-controller.php'; require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-edit-site-export-controller.php'; require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php'; +require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-block-patterns-controller.php'; +require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php'; require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-application-passwords-controller.php'; require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-site-health-controller.php'; require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-sidebars-controller.php';