REST API: Cache results of get_item_schema on controller instances for performance.

Caches the output of get_item_schema() to avoid redundant recomputation of translatable strings and other computed values. This method is called many times per item in each REST request, and the results of the method should not vary between calls.
Additional schema fields are not cached.

Props kadamwhite, joehoyle, TimothyBlynJacobs.
Fixes #47871.


git-svn-id: https://develop.svn.wordpress.org/trunk@45811 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
K. Adam White 2019-08-15 21:08:05 +00:00
parent 94b8a122c4
commit eb468c4446
18 changed files with 106 additions and 14 deletions

View File

@ -417,6 +417,9 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
* @return array Item schema as an array.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = parent::get_item_schema();
@ -513,7 +516,8 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
unset( $schema['properties']['password'] );
return $schema;
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -296,6 +296,10 @@ class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = $this->revisions_controller->get_item_schema();
$schema['properties']['preview_link'] = array(
@ -306,7 +310,8 @@ class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller {
'readonly' => true,
);
return $schema;
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -161,7 +161,11 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
return array(
if ( $this->schema ) {
return $this->schema;
}
$this->schema = array(
'$schema' => 'http://json-schema.org/schema#',
'title' => 'rendered-block',
'type' => 'object',
@ -174,5 +178,6 @@ class WP_REST_Block_Renderer_Controller extends WP_REST_Controller {
),
),
);
return $this->schema;
}
}

View File

@ -68,6 +68,7 @@ class WP_REST_Blocks_Controller extends WP_REST_Posts_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
// Do not cache this schema because all properties are derived from parent controller.
$schema = parent::get_item_schema();
/*

View File

@ -1215,6 +1215,10 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return array
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'comment',
@ -1364,7 +1368,8 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
$schema['properties']['meta'] = $this->meta->get_field_schema();
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -30,6 +30,14 @@ abstract class WP_REST_Controller {
*/
protected $rest_base;
/**
* Cached results of get_item_schema.
*
* @since 5.3.0
* @var array
*/
protected $schema;
/**
* Registers the routes for the objects of the controller.
*

View File

@ -268,6 +268,10 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'status',
@ -318,7 +322,8 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
),
);
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -242,6 +242,10 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'type',
@ -312,7 +316,9 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
),
),
);
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -1870,6 +1870,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
@ -2229,7 +2232,8 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
$schema['links'] = $schema_links;
}
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -606,6 +606,10 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => "{$this->parent_post_type}-revision",
@ -682,7 +686,8 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
$schema['properties']['guid'] = $parent_schema['properties']['guid'];
}
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -211,6 +211,10 @@ class WP_REST_Search_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$types = array();
$subtypes = array();
foreach ( $this->search_handlers as $search_handler ) {
@ -262,7 +266,8 @@ class WP_REST_Search_Controller extends WP_REST_Controller {
),
);
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -270,6 +270,10 @@ class WP_REST_Settings_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$options = $this->get_registered_options();
$schema = array(
@ -286,7 +290,8 @@ class WP_REST_Settings_Controller extends WP_REST_Controller {
);
}
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -276,6 +276,10 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'taxonomy',
@ -373,7 +377,9 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
),
),
);
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -856,6 +856,10 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'post_tag' === $this->taxonomy ? 'tag' : $this->taxonomy,
@ -924,7 +928,8 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
$schema['properties']['meta'] = $this->meta->get_field_schema();
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -147,6 +147,10 @@ class WP_REST_Themes_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'theme',
@ -177,7 +181,8 @@ class WP_REST_Themes_Controller extends WP_REST_Controller {
),
);
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -1178,6 +1178,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'user',
@ -1334,7 +1338,8 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
$schema['properties']['meta'] = $this->meta->get_field_schema();
return $this->add_additional_fields_schema( $schema );
$this->schema = $schema;
return $this->add_additional_fields_schema( $this->schema );
}
/**

View File

@ -3919,6 +3919,12 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
remove_post_type_support( 'post', 'author' );
// Re-initialize the controller to cache-bust schemas from prior test runs.
$GLOBALS['wp_rest_server']->override_by_default = true;
$controller = new WP_REST_Posts_Controller( 'post' );
$controller->register_routes();
$GLOBALS['wp_rest_server']->override_by_default = false;
$response = rest_get_server()->dispatch( new WP_REST_Request( 'OPTIONS', '/wp/v2/posts' ) );
$data = $response->get_data();
$schema = $data['schema'];

View File

@ -2522,6 +2522,13 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
public function test_get_item_schema_show_avatar() {
update_option( 'show_avatars', false );
// Re-initialize the controller to cache-bust schemas from prior test runs.
$GLOBALS['wp_rest_server']->override_by_default = true;
$controller = new WP_REST_Users_Controller();
$controller->register_routes();
$GLOBALS['wp_rest_server']->override_by_default = false;
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/users' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();