Make WordPress Core

Changeset 47224


Ignore:
Timestamp:
02/09/2020 08:52:06 PM (7 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Introduce selective link embedding.

Previously the _embed flag would embed all embeddable links in a response even if only a subset of the links were necessary. Now, a list of link relations can be passed in the _embed parameter to restrict the list of embedded objects.

Props rheinardkorf, adamsilverstein, jnylen0, cklosows, chrisvanpatten, TimothyBlynJacobs.
Fixes #39696.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api.php

    r47219 r47224  
    15721572        return $memo;
    15731573}
     1574
     1575/**
     1576 * Parses the "_embed" parameter into the list of resources to embed.
     1577 *
     1578 * @since 5.4.0
     1579 *
     1580 * @param string|array $embed Raw "_embed" parameter value.
     1581 * @return true|string[] Either true to embed all embeds, or a list of relations to embed.
     1582 */
     1583function rest_parse_embed_param( $embed ) {
     1584        if ( ! $embed || 'true' === $embed || '1' === $embed ) {
     1585                return true;
     1586        }
     1587
     1588        $rels = wp_parse_list( $embed );
     1589
     1590        if ( ! $rels ) {
     1591                return true;
     1592        }
     1593
     1594        return $rels;
     1595}
  • trunk/src/wp-includes/rest-api/class-wp-rest-server.php

    r47138 r47224  
    399399
    400400                        // Embed links inside the request.
    401                         $result = $this->response_to_data( $result, isset( $_GET['_embed'] ) );
     401                        $embed  = isset( $_GET['_embed'] ) ? rest_parse_embed_param( $_GET['_embed'] ) : false;
     402                        $result = $this->response_to_data( $result, $embed );
    402403
    403404                        /**
     
    451452         *
    452453         * @since 4.4.0
     454         * @since 5.4.0 The $embed parameter can now contain a list of link relations to include.
    453455         *
    454456         * @param WP_REST_Response $response Response object.
    455          * @param bool             $embed    Whether links should be embedded.
     457         * @param bool|string[]    $embed    Whether to embed all links, a filtered list of link relations, or no links.
    456458         * @return array {
    457459         *     Data with sub-requests embedded.
     
    474476                        // Determine if this is a numeric array.
    475477                        if ( wp_is_numeric_array( $data ) ) {
    476                                 $data = array_map( array( $this, 'embed_links' ), $data );
     478                                foreach ( $data as $key => $item ) {
     479                                        $data[ $key ] = $this->embed_links( $item, $embed );
     480                                }
    477481                        } else {
    478                                 $data = $this->embed_links( $data );
     482                                $data = $this->embed_links( $data, $embed );
    479483                        }
    480484                        $this->embed_cache = array();
     
    572576         *
    573577         * @since 4.4.0
    574          *
    575          * @param array $data Data from the request.
     578         * @since 5.4.0 The $embed parameter can now contain a list of link relations to include.
     579         *
     580         * @param array         $data  Data from the request.
     581         * @param bool|string[] $embed Whether to embed all links or a filtered list of link relations.
    576582         * @return array {
    577583         *     Data with sub-requests embedded.
     
    581587         * }
    582588         */
    583         protected function embed_links( $data ) {
     589        protected function embed_links( $data, $embed = true ) {
    584590                if ( empty( $data['_links'] ) ) {
    585591                        return $data;
     
    589595
    590596                foreach ( $data['_links'] as $rel => $links ) {
     597                        // If a list of relations was specified, and the link relation is not in the whitelist, don't process the link.
     598                        if ( is_array( $embed ) && ! in_array( $rel, $embed, true ) ) {
     599                                continue;
     600                        }
     601
    591602                        $embeds = array();
    592603
  • trunk/tests/phpunit/tests/rest-api.php

    r47122 r47224  
    907907                $this->assertEquals( 'GET', $request->get_method() );
    908908        }
     909
     910        /**
     911         * @dataProvider _dp_rest_parse_embed_param
     912         */
     913        public function test_rest_parse_embed_param( $expected, $embed ) {
     914                $this->assertEquals( $expected, rest_parse_embed_param( $embed ) );
     915        }
     916
     917        public function _dp_rest_parse_embed_param() {
     918                return array(
     919                        array( true, '' ),
     920                        array( true, null ),
     921                        array( true, '1' ),
     922                        array( true, 'true' ),
     923                        array( true, array() ),
     924                        array( array( 'author' ), 'author' ),
     925                        array( array( 'author', 'replies' ), 'author,replies' ),
     926                        array( array( 'author', 'replies' ), 'author,replies ' ),
     927                        array( array( 'wp:term' ), 'wp:term' ),
     928                        array( array( 'wp:term', 'wp:attachment' ), 'wp:term,wp:attachment' ),
     929                        array( array( 'author' ), array( 'author' ) ),
     930                        array( array( 'author', 'replies' ), array( 'author', 'replies' ) ),
     931                        array( array( 'https://api.w.org/term' ), 'https://api.w.org/term' ),
     932                        array( array( 'https://api.w.org/term', 'https://api.w.org/attachment' ), 'https://api.w.org/term,https://api.w.org/attachment' ),
     933                        array( array( 'https://api.w.org/term', 'https://api.w.org/attachment' ), array( 'https://api.w.org/term', 'https://api.w.org/attachment' ) ),
     934                );
     935        }
    909936}
  • trunk/tests/phpunit/tests/rest-api/rest-server.php

    r47138 r47224  
    844844                );
    845845                $this->assertEquals( $self_not_filtered, $data['_links']['self'][0] );
     846        }
     847
     848        /**
     849         * @dataProvider _dp_response_to_data_embedding
     850         */
     851        public function test_response_to_data_embedding( $expected, $embed ) {
     852                $response = new WP_REST_Response();
     853                $response->add_link( 'author', rest_url( '404' ), array( 'embeddable' => true ) );
     854                $response->add_link( 'https://api.w.org/term', rest_url( '404' ), array( 'embeddable' => true ) );
     855                $response->add_link( 'https://wordpress.org', rest_url( '404' ), array( 'embeddable' => true ) );
     856                $response->add_link( 'no-embed', rest_url( '404' ) );
     857
     858                $data = rest_get_server()->response_to_data( $response, $embed );
     859
     860                if ( false === $expected ) {
     861                        $this->assertArrayNotHasKey( '_embedded', $data );
     862                } else {
     863                        $this->assertEqualSets( $expected, array_keys( $data['_embedded'] ) );
     864                }
     865        }
     866
     867        public function _dp_response_to_data_embedding() {
     868                return array(
     869                        array(
     870                                array( 'author', 'wp:term', 'https://wordpress.org' ),
     871                                true,
     872                        ),
     873                        array(
     874                                array( 'author', 'wp:term', 'https://wordpress.org' ),
     875                                array( 'author', 'wp:term', 'https://wordpress.org' ),
     876                        ),
     877                        array(
     878                                array( 'author' ),
     879                                array( 'author' ),
     880                        ),
     881                        array(
     882                                array( 'wp:term' ),
     883                                array( 'wp:term' ),
     884                        ),
     885                        array(
     886                                array( 'https://wordpress.org' ),
     887                                array( 'https://wordpress.org' ),
     888                        ),
     889                        array(
     890                                array( 'author', 'wp:term' ),
     891                                array( 'author', 'wp:term' ),
     892                        ),
     893                        array(
     894                                false,
     895                                false,
     896                        ),
     897                        array(
     898                                false,
     899                                array( 'no-embed' ),
     900                        ),
     901                        array(
     902                                array( 'author' ),
     903                                array( 'author', 'no-embed' ),
     904                        ),
     905                );
    846906        }
    847907
Note: See TracChangeset for help on using the changeset viewer.