REST API: Add support for CURIEs.

CURIEs are Compact URIs, which provide a more usable way to use
custom relations in the API. The `wp` CURIE is registered by default
for `https://api.w.org/` URI relations.

Fixes #34729.
Props joehoyle.


git-svn-id: https://develop.svn.wordpress.org/trunk@36533 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Ryan McCue 2016-02-16 02:18:34 +00:00
parent 6dd1dd61a1
commit d7e7c0b81b
3 changed files with 106 additions and 0 deletions

View File

@ -256,4 +256,45 @@ class WP_REST_Response extends WP_HTTP_Response {
return $error;
}
/**
* Get the CURIEs (compact URIs) used for relations.
*
* @return array
*/
public function get_curies() {
$curies = array(
array(
'name' => 'wp',
'href' => 'https://api.w.org/{rel}',
'templated' => true,
),
);
/**
* Filter extra CURIEs available on API responses.
*
* CURIEs allow a shortened version of URI relations. This allows a more
* usable form for custom relations than using the full URI. These work
* similarly to how XML namespaces work.
*
* Registered CURIES need to specify a name and URI template. This will
* automatically transform URI relations into their shortened version.
* The shortened relation follows the format `{name}:{rel}`. `{rel}` in
* the URI template will be replaced with the `{rel}` part of the
* shortened relation.
*
* For example, a CURIE with name `example` and URI template
* `http://w.org/{rel}` would transform a `http://w.org/term` relation
* into `example:term`.
*
* Well-behaved clients should expand and normalise these back to their
* full URI relation, however some naive clients may not resolve these
* correctly, so adding new CURIEs may break backwards compatibility.
*
* @param array $additional Additional CURIEs to register with the API.
*/
$additional = apply_filters( 'rest_response_link_curies', array() );
return array_merge( $curies, $additional );
}
}

View File

@ -460,7 +460,28 @@ class WP_REST_Server {
// Convert links to part of the data.
$data = array();
$curies = $response->get_curies();
$used_curies = array();
foreach ( $links as $rel => $items ) {
// Convert $rel URIs to their compact versions if they exist.
foreach ( $curies as $curie ) {
$href_prefix = substr( $curie['href'], 0, strpos( $curie['href'], '{rel}' ) );
if ( strpos( $rel, $href_prefix ) !== 0 ) {
continue;
}
$used_curies[ $curie['name'] ] = $curie;
// Relation now changes from '$uri' to '$curie:$relation'
$rel_regex = str_replace( '\{rel\}', '([\w]+)', preg_quote( $curie['href'], '!' ) );
preg_match( '!' . $rel_regex . '!', $rel, $matches );
if ( $matches ) {
$rel = $curie['name'] . ':' . $matches[1];
}
break;
}
$data[ $rel ] = array();
foreach ( $items as $item ) {
@ -470,6 +491,11 @@ class WP_REST_Server {
}
}
// Push the curies onto the start of the links array.
if ( $used_curies ) {
$data = array_merge( array( 'curies' => array_values( $used_curies ) ), $data );
}
return $data;
}

View File

@ -400,6 +400,45 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
$this->assertEquals( 'embed', $alternate[1]['parameters']['context'] );
}
public function test_link_curies() {
$response = new WP_REST_Response();
$response->add_link( 'https://api.w.org/term', 'http://example.com/' );
$data = $this->server->response_to_data( $response, false );
$links = $data['_links'];
$this->assertArrayHasKey( 'wp:term', $links );
$this->assertArrayHasKey( 'curies', $links );
}
public function test_custom_curie_link() {
$response = new WP_REST_Response();
$response->add_link( 'http://mysite.com/contact.html', 'http://example.com/' );
add_filter( 'rest_response_link_curies', array( $this, 'add_custom_curie' ) );
$data = $this->server->response_to_data( $response, false );
$links = $data['_links'];
$this->assertArrayHasKey( 'my_site:contact', $links );
$this->assertArrayHasKey( 'curies', $links );
}
/**
* Helper callback to add a new custom curie via a filter.
*
* @param array $curies
* @return array
*/
public function add_custom_curie( $curies ) {
$curies[] = array(
'name' => 'my_site',
'href' => 'http://mysite.com/{rel}.html',
'templated' => true,
);
return $curies;
}
/**
* @depends test_link_embedding
*/