Make WordPress Core

Ticket #38131: 38131.4.diff

File 38131.4.diff, 5.2 KB (added by kadamwhite, 7 years ago)

Revision of 38131.2.diff supporting array format on _fields param

  • src/wp-includes/rest-api.php

     
    165165        // Default serving.
    166166        add_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
    167167        add_filter( 'rest_post_dispatch', 'rest_send_allow_header', 10, 3 );
     168        add_filter( 'rest_post_dispatch', 'rest_filter_response_fields', 10, 3 );
    168169
    169170        add_filter( 'rest_pre_dispatch', 'rest_handle_options_request', 10, 3 );
    170171}
     
    633634}
    634635
    635636/**
     637 * Filter the API response to include only a white-listed set of response object fields.
     638 *
     639 * @since 4.8.0
     640 *
     641 * @param WP_REST_Response $response Current response being served.
     642 * @param WP_REST_Server   $server   ResponseHandler instance (usually WP_REST_Server).
     643 * @param WP_REST_Request  $request  The request that was used to make current response.
     644 *
     645 * @return WP_REST_Response Response to be served, trimmed down to contain a subset of fields.
     646 */
     647function rest_filter_response_fields( $response, $server, $request ) {
     648        if ( ! isset( $request['_fields'] ) || $response->is_error() ) {
     649                return $response;
     650        }
     651
     652        $data = $response->get_data();
     653
     654        $fields = is_array( $request['_fields']  ) ? $request['_fields'] : preg_split( '/[\s,]+/', $request['_fields'] );
     655
     656        if ( 0 === count( $fields ) ) {
     657                return $response;
     658        }
     659
     660        // Trim off outside whitespace from the comma delimited list.
     661        $fields = array_map( 'trim', $fields );
     662
     663        $fields_as_keyed = array_combine( $fields, array_fill( 0, count( $fields ), true ) );
     664
     665        if ( wp_is_numeric_array( $data ) ) {
     666                $new_data = array();
     667                foreach ( $data as $item ) {
     668                        $new_data[] = array_intersect_key( $item, $fields_as_keyed );
     669                }
     670        } else {
     671                $new_data = array_intersect_key( $data, $fields_as_keyed );
     672        }
     673
     674        $response->set_data( $new_data );
     675
     676        return $response;
     677}
     678
     679/**
    636680 * Adds the REST API URL to the WP RSD endpoint.
    637681 *
    638682 * @since 4.4.0
  • tests/phpunit/tests/rest-api.php

     
    305305        }
    306306
    307307        /**
     308         * Ensure that result fields are not whitelisted if no request['_fields'] is present.
     309         */
     310        public function test_rest_filter_response_fields_no_request_filter() {
     311                $response = new WP_REST_Response();
     312                $response->set_data( array( 'a' => true ) );
     313                $request = array();
     314
     315                $response = rest_filter_response_fields( $response, null, $request );
     316                $this->assertEquals( array( 'a' => true ), $response->get_data() );
     317        }
     318
     319        /**
     320         * Ensure that result fields are whitelisted if request['_fields'] is present.
     321         */
     322        public function test_rest_filter_response_fields_single_field_filter() {
     323                $response = new WP_REST_Response();
     324                $response->set_data( array(
     325                        'a' => 0,
     326                        'b' => 1,
     327                        'c' => 2,
     328                ) );
     329                $request = array(
     330                        '_fields' => 'b'
     331                );
     332
     333                $response = rest_filter_response_fields( $response, null, $request );
     334                $this->assertEquals( array( 'b' => 1 ), $response->get_data() );
     335        }
     336
     337        /**
     338         * Ensure that multiple comma-separated fields may be whitelisted with request['_fields'].
     339         */
     340        public function test_rest_filter_response_fields_multi_field_filter() {
     341                $response = new WP_REST_Response();
     342                $response->set_data( array(
     343                        'a' => 0,
     344                        'b' => 1,
     345                        'c' => 2,
     346                        'd' => 3,
     347                        'e' => 4,
     348                        'f' => 5,
     349                ) );
     350                $request = array(
     351                        '_fields' => 'b,c,e'
     352                );
     353
     354                $response = rest_filter_response_fields( $response, null, $request );
     355                $this->assertEquals( array(
     356                        'b' => 1,
     357                        'c' => 2,
     358                        'e' => 4,
     359                ), $response->get_data() );
     360        }
     361
     362        /**
     363         * Ensure that multiple comma-separated fields may be whitelisted
     364         * with request['_fields'] using query parameter array syntax.
     365         */
     366        public function test_rest_filter_response_fields_multi_field_filter_array() {
     367                $response = new WP_REST_Response();
     368
     369                $response->set_data( array(
     370                        'a' => 0,
     371                        'b' => 1,
     372                        'c' => 2,
     373                        'd' => 3,
     374                        'e' => 4,
     375                        'f' => 5,
     376                ) );
     377                $request = array(
     378                        '_fields' => array( 'b', 'c', 'e' )
     379                );
     380
     381                $response = rest_filter_response_fields( $response, null, $request );
     382                $this->assertEquals( array(
     383                        'b' => 1,
     384                        'c' => 2,
     385                        'e' => 4,
     386                ), $response->get_data() );
     387        }
     388
     389        /**
     390         * Ensure that request['_fields'] whitelists apply to items in response collections.
     391         */
     392        public function test_rest_filter_response_fields_numeric_array() {
     393                $response = new WP_REST_Response();
     394                $response->set_data( array(
     395                        array(
     396                                'a' => 0,
     397                                'b' => 1,
     398                                'c' => 2,
     399                        ),
     400                        array(
     401                                'a' => 3,
     402                                'b' => 4,
     403                                'c' => 5,
     404                        ),
     405                        array(
     406                                'a' => 6,
     407                                'b' => 7,
     408                                'c' => 8,
     409                        ),
     410                ) );
     411                $request = array(
     412                        '_fields' => 'b,c'
     413                );
     414
     415                $response = rest_filter_response_fields( $response, null, $request );
     416                $this->assertEquals( array(
     417                        array(
     418                                'b' => 1,
     419                                'c' => 2,
     420                        ),
     421                        array(
     422                                'b' => 4,
     423                                'c' => 5,
     424                        ),
     425                        array(
     426                                'b' => 7,
     427                                'c' => 8,
     428                        ),
     429                ), $response->get_data() );
     430        }
     431
     432        /**
    308433         * The get_rest_url function should return a URL consistently terminated with a "/",
    309434         * whether the blog is configured with pretty permalink support or not.
    310435         */