From 70b408c8fe24a6d5b78f15bfa1cabfd46fd17da2 Mon Sep 17 00:00:00 2001 From: "K. Adam White" Date: Thu, 10 Oct 2019 17:16:44 +0000 Subject: [PATCH] REST API: Fix error in _fields filtering logic where only one of several requested sibling properties would be included. Props kadamwhite, TimothyBlynJacobs. Fixes #48266. git-svn-id: https://develop.svn.wordpress.org/trunk@46456 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/rest-api.php | 8 ++- tests/phpunit/tests/rest-api.php | 96 ++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index c397bdc116..3e6f419f6b 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -743,8 +743,12 @@ function rest_filter_response_fields( $response, $server, $request ) { $parts = explode( '.', $field ); $ref = &$fields_as_keyed; while ( count( $parts ) > 1 ) { - $next = array_shift( $parts ); - $ref[ $next ] = array(); + $next = array_shift( $parts ); + if ( isset( $ref[ $next ] ) && true === $ref[ $next ] ) { + // Skip any sub-properties if their parent prop is already marked for inclusion. + break 2; + } + $ref[ $next ] = isset( $ref[ $next ] ) ? $ref[ $next ] : array(); $ref = &$ref[ $next ]; } $last = array_shift( $parts ); diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 2b8310f168..1efb81a348 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -560,6 +560,102 @@ class Tests_REST_API extends WP_UnitTestCase { ); } + /** + * Ensure that specifying a single top-level key in _fields includes that field and all children. + * + * @ticket 48266 + */ + public function test_rest_filter_response_fields_top_level_key() { + $response = new WP_REST_Response(); + + $response->set_data( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ) + ); + $request = array( + '_fields' => 'meta', + ); + + $response = rest_filter_response_fields( $response, null, $request ); + $this->assertEquals( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ), + $response->get_data() + ); + } + + /** + * Ensure that a top-level key in _fields supersedes any specified children of that field. + * + * @ticket 48266 + */ + public function test_rest_filter_response_fields_child_after_parent() { + $response = new WP_REST_Response(); + + $response->set_data( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ) + ); + $request = array( + '_fields' => 'meta,meta.key1', + ); + + $response = rest_filter_response_fields( $response, null, $request ); + $this->assertEquals( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ), + $response->get_data() + ); + } + + /** + * Ensure that specifying two sibling properties in _fields causes both to be included. + * + * @ticket 48266 + */ + public function test_rest_filter_response_fields_include_all_specified_siblings() { + $response = new WP_REST_Response(); + + $response->set_data( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ) + ); + $request = array( + '_fields' => 'meta.key1,meta.key2', + ); + + $response = rest_filter_response_fields( $response, null, $request ); + $this->assertEquals( + array( + 'meta' => array( + 'key1' => 1, + 'key2' => 2, + ), + ), + $response->get_data() + ); + } + /** * @ticket 42094 */