mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-06-28 14:20:15 +00:00
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. git-svn-id: https://develop.svn.wordpress.org/trunk@47224 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -1571,3 +1571,25 @@ function rest_preload_api_request( $memo, $path ) {
|
||||
|
||||
return $memo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the "_embed" parameter into the list of resources to embed.
|
||||
*
|
||||
* @since 5.4.0
|
||||
*
|
||||
* @param string|array $embed Raw "_embed" parameter value.
|
||||
* @return true|string[] Either true to embed all embeds, or a list of relations to embed.
|
||||
*/
|
||||
function rest_parse_embed_param( $embed ) {
|
||||
if ( ! $embed || 'true' === $embed || '1' === $embed ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$rels = wp_parse_list( $embed );
|
||||
|
||||
if ( ! $rels ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $rels;
|
||||
}
|
||||
|
||||
@@ -398,7 +398,8 @@ class WP_REST_Server {
|
||||
}
|
||||
|
||||
// Embed links inside the request.
|
||||
$result = $this->response_to_data( $result, isset( $_GET['_embed'] ) );
|
||||
$embed = isset( $_GET['_embed'] ) ? rest_parse_embed_param( $_GET['_embed'] ) : false;
|
||||
$result = $this->response_to_data( $result, $embed );
|
||||
|
||||
/**
|
||||
* Filters the API response.
|
||||
@@ -450,9 +451,10 @@ class WP_REST_Server {
|
||||
* Converts a response to data to send.
|
||||
*
|
||||
* @since 4.4.0
|
||||
* @since 5.4.0 The $embed parameter can now contain a list of link relations to include.
|
||||
*
|
||||
* @param WP_REST_Response $response Response object.
|
||||
* @param bool $embed Whether links should be embedded.
|
||||
* @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links.
|
||||
* @return array {
|
||||
* Data with sub-requests embedded.
|
||||
*
|
||||
@@ -473,9 +475,11 @@ class WP_REST_Server {
|
||||
$this->embed_cache = array();
|
||||
// Determine if this is a numeric array.
|
||||
if ( wp_is_numeric_array( $data ) ) {
|
||||
$data = array_map( array( $this, 'embed_links' ), $data );
|
||||
foreach ( $data as $key => $item ) {
|
||||
$data[ $key ] = $this->embed_links( $item, $embed );
|
||||
}
|
||||
} else {
|
||||
$data = $this->embed_links( $data );
|
||||
$data = $this->embed_links( $data, $embed );
|
||||
}
|
||||
$this->embed_cache = array();
|
||||
}
|
||||
@@ -571,8 +575,10 @@ class WP_REST_Server {
|
||||
* Embeds the links from the data into the request.
|
||||
*
|
||||
* @since 4.4.0
|
||||
* @since 5.4.0 The $embed parameter can now contain a list of link relations to include.
|
||||
*
|
||||
* @param array $data Data from the request.
|
||||
* @param array $data Data from the request.
|
||||
* @param bool|string[] $embed Whether to embed all links or a filtered list of link relations.
|
||||
* @return array {
|
||||
* Data with sub-requests embedded.
|
||||
*
|
||||
@@ -580,7 +586,7 @@ class WP_REST_Server {
|
||||
* @type array [$_embedded] Embeddeds.
|
||||
* }
|
||||
*/
|
||||
protected function embed_links( $data ) {
|
||||
protected function embed_links( $data, $embed = true ) {
|
||||
if ( empty( $data['_links'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
@@ -588,6 +594,11 @@ class WP_REST_Server {
|
||||
$embedded = array();
|
||||
|
||||
foreach ( $data['_links'] as $rel => $links ) {
|
||||
// If a list of relations was specified, and the link relation is not in the whitelist, don't process the link.
|
||||
if ( is_array( $embed ) && ! in_array( $rel, $embed, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$embeds = array();
|
||||
|
||||
foreach ( $links as $item ) {
|
||||
|
||||
@@ -906,4 +906,31 @@ class Tests_REST_API extends WP_UnitTestCase {
|
||||
$this->assertEquals( '/wp/v2/posts', $request->get_route() );
|
||||
$this->assertEquals( 'GET', $request->get_method() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider _dp_rest_parse_embed_param
|
||||
*/
|
||||
public function test_rest_parse_embed_param( $expected, $embed ) {
|
||||
$this->assertEquals( $expected, rest_parse_embed_param( $embed ) );
|
||||
}
|
||||
|
||||
public function _dp_rest_parse_embed_param() {
|
||||
return array(
|
||||
array( true, '' ),
|
||||
array( true, null ),
|
||||
array( true, '1' ),
|
||||
array( true, 'true' ),
|
||||
array( true, array() ),
|
||||
array( array( 'author' ), 'author' ),
|
||||
array( array( 'author', 'replies' ), 'author,replies' ),
|
||||
array( array( 'author', 'replies' ), 'author,replies ' ),
|
||||
array( array( 'wp:term' ), 'wp:term' ),
|
||||
array( array( 'wp:term', 'wp:attachment' ), 'wp:term,wp:attachment' ),
|
||||
array( array( 'author' ), array( 'author' ) ),
|
||||
array( array( 'author', 'replies' ), array( 'author', 'replies' ) ),
|
||||
array( array( 'https://api.w.org/term' ), 'https://api.w.org/term' ),
|
||||
array( array( 'https://api.w.org/term', 'https://api.w.org/attachment' ), 'https://api.w.org/term,https://api.w.org/attachment' ),
|
||||
array( array( 'https://api.w.org/term', 'https://api.w.org/attachment' ), array( 'https://api.w.org/term', 'https://api.w.org/attachment' ) ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -845,6 +845,66 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
|
||||
$this->assertEquals( $self_not_filtered, $data['_links']['self'][0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider _dp_response_to_data_embedding
|
||||
*/
|
||||
public function test_response_to_data_embedding( $expected, $embed ) {
|
||||
$response = new WP_REST_Response();
|
||||
$response->add_link( 'author', rest_url( '404' ), array( 'embeddable' => true ) );
|
||||
$response->add_link( 'https://api.w.org/term', rest_url( '404' ), array( 'embeddable' => true ) );
|
||||
$response->add_link( 'https://wordpress.org', rest_url( '404' ), array( 'embeddable' => true ) );
|
||||
$response->add_link( 'no-embed', rest_url( '404' ) );
|
||||
|
||||
$data = rest_get_server()->response_to_data( $response, $embed );
|
||||
|
||||
if ( false === $expected ) {
|
||||
$this->assertArrayNotHasKey( '_embedded', $data );
|
||||
} else {
|
||||
$this->assertEqualSets( $expected, array_keys( $data['_embedded'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function _dp_response_to_data_embedding() {
|
||||
return array(
|
||||
array(
|
||||
array( 'author', 'wp:term', 'https://wordpress.org' ),
|
||||
true,
|
||||
),
|
||||
array(
|
||||
array( 'author', 'wp:term', 'https://wordpress.org' ),
|
||||
array( 'author', 'wp:term', 'https://wordpress.org' ),
|
||||
),
|
||||
array(
|
||||
array( 'author' ),
|
||||
array( 'author' ),
|
||||
),
|
||||
array(
|
||||
array( 'wp:term' ),
|
||||
array( 'wp:term' ),
|
||||
),
|
||||
array(
|
||||
array( 'https://wordpress.org' ),
|
||||
array( 'https://wordpress.org' ),
|
||||
),
|
||||
array(
|
||||
array( 'author', 'wp:term' ),
|
||||
array( 'author', 'wp:term' ),
|
||||
),
|
||||
array(
|
||||
false,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
false,
|
||||
array( 'no-embed' ),
|
||||
),
|
||||
array(
|
||||
array( 'author' ),
|
||||
array( 'author', 'no-embed' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function test_get_index() {
|
||||
$server = new WP_REST_Server();
|
||||
$server->register_route(
|
||||
|
||||
Reference in New Issue
Block a user