From 16dfb05173f7e53dd8fc3a42e58610a9045dc36d Mon Sep 17 00:00:00 2001 From: spacedmonkey Date: Fri, 22 Jul 2022 14:00:12 +0000 Subject: [PATCH] REST API: Avoid unnecessarily preparing item links. Do not call the `prepare_links` methods in core REST API controllers, unless the `_links` or `_embedded` fields are requested. There is no need to prepare links if they are never returned in the response. This saves resources, as many calls to `prepare_links` methods perform database queries. Props Spacedmonkey, timothyblynjacobs, rachelbaker, desrosj, dlh, hellofromTonya. Fixes #52992. Built from https://develop.svn.wordpress.org/trunk@53760 git-svn-id: http://core.svn.wordpress.org/trunk@53319 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- ...-rest-application-passwords-controller.php | 7 ++++- ...ass-wp-rest-block-directory-controller.php | 7 ++++- .../class-wp-rest-block-types-controller.php | 4 ++- .../class-wp-rest-comments-controller.php | 4 ++- .../endpoints/class-wp-rest-controller.php | 12 +++++++ ...class-wp-rest-global-styles-controller.php | 31 ++++++++++--------- .../class-wp-rest-menu-items-controller.php | 16 +++++----- ...lass-wp-rest-menu-locations-controller.php | 4 ++- .../class-wp-rest-menus-controller.php | 5 ++- .../class-wp-rest-plugins-controller.php | 7 ++++- .../class-wp-rest-post-types-controller.php | 4 ++- .../class-wp-rest-posts-controller.php | 16 +++++----- .../class-wp-rest-search-controller.php | 12 ++++--- .../class-wp-rest-sidebars-controller.php | 4 ++- .../class-wp-rest-taxonomies-controller.php | 4 ++- .../class-wp-rest-templates-controller.php | 16 +++++----- .../class-wp-rest-terms-controller.php | 4 ++- .../class-wp-rest-themes-controller.php | 4 ++- .../class-wp-rest-users-controller.php | 4 ++- .../class-wp-rest-widget-types-controller.php | 4 ++- .../class-wp-rest-widgets-controller.php | 4 ++- wp-includes/version.php | 2 +- 22 files changed, 119 insertions(+), 56 deletions(-) diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php index 9c842d0717..af920d21f5 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php @@ -610,6 +610,8 @@ class WP_REST_Application_Passwords_Controller extends WP_REST_Controller { return $user; } + $fields = $this->get_fields_for_response( $request ); + $prepared = array( 'uuid' => $item['uuid'], 'app_id' => empty( $item['app_id'] ) ? '' : $item['app_id'], @@ -627,7 +629,10 @@ class WP_REST_Application_Passwords_Controller extends WP_REST_Controller { $prepared = $this->filter_response_by_context( $prepared, $request['context'] ); $response = new WP_REST_Response( $prepared ); - $response->add_links( $this->prepare_links( $user, $item ) ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $user, $item ) ); + } /** * Filters the REST API response for an application password. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php index 37fa0a0e73..cfcb0dbc5c 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php @@ -119,6 +119,8 @@ class WP_REST_Block_Directory_Controller extends WP_REST_Controller { // Restores the more descriptive, specific name for use within this method. $plugin = $item; + $fields = $this->get_fields_for_response( $request ); + // There might be multiple blocks in a plugin. Only the first block is mapped. $block_data = reset( $plugin['blocks'] ); @@ -146,7 +148,10 @@ class WP_REST_Block_Directory_Controller extends WP_REST_Controller { $this->add_additional_fields_to_object( $block, $request ); $response = new WP_REST_Response( $block ); - $response->add_links( $this->prepare_links( $plugin ) ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $plugin ) ); + } return $response; } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php index 91d725c5f4..6ebecadc5f 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php @@ -306,7 +306,9 @@ class WP_REST_Block_Types_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $block_type ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $block_type ) ); + } /** * Filters a block type returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index 486e8e6d81..de2f6cc4eb 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -1119,7 +1119,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $comment ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $comment ) ); + } /** * Filters a comment returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-controller.php index b3f41c6a6a..982376cb2f 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-controller.php @@ -581,6 +581,18 @@ abstract class WP_REST_Controller { $fields = array_keys( $properties ); + /* + * '_links' and '_embedded' are not typically part of the item schema, + * but they can be specified in '_fields', so they are added here as a + * convenience for checking with rest_is_field_included(). + */ + $fields[] = '_links'; + if ( $request->has_param( '_embed' ) ) { + $fields[] = '_embedded'; + } + + $fields = array_unique( $fields ); + if ( ! isset( $request['_fields'] ) ) { return $fields; } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php index 0f6d103cae..f1a9d2482a 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php @@ -392,13 +392,15 @@ class WP_REST_Global_Styles_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $links = $this->prepare_links( $post->ID ); - $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions(); - $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $post->ID ); + $response->add_links( $links ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions(); + $self = $links['self']['href']; + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } } } @@ -590,13 +592,14 @@ class WP_REST_Global_Styles_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $links = array( - 'self' => array( - 'href' => rest_url( sprintf( '%s/%s/themes/%s', $this->namespace, $this->rest_base, $request['stylesheet'] ) ), - ), - ); - - $response->add_links( $links ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = array( + 'self' => array( + 'href' => rest_url( sprintf( '%s/%s/themes/%s', $this->namespace, $this->rest_base, $request['stylesheet'] ) ), + ), + ); + $response->add_links( $links ); + } return $response; } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php index 4cf8cf5f54..c50dded161 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php @@ -610,16 +610,18 @@ class WP_REST_Menu_Items_Controller extends WP_REST_Posts_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $links = $this->prepare_links( $item ); - $response->add_links( $links ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $item ); + $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions( $item, $request ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions( $item, $request ); - $self = $links['self']['href']; + $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } } } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php index ff9ab8e48f..5c06dc7a65 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php @@ -193,7 +193,9 @@ class WP_REST_Menu_Locations_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $location ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $location ) ); + } /** * Filters menu location data returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php index 9f723c473d..775d805efe 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php @@ -134,7 +134,10 @@ class WP_REST_Menus_Controller extends WP_REST_Terms_Controller { $data = $this->filter_response_by_context( $data, $context ); $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $term ) ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $term ) ); + } /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */ return apply_filters( "rest_prepare_{$this->taxonomy}", $response, $term, $request ); diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php index 2ba4238e4a..a31f11396f 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php @@ -576,6 +576,8 @@ class WP_REST_Plugins_Controller extends WP_REST_Controller { * @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 ); + $item = _get_plugin_data_markup_translate( $item['_file'], $item, false ); $marked = _get_plugin_data_markup_translate( $item['_file'], $item, true ); @@ -600,7 +602,10 @@ class WP_REST_Plugins_Controller extends WP_REST_Controller { $data = $this->add_additional_fields_to_object( $data, $request ); $response = new WP_REST_Response( $data ); - $response->add_links( $this->prepare_links( $item ) ); + + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $item ) ); + } /** * Filters plugin data for a REST API response. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php index 13ecec4744..cb2daa4b29 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php @@ -244,7 +244,9 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $post_type ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $post_type ) ); + } /** * Filters a post type returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index f07c8d2893..946f08eafa 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -1933,16 +1933,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $links = $this->prepare_links( $post ); - $response->add_links( $links ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $post ); + $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions( $post, $request ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions( $post, $request ); - $self = $links['self']['href']; + $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } } } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php index b87973c9d6..76021ff0b0 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php @@ -210,11 +210,13 @@ class WP_REST_Search_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $links = $handler->prepare_item_links( $item_id ); - $links['collection'] = array( - 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), - ); - $response->add_links( $links ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $handler->prepare_item_links( $item_id ); + $links['collection'] = array( + 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), + ); + $response->add_links( $links ); + } return $response; } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php index 3ce3beded2..449ad6bb5b 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php @@ -368,7 +368,9 @@ class WP_REST_Sidebars_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $sidebar ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $sidebar ) ); + } /** * Filters the REST API response for a sidebar. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php index 7376df60df..0690983d37 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php @@ -272,7 +272,9 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $taxonomy ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $taxonomy ) ); + } /** * Filters a taxonomy returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php index 1108fbeec7..6d70372cbc 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php @@ -662,13 +662,15 @@ class WP_REST_Templates_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $links = $this->prepare_links( $template->id ); - $response->add_links( $links ); - if ( ! empty( $links['self']['href'] ) ) { - $actions = $this->get_available_actions(); - $self = $links['self']['href']; - foreach ( $actions as $rel ) { - $response->add_link( $rel, $self ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $links = $this->prepare_links( $template->id ); + $response->add_links( $links ); + if ( ! empty( $links['self']['href'] ) ) { + $actions = $this->get_available_actions(); + $self = $links['self']['href']; + foreach ( $actions as $rel ) { + $response->add_link( $rel, $self ); + } } } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php index 8856609375..3a0baeac71 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php @@ -859,7 +859,9 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $item ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $item ) ); + } /** * Filters the term data for a REST API response. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php index b7c3282c85..71dbcb6193 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php @@ -331,7 +331,9 @@ class WP_REST_Themes_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $theme ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $theme ) ); + } /** * Filters theme data returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php index 5edd0fc57b..8f540789c6 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php @@ -1072,7 +1072,9 @@ class WP_REST_Users_Controller extends WP_REST_Controller { // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $user ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $user ) ); + } /** * Filters user data returned from the REST API. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php index e38d46b918..d721c32d64 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php @@ -335,7 +335,9 @@ class WP_REST_Widget_Types_Controller extends WP_REST_Controller { $response = rest_ensure_response( $data ); - $response->add_links( $this->prepare_links( $widget_type ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $widget_type ) ); + } /** * Filters the REST API response for a widget type. diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php index 079f18cc1f..e6ac11cf88 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php @@ -726,7 +726,9 @@ class WP_REST_Widgets_Controller extends WP_REST_Controller { $response = rest_ensure_response( $prepared ); - $response->add_links( $this->prepare_links( $prepared ) ); + if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { + $response->add_links( $this->prepare_links( $prepared ) ); + } /** * Filters the REST API response for a widget. diff --git a/wp-includes/version.php b/wp-includes/version.php index 9c50a26b7c..a5b15d04ed 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.1-alpha-53759'; +$wp_version = '6.1-alpha-53760'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.