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
This commit is contained in:
TimothyBlynJacobs 2020-06-17 03:22:12 +00:00
parent 353c9bfc58
commit 41f70ae5f8
2 changed files with 48 additions and 41 deletions

View File

@ -34,47 +34,52 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller {
* @see register_rest_route() * @see register_rest_route()
*/ */
public function register_routes() { public function register_routes() {
$block_types = WP_Block_Type_Registry::get_instance()->get_all_registered(); register_rest_route(
$this->namespace,
foreach ( $block_types as $block_type ) { '/' . $this->rest_base . '/(?P<name>[a-z0-9-]+/[a-z0-9-]+)',
if ( ! $block_type->is_dynamic() ) { array(
continue; 'args' => array(
} 'name' => array(
'description' => __( 'Unique registered name for the block.' ),
register_rest_route( 'type' => 'string',
$this->namespace, ),
'/' . $this->rest_base . '/(?P<name>' . $block_type->name . ')', ),
array( array(
'args' => array( 'methods' => array( WP_REST_Server::READABLE, WP_REST_Server::CREATABLE ),
'name' => array( 'callback' => array( $this, 'get_item' ),
'description' => __( 'Unique registered name for the block.' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ),
'type' => 'string', '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 ), 'schema' => array( $this, 'get_public_item_schema' ),
'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' ),
)
);
}
} }
/** /**
@ -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. // Set up postdata since this will be needed if post_id was set.
setup_postdata( $post ); 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( return new WP_Error(
'block_invalid', 'block_invalid',
__( 'Invalid block.' ), __( 'Invalid block.' ),

View File

@ -13,7 +13,7 @@
* *
* @global string $wp_version * @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. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.