From 9ea3656e1eea5927e9d6128022735e38a3f708d9 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 19 Nov 2018 14:09:07 +0000 Subject: [PATCH] REST API: Include fields with null schema in `get_fields_for_response()`. In [43736], we prevented rendering fields when not present in `?_fields=`. However, because `get_fields_for_response()` is dependent on `get_item_schema()`, any custom fields registered with a null schema would be incorrectly excluded from the response. Because the REST API permits a null schema for `register_rest_field()`, those fields should be included in the available fields for a response. Fixes #45220. git-svn-id: https://develop.svn.wordpress.org/branches/5.0@43908 602fd350-edb4-49c9-b593-d223f7449a82 --- .../endpoints/class-wp-rest-controller.php | 10 ++++++ .../tests/rest-api/rest-posts-controller.php | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) 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 f98d1ad57e..caee7204ea 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 @@ -519,6 +519,16 @@ abstract class WP_REST_Controller { public function get_fields_for_response( $request ) { $schema = $this->get_item_schema(); $fields = isset( $schema['properties'] ) ? array_keys( $schema['properties'] ) : array(); + + $additional_fields = $this->get_additional_fields(); + foreach ( $additional_fields as $field_name => $field_options ) { + // For back-compat, include any field with an empty schema + // because it won't be present in $this->get_item_schema(). + if ( is_null( $field_options['schema'] ) ) { + $fields[] = $field_name; + } + } + if ( ! isset( $request['_fields'] ) ) { return $fields; } diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index 10f6a6eebc..ff97d2648d 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -3365,6 +3365,38 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $wp_rest_additional_fields = array(); } + /** + * @ticket 45220 + */ + public function test_get_additional_field_registration_null_schema() { + register_rest_field( 'post', 'my_custom_int', array( + 'schema' => null, + 'get_callback' => array( $this, 'additional_field_get_callback' ), + 'update_callback' => null, + ) ); + $post_id = $this->factory->post->create(); + + // 'my_custom_int' should appear because ?_fields= isn't set. + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); + $response = $this->server->dispatch( $request ); + $this->assertArrayHasKey( 'my_custom_int', $response->data ); + + // 'my_custom_int' should appear because it's present in ?_fields=. + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); + $request->set_param( '_fields', 'title,my_custom_int' ); + $response = $this->server->dispatch( $request ); + $this->assertArrayHasKey( 'my_custom_int', $response->data ); + + // 'my_custom_int' should not appear because it's not present in ?_fields=. + $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); + $request->set_param( '_fields', 'title' ); + $response = $this->server->dispatch( $request ); + $this->assertArrayNotHasKey( 'my_custom_int', $response->data ); + + global $wp_rest_additional_fields; + $wp_rest_additional_fields = array(); + } + public function test_additional_field_update_errors() { $schema = array( 'type' => 'integer',