diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index fe7bd06ee0..bc1a280492 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php index e55d3a3729..0d015519d3 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php index 681e519313..18fbe1e036 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-renderer-controller.php @@ -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; } } diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php index a523764dc5..36d1573a9a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-blocks-controller.php @@ -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(); /* diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index b730844fde..8bce803ea9 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php index e1ca0af6ce..735fee738a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php @@ -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. * diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php index 699e8fd2ce..155c8aaa96 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php index c718a3dfa6..99a3c77071 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index 090ca2a5da..ad53ea6a1e 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php index 52df0f2206..1b34619130 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php index 299029b1c3..c464e0d1b4 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php index 95752f8236..b11e4fdca8 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php index 6dc78cb6d0..58ad748132 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php index 881afcd41f..52bc9d2b0a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php index dbfaa839cb..e04b23594d 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php @@ -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 ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php index bd09b70b32..ec29c66974 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php @@ -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 ); } /** diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index f03eee8e83..ba174c448e 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -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']; diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php index 02ef87c04b..28755a97d1 100644 --- a/tests/phpunit/tests/rest-api/rest-users-controller.php +++ b/tests/phpunit/tests/rest-api/rest-users-controller.php @@ -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();