WordPress.org

Make WordPress Core

Ticket #45605: 45605.2.diff

File 45605.2.diff, 4.8 KB (added by dlh, 7 months ago)
  • src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php

    diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php
    index d610504692..dc77556601 100644
    abstract class WP_REST_Controller { 
    518518         */
    519519        public function get_fields_for_response( $request ) {
    520520                $schema = $this->get_item_schema();
    521                 $fields = isset( $schema['properties'] ) ? array_keys( $schema['properties'] ) : array();
     521                $properties = isset( $schema['properties'] ) ? $schema['properties'] : array();
    522522
    523                 $additional_fields = $this->get_additional_fields();
    524                 foreach ( $additional_fields as $field_name => $field_options ) {
     523                foreach ( $this->get_additional_fields() as $field_name => $field_options ) {
    525524                        // For back-compat, include any field with an empty schema
    526525                        // because it won't be present in $this->get_item_schema().
    527526                        if ( is_null( $field_options['schema'] ) ) {
    528                                 $fields[] = $field_name;
     527                                $properties[ $field_name ] = $field_options;
     528                        }
     529                }
     530
     531                // Exclude fields that specify a different context than the request context.
     532                $context = $request['context'];
     533                if ( $context ) {
     534                        foreach ( $properties as $name => $options ) {
     535                                if ( isset( $options['context'] ) && ! in_array( $context, $options['context'], true ) ) {
     536                                        unset( $properties[ $name ] );
     537                                }
    529538                        }
    530539                }
    531540
     541                $fields = array_keys( $properties );
     542
    532543                if ( ! isset( $request['_fields'] ) ) {
    533544                        return $fields;
    534545                }
     546
    535547                $requested_fields = wp_parse_list( $request['_fields'] );
    536548                if ( 0 === count( $requested_fields ) ) {
    537549                        return $fields;
    538550                }
    539                 // Trim off outside whitespace from the comma delimited list.
    540                 $requested_fields = array_map( 'trim', $requested_fields );
     551
    541552                // Always persist 'id', because it can be needed for add_additional_fields_to_object().
    542553                if ( in_array( 'id', $fields, true ) ) {
    543554                        $requested_fields[] = 'id';
    544555                }
     556
    545557                return array_intersect( $fields, $requested_fields );
    546558        }
    547559
  • tests/phpunit/tests/rest-api/rest-controller.php

    diff --git tests/phpunit/tests/rest-api/rest-controller.php tests/phpunit/tests/rest-api/rest-controller.php
    index 6301e64d9d..f130abc62d 100644
    class WP_Test_REST_Controller extends WP_Test_REST_TestCase { 
    255255                );
    256256        }
    257257
     258        public function test_get_fields_for_response_filters_by_context() {
     259                $controller = new WP_REST_Test_Controller();
     260
     261                $request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
     262                $request->set_param( 'context', 'view' );
     263
     264                $schema = $controller->get_item_schema();
     265                $field  = 'somefield';
     266
     267                $listener = new MockAction();
     268                $method   = 'action';
     269
     270                register_rest_field(
     271                        $schema['title'],
     272                        $field,
     273                        array(
     274                                'schema'       => array(
     275                                        'type'    => 'string',
     276                                        'context' => array( 'embed' ),
     277                                ),
     278                                'get_callback' => array( $listener, $method ),
     279                        )
     280                );
     281
     282                $controller->prepare_item_for_response( array(), $request );
     283
     284                $this->assertSame( 0, $listener->get_call_count( $method ) );
     285
     286                $request->set_param( 'context', 'embed' );
     287
     288                $controller->prepare_item_for_response( array(), $request );
     289
     290                $this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
     291        }
     292
     293        public function test_filtering_fields_for_response_by_context_returns_fields_with_no_context() {
     294                $controller = new WP_REST_Test_Controller();
     295
     296                $request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
     297                $request->set_param( 'context', 'view' );
     298
     299                $schema = $controller->get_item_schema();
     300                $field  = 'somefield';
     301
     302                $listener = new MockAction();
     303                $method   = 'action';
     304
     305                register_rest_field(
     306                        $schema['title'],
     307                        $field,
     308                        array(
     309                                'schema'       => array(
     310                                        'type' => 'string',
     311                                ),
     312                                'get_callback' => array( $listener, $method ),
     313                        )
     314                );
     315
     316                $controller->prepare_item_for_response( array(), $request );
     317
     318                $this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
     319        }
     320
     321        public function test_filtering_fields_for_response_by_context_returns_fields_with_no_schema() {
     322                $controller = new WP_REST_Test_Controller();
     323
     324                $request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
     325                $request->set_param( 'context', 'view' );
     326
     327                $schema = $controller->get_item_schema();
     328                $field  = 'somefield';
     329
     330                $listener = new MockAction();
     331                $method   = 'action';
     332
     333                register_rest_field(
     334                        $schema['title'],
     335                        $field,
     336                        array(
     337                                'get_callback' => array( $listener, $method ),
     338                        )
     339                );
     340
     341                $controller->prepare_item_for_response( array(), $request );
     342
     343                $this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
     344        }
     345
    258346        public function test_add_additional_fields_to_object_respects_fields_param() {
    259347                $controller = new WP_REST_Test_Controller();
    260348                $request    = new WP_REST_Request( 'GET', '/wp/v2/testroute' );