REST API: Fix _fields filtering of registered rest fields.

Use rest_is_field_included when determining which additional fields to include to permit filtering by nested field properties.

Props Dudo, kadamwhite, TimothyBlynJacobs.
Fixes #49648.


git-svn-id: https://develop.svn.wordpress.org/trunk@47511 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
K. Adam White 2020-03-26 17:50:39 +00:00
parent 728a031767
commit bef2746334
3 changed files with 171 additions and 1 deletions

View File

@ -451,7 +451,7 @@ abstract class WP_REST_Controller {
continue;
}
if ( ! in_array( $field_name, $requested_fields, true ) ) {
if ( ! rest_is_field_included( $field_name, $requested_fields ) ) {
continue;
}

View File

@ -560,6 +560,48 @@ class Tests_REST_API extends WP_UnitTestCase {
);
}
/**
* Ensure inclusion of deeply nested fields may be controlled with request['_fields'].
*
* @ticket 49648
*/
public function test_rest_filter_response_fields_deeply_nested_field_filter() {
$response = new WP_REST_Response();
$response->set_data(
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
),
)
);
$request = array(
'_fields' => 'field.a.i,field.b.iv',
);
$response = rest_filter_response_fields( $response, null, $request );
$this->assertEquals(
array(
'field' => array(
'a' => array(
'i' => 'value i',
),
'b' => array(
'iv' => 'value iv',
),
),
),
$response->get_data()
);
}
/**
* Ensure that specifying a single top-level key in _fields includes that field and all children.
*

View File

@ -48,6 +48,13 @@ class WP_Test_REST_Controller extends WP_Test_REST_TestCase {
);
}
public function tearDown() {
parent::tearDown();
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function test_validate_schema_type_integer() {
$this->assertTrue(
@ -437,4 +444,125 @@ class WP_Test_REST_Controller extends WP_Test_REST_TestCase {
$this->assertTrue( $listener->get_call_count( $method ) > $first_call_count );
}
/**
* @dataProvider data_filter_nested_registered_rest_fields
* @ticket 49648
*/
public function test_filter_nested_registered_rest_fields( $filter, $expected ) {
$controller = new WP_REST_Test_Controller();
register_rest_field(
'type',
'field',
array(
'schema' => array(
'type' => 'object',
'description' => 'A complex object',
'context' => array( 'view', 'edit' ),
'properties' => array(
'a' => array(
'i' => 'string',
'ii' => 'string',
),
'b' => array(
'iii' => 'string',
'iv' => 'string',
),
),
),
'get_callback' => array( $this, 'register_nested_rest_field_get_callback' ),
)
);
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$request->set_param( '_fields', $filter );
$response = $controller->prepare_item_for_response( array(), $request );
$response = rest_filter_response_fields( $response, rest_get_server(), $request );
$this->assertEquals( $expected, $response->get_data() );
}
public function register_nested_rest_field_get_callback() {
return array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
);
}
public function data_filter_nested_registered_rest_fields() {
return array(
array(
'field',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
),
),
),
array(
'field.a',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
),
),
),
array(
'field.b',
array(
'field' => array(
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
),
),
),
array(
'field.a.i,field.b.iv',
array(
'field' => array(
'a' => array(
'i' => 'value i',
),
'b' => array(
'iv' => 'value iv',
),
),
),
),
array(
'field.a,field.b.iii',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
),
),
),
),
);
}
}