From 41f70ae5f8fbf80a9dbb38404b105c2527ad6629 Mon Sep 17 00:00:00 2001 From: TimothyBlynJacobs Date: Wed, 17 Jun 2020 03:22:12 +0000 Subject: [PATCH] REST API: Only register one block renderer route. Every block has a different set of attributes. These attributes are specified as a JSON Schema object. Previously, every block registered its own block renderer route using its attributes for the schema. This allowed for the attributes to be validated using the built in endpoint validation rules. It had the unfortunate side effect, however, of creating a large number of nearly identical REST API routes, one for each dynamic block. Each registered route has a performance impact. As the number of server side blocks goes up, this becomes more and more of an issue. Now, we register a single block renderer route and dynamically validate the attributes based on the selected block. Fixes #48079. Props gziolo, TimothyBlynJacobs. Built from https://develop.svn.wordpress.org/trunk@48069 git-svn-id: http://core.svn.wordpress.org/trunk@47836 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- ...lass-wp-rest-block-renderer-controller.php | 87 ++++++++++--------- wp-includes/version.php | 2 +- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php index 3bdcae5435..3388078d05 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php @@ -34,47 +34,52 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller { * @see register_rest_route() */ public function register_routes() { - $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered(); - - foreach ( $block_types as $block_type ) { - if ( ! $block_type->is_dynamic() ) { - continue; - } - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/(?P' . $block_type->name . ')', + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/(?P[a-z0-9-]+/[a-z0-9-]+)', + array( + 'args' => array( + 'name' => array( + 'description' => __( 'Unique registered name for the block.' ), + 'type' => 'string', + ), + ), array( - 'args' => array( - 'name' => array( - 'description' => __( 'Unique registered name for the block.' ), - 'type' => 'string', + 'methods' => array( WP_REST_Server::READABLE, WP_REST_Server::CREATABLE ), + 'callback' => array( $this, 'get_item' ), + 'permission_callback' => array( $this, 'get_item_permissions_check' ), + 'args' => array( + 'context' => $this->get_context_param( array( 'default' => 'view' ) ), + 'attributes' => array( + 'description' => __( 'Attributes for the block' ), + 'type' => 'object', + 'default' => array(), + 'validate_callback' => static function ( $value, $request ) { + $block = WP_Block_Type_Registry::get_instance()->get_registered( $request['name'] ); + + if ( ! $block ) { + // This will get rejected in ::get_item(). + return true; + } + + $schema = array( + 'type' => 'object', + 'properties' => $block->get_attributes(), + 'additionalProperties' => false, + ); + + return rest_validate_value_from_schema( $value, $schema ); + }, + ), + 'post_id' => array( + 'description' => __( 'ID of the post context.' ), + 'type' => 'integer', ), ), - array( - 'methods' => array( WP_REST_Server::READABLE, WP_REST_Server::CREATABLE ), - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - 'attributes' => array( - /* translators: %s: The name of the block. */ - 'description' => sprintf( __( 'Attributes for %s block' ), $block_type->name ), - 'type' => 'object', - 'additionalProperties' => false, - 'properties' => $block_type->get_attributes(), - 'default' => array(), - ), - 'post_id' => array( - 'description' => __( 'ID of the post context.' ), - 'type' => 'integer', - ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } + ), + 'schema' => array( $this, 'get_public_item_schema' ), + ) + ); } /** @@ -136,9 +141,11 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller { // Set up postdata since this will be needed if post_id was set. setup_postdata( $post ); } - $registry = WP_Block_Type_Registry::get_instance(); - if ( null === $registry->get_registered( $request['name'] ) ) { + $registry = WP_Block_Type_Registry::get_instance(); + $registered = $registry->get_registered( $request['name'] ); + + if ( null === $registered || ! $registered->is_dynamic() ) { return new WP_Error( 'block_invalid', __( 'Invalid block.' ), diff --git a/wp-includes/version.php b/wp-includes/version.php index 0149a32b92..1773c5d6a7 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.5-alpha-48068'; +$wp_version = '5.5-alpha-48069'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.