WordPress.org

Make WordPress Core

Changeset 47224


Ignore:
Timestamp:
02/09/2020 08:52:06 PM (6 months 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.