Make WordPress Core

Ticket #38131: 38131.2.diff

File 38131.2.diff, 4.6 KB (added by adamsilverstein, 7 years ago)
  • src/wp-includes/rest-api.php

    diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
    index e6cdc3a..c2fb113 100644
    a b function rest_api_default_filters() { 
    170170        // Default serving.
    171171        add_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
    172172        add_filter( 'rest_post_dispatch', 'rest_send_allow_header', 10, 3 );
     173        add_filter( 'rest_post_dispatch', 'rest_filter_response_fields', 10, 3 );
    173174
    174175        add_filter( 'rest_pre_dispatch', 'rest_handle_options_request', 10, 3 );
    175176}
    function rest_send_allow_header( $response, $server, $request ) { 
    618619}
    619620
    620621/**
     622 * Filter the API response to include only a white-listed set of response object fields.
     623 *
     624 * @since 4.8.0
     625 *
     626 * @param WP_REST_Response $response Current response being served.
     627 * @param WP_REST_Server   $server   ResponseHandler instance (usually WP_REST_Server).
     628 * @param WP_REST_Request  $request  The request that was used to make current response.
     629 *
     630 * @return WP_REST_Response Response to be served, trimmed down to contain a subset of fields.
     631 */
     632function rest_filter_response_fields( $response, $server, $request ) {
     633        if ( ! isset( $request['_fields'] ) || $response->is_error() ) {
     634                return $response;
     635        }
     636
     637        $data = $response->get_data();
     638
     639        $fields = (array) explode( ',', $request['_fields'] );
     640
     641        if ( 0 === count( $fields ) ) {
     642                return $response;
     643        }
     644
     645        // Trim off outside whitespace from the comma delimited list.
     646        $fields = array_map( 'trim', $fields );
     647
     648        $fields_as_keyed = array_combine( $fields, array_fill( 0, count( $fields ), true ) );
     649
     650        if ( wp_is_numeric_array( $data ) ) {
     651                $new_data = array();
     652                foreach ( $data as $item ) {
     653                        $new_data[] = array_intersect_key( $item, $fields_as_keyed );
     654                }
     655        } else {
     656                $new_data = array_intersect_key( $data, $fields_as_keyed );
     657        }
     658
     659        $response->set_data( $new_data );
     660
     661        return $response;
     662}
     663
     664/**
    621665 * Adds the REST API URL to the WP RSD endpoint.
    622666 *
    623667 * @since 4.4.0
  • tests/phpunit/tests/rest-api.php

    diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php
    index f303a01..cecfc1b 100644
    a b class Tests_REST_API extends WP_UnitTestCase { 
    300300        }
    301301
    302302        /**
     303         * Ensure that result fields are not whitelisted if no request['_fields'] is present.
     304         */
     305        public function test_rest_filter_response_fields_no_request_filter() {
     306                $response = new WP_REST_Response();
     307                $response->set_data( array( 'a' => true ) );
     308                $request = array();
     309
     310                $response = rest_filter_response_fields( $response, null, $request );
     311                $this->assertEquals( array( 'a' => true ), $response->get_data() );
     312        }
     313
     314        /**
     315         * Ensure that result fields are whitelisted if request['_fields'] is present.
     316         */
     317        public function test_rest_filter_response_fields_single_field_filter() {
     318                $response = new WP_REST_Response();
     319                $response->set_data( array(
     320                        'a' => 0,
     321                        'b' => 1,
     322                        'c' => 2,
     323                ) );
     324                $request = array(
     325                        '_fields' => 'b'
     326                );
     327
     328                $response = rest_filter_response_fields( $response, null, $request );
     329                $this->assertEquals( array( 'b' => 1 ), $response->get_data() );
     330        }
     331
     332        /**
     333         * Ensure that multiple comma-separated fields may be whitelisted with request['_fields'].
     334         */
     335        public function test_rest_filter_response_fields_multi_field_filter() {
     336                $response = new WP_REST_Response();
     337                $response->set_data( array(
     338                        'a' => 0,
     339                        'b' => 1,
     340                        'c' => 2,
     341                        'd' => 3,
     342                        'e' => 4,
     343                        'f' => 5,
     344                ) );
     345                $request = array(
     346                        '_fields' => 'b,c,e'
     347                );
     348
     349                $response = rest_filter_response_fields( $response, null, $request );
     350                $this->assertEquals( array(
     351                        'b' => 1,
     352                        'c' => 2,
     353                        'e' => 4,
     354                ), $response->get_data() );
     355        }
     356
     357        /**
     358         * Ensure that request['_fields'] whitelists apply to items in response collections.
     359         */
     360        public function test_rest_filter_response_fields_numeric_array() {
     361                $response = new WP_REST_Response();
     362                $response->set_data( array(
     363                        array(
     364                                'a' => 0,
     365                                'b' => 1,
     366                                'c' => 2,
     367                        ),
     368                        array(
     369                                'a' => 3,
     370                                'b' => 4,
     371                                'c' => 5,
     372                        ),
     373                        array(
     374                                'a' => 6,
     375                                'b' => 7,
     376                                'c' => 8,
     377                        ),
     378                ) );
     379                $request = array(
     380                        '_fields' => 'b,c'
     381                );
     382
     383                $response = rest_filter_response_fields( $response, null, $request );
     384                $this->assertEquals( array(
     385                        array(
     386                                'b' => 1,
     387                                'c' => 2,
     388                        ),
     389                        array(
     390                                'b' => 4,
     391                                'c' => 5,
     392                        ),
     393                        array(
     394                                'b' => 7,
     395                                'c' => 8,
     396                        ),
     397                ), $response->get_data() );
     398        }
     399
     400        /**
    303401         * The get_rest_url function should return a URL consistently terminated with a "/",
    304402         * whether the blog is configured with pretty permalink support or not.
    305403         */