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 1b73881e96..dbd129cc43 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 @@ -385,12 +385,18 @@ abstract class WP_REST_Controller { $additional_fields = $this->get_additional_fields(); + $requested_fields = $this->get_fields_for_response( $request ); + foreach ( $additional_fields as $field_name => $field_options ) { if ( ! $field_options['get_callback'] ) { continue; } + if ( ! in_array( $field_name, $requested_fields, true ) ) { + continue; + } + $object[ $field_name ] = call_user_func( $field_options['get_callback'], $object, $field_name, $request, $this->get_object_type() ); } diff --git a/tests/phpunit/tests/rest-api/rest-controller.php b/tests/phpunit/tests/rest-api/rest-controller.php index 809ec17722..8052cd4c14 100644 --- a/tests/phpunit/tests/rest-api/rest-controller.php +++ b/tests/phpunit/tests/rest-api/rest-controller.php @@ -231,4 +231,45 @@ class WP_Test_REST_Controller extends WP_Test_REST_TestCase { $fields ); } + + public function test_add_additional_fields_to_object_respects_fields_param() { + $controller = new WP_REST_Test_Controller(); + $request = new WP_REST_Request( 'GET', '/wp/v2/testroute' ); + $schema = $controller->get_item_schema(); + $field = 'somefield'; + + $listener = new MockAction(); + $method = 'action'; + + register_rest_field( + $schema['title'], + $field, + array( + 'get_callback' => array( $listener, $method ), + 'schema' => array( + 'type' => 'string', + ), + ) + ); + + $item = array(); + + $controller->prepare_item_for_response( $item, $request ); + + $first_call_count = $listener->get_call_count( $method ); + + $this->assertTrue( $first_call_count > 0 ); + + $request->set_param( '_fields', 'somestring' ); + + $controller->prepare_item_for_response( $item, $request ); + + $this->assertSame( $first_call_count, $listener->get_call_count( $method ) ); + + $request->set_param( '_fields', $field ); + + $controller->prepare_item_for_response( $item, $request ); + + $this->assertTrue( $listener->get_call_count( $method ) > $first_call_count ); + } } diff --git a/tests/phpunit/tests/rest-api/rest-test-controller.php b/tests/phpunit/tests/rest-api/rest-test-controller.php index 52351fd745..b72ed7a415 100644 --- a/tests/phpunit/tests/rest-api/rest-test-controller.php +++ b/tests/phpunit/tests/rest-api/rest-test-controller.php @@ -10,9 +10,23 @@ * @group restapi */ class WP_REST_Test_Controller extends WP_REST_Controller { + /** + * Prepares the item for the REST response. + * + * @param mixed $item WordPress representation of the item. + * @param WP_REST_Request $request Request object. + * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response( $item, $request ) { + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $item = $this->add_additional_fields_to_object( $item, $request ); + $item = $this->filter_response_by_context( $item, $context ); + $response = rest_ensure_response( $item ); + return $response; + } /** - * Get the Post type's schema, conforming to JSON Schema + * Get the item's schema, conforming to JSON Schema. * * @return array */ @@ -72,7 +86,7 @@ class WP_REST_Test_Controller extends WP_REST_Controller { ), ); - return $schema; + return $this->add_additional_fields_schema( $schema ); } }