Embeds: Who put this REST API infrastructure in my WordPress?

Well, while it's here, we probably should make use of it. The oEmbed endpoint now uses the REST API infrastructure, instead of providing its own.

Props swissspidy.

Fixes #34207.



git-svn-id: https://develop.svn.wordpress.org/trunk@35436 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Gary Pendergast 2015-10-29 22:50:13 +00:00
parent 4b10def07e
commit 4832d8d933
8 changed files with 371 additions and 421 deletions

View File

@ -10,36 +10,18 @@
/**
* oEmbed API endpoint controller.
*
* Parses the oEmbed API requests and delivers
* XML and JSON responses.
* Registers the API route and delivers the response data.
* The output format (XML or JSON) is handled by the REST API.
*
* @since 4.4.0
*/
final class WP_oEmbed_Controller {
/**
* Hook into the query parsing to detect oEmbed requests.
*
* If an oEmbed request is made, trigger the output.
* Register the oEmbed REST API route.
*
* @since 4.4.0
*
* @param WP_Query $wp_query The WP_Query instance (passed by reference).
*/
public function parse_query( $wp_query ) {
if ( false === $wp_query->get( 'oembed', false ) ) {
return;
}
if ( false === $wp_query->get( 'url', false ) ) {
status_header( 400 );
return get_status_header_desc( 400 );
exit;
}
$url = esc_url_raw( get_query_var( 'url' ) );
$format = wp_oembed_ensure_format( get_query_var( 'format' ) );
public function register_routes() {
/**
* Filter the maxwidth oEmbed parameter.
*
@ -48,30 +30,40 @@ final class WP_oEmbed_Controller {
* @param int $maxwidth Maximum allowed width. Default 600.
*/
$maxwidth = apply_filters( 'oembed_default_width', 600 );
$maxwidth = absint( get_query_var( 'maxwidth', $maxwidth ) );
$callback = get_query_var( '_jsonp', false );
$request = array(
'url' => $url,
'format' => $format,
'maxwidth' => $maxwidth,
'callback' => $callback,
);
echo $this->dispatch( $request );
exit;
register_rest_route( 'oembed/1.0/', '/embed', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'args' => array(
'url' => array(
'required' => true,
'sanitize_callback' => 'esc_url_raw',
),
'format' => array(
'default' => 'json',
'sanitize_callback' => 'wp_oembed_ensure_format',
),
'maxwidth' => array(
'default' => $maxwidth,
'sanitize_callback' => 'absint',
),
),
),
) );
}
/**
* Handle the whole request and print the response.
* Callback for the API endpoint.
*
* Returns the JSON object for the post.
*
* @since 4.4.0
*
* @param array $request The request arguments.
* @return string The oEmbed API response.
* @param WP_REST_Request $request Full data about the request.
* @return WP_Error|array oEmbed response data or WP_Error on failure.
*/
public function dispatch( $request ) {
public function get_item( $request ) {
$post_id = url_to_postid( $request['url'] );
/**
@ -86,79 +78,10 @@ final class WP_oEmbed_Controller {
$data = get_oembed_response_data( $post_id, $request['maxwidth'] );
if ( false === $data ) {
status_header( 404 );
return get_status_header_desc( 404 );
if ( ! $data ) {
return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) );
}
if ( 'json' === $request['format'] ) {
return $this->json_response( $data, $request );
}
return $this->xml_response( $data );
}
/**
* Print the oEmbed JSON response.
*
* @since 4.4.0
*
* @param array $data The oEmbed response data.
* @param array $request The request arguments.
* @return string The JSON response data.
*/
public function json_response( $data, $request ) {
if ( ! is_string( $request['callback'] ) || preg_match( '/[^\w\.]/', $request['callback'] ) ) {
$request['callback'] = false;
}
$result = wp_json_encode( $data );
// Bail if the result couldn't be JSON encoded.
if ( ! $result || ! is_array( $data ) || empty( $data ) ) {
status_header( 501 );
return get_status_header_desc( 501 );
}
if ( ! headers_sent() ) {
$content_type = $request['callback'] ? 'application/javascript' : 'application/json';
header( 'Content-Type: ' . $content_type . '; charset=' . get_option( 'blog_charset' ) );
header( 'X-Content-Type-Options: nosniff' );
}
if ( $request['callback'] ) {
return '/**/' . $request['callback'] . '(' . $result . ')';
}
return $result;
}
/**
* Print the oEmbed XML response.
*
* @since 4.4.0
*
* @param array $data The oEmbed response data.
* @return string The XML response data.
*/
public function xml_response( $data ) {
if ( ! class_exists( 'SimpleXMLElement' ) ) {
status_header( 501 );
return get_status_header_desc( 501 );
}
$result = _oembed_create_xml( $data );
// Bail if there's no XML.
if ( ! $result ) {
status_header( 501 );
return get_status_header_desc( 501 );
}
if ( ! headers_sent() ) {
header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) );
}
return $result;
return $data;
}
}

View File

@ -15,7 +15,7 @@ class WP {
* @access public
* @var array
*/
public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'title', 'embed', 'oembed', 'format', 'url', '_jsonp', 'maxwidth' );
public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'title', 'embed' );
/**
* Private query variables.

View File

@ -439,31 +439,32 @@ add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 );
add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
// Embeds
add_action( 'parse_query', 'wp_oembed_parse_query' );
add_action( 'rest_api_init', 'wp_oembed_register_route' );
add_filter( 'rest_pre_serve_request', '_oembed_rest_pre_serve_request', 10, 4 );
add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
add_action( 'wp_head', 'wp_oembed_add_host_js' );
add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
add_action( 'wp_head', 'wp_oembed_add_host_js' );
add_action( 'embed_head', 'print_emoji_detection_script' );
add_action( 'embed_head', 'print_emoji_styles' );
add_action( 'embed_head', 'print_embed_styles' );
add_action( 'embed_head', 'wp_print_head_scripts', 20 );
add_action( 'embed_head', 'wp_print_styles', 20 );
add_action( 'embed_head', 'wp_no_robots' );
add_action( 'embed_head', 'rel_canonical' );
add_action( 'embed_head', 'locale_stylesheet' );
add_action( 'embed_head', 'print_emoji_detection_script' );
add_action( 'embed_head', 'print_emoji_styles' );
add_action( 'embed_head', 'print_embed_styles' );
add_action( 'embed_head', 'wp_print_head_scripts', 20 );
add_action( 'embed_head', 'wp_print_styles', 20 );
add_action( 'embed_head', 'wp_no_robots' );
add_action( 'embed_head', 'rel_canonical' );
add_action( 'embed_head', 'locale_stylesheet' );
add_action( 'embed_footer', 'print_embed_scripts' );
add_action( 'embed_footer', 'wp_print_footer_scripts', 20 );
add_action( 'embed_footer', 'print_embed_scripts' );
add_action( 'embed_footer', 'wp_print_footer_scripts', 20 );
add_filter( 'excerpt_more', 'wp_embed_excerpt_more', 20 );
add_filter( 'the_excerpt_embed', 'wptexturize' );
add_filter( 'the_excerpt_embed', 'convert_chars' );
add_filter( 'the_excerpt_embed', 'wpautop' );
add_filter( 'the_excerpt_embed', 'shortcode_unautop' );
add_filter( 'the_excerpt_embed', 'wp_embed_excerpt_attachment' );
add_filter( 'excerpt_more', 'wp_embed_excerpt_more', 20 );
add_filter( 'the_excerpt_embed', 'wptexturize' );
add_filter( 'the_excerpt_embed', 'convert_chars' );
add_filter( 'the_excerpt_embed', 'wpautop' );
add_filter( 'the_excerpt_embed', 'shortcode_unautop' );
add_filter( 'the_excerpt_embed', 'wp_embed_excerpt_attachment' );
add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 );
add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 );
add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
unset( $filter, $action );

View File

@ -328,17 +328,13 @@ function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
}
/**
* Parses an oEmbed API query.
* Registers the oEmbed REST API route.
*
* @since 4.4.0
*
* @see WP_oEmbed_Controller::parse_query()
*
* @param WP_Query $wp_query The current WP_Query instance.
*/
function wp_oembed_parse_query( $wp_query ) {
function wp_oembed_register_route() {
$controller = new WP_oEmbed_Controller();
$controller->parse_query( $wp_query );
$controller->register_routes();
}
/**
@ -421,7 +417,7 @@ function get_post_embed_url( $post = null ) {
* @return string The oEmbed endpoint URL.
*/
function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) {
$url = add_query_arg( array( 'oembed' => 'true' ), home_url( '/' ) );
$url = rest_url( 'oembed/1.0/embed' );
if ( 'json' === $format ) {
$format = false;
@ -545,17 +541,8 @@ function get_oembed_response_data( $post = null, $width ) {
'max' => 600
) );
if ( $width < $min_max_width['min'] ) {
$width = $min_max_width['min'];
} elseif ( $width > $min_max_width['max'] ) {
$width = $min_max_width['max'];
}
$height = ceil( $width / 16 * 9 );
if ( 200 > $height ) {
$height = 200;
}
$width = min( max( $min_max_width['min'], $width ), $min_max_width['max'] );
$height = max( ceil( $width / 16 * 9 ), 200 );
$data = array(
'version' => '1.0',
@ -646,6 +633,61 @@ function wp_oembed_ensure_format( $format ) {
return $format;
}
/**
* Hooks into the REST API output to print XML instead of JSON.
*
* This is only done for the oEmbed API endpoint,
* which supports both formats.
*
* @access private
* @since 4.4.0
*
* @param bool $served Whether the request has already been served.
* @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response.
* @param WP_REST_Request $request Request used to generate the response.
* @param WP_REST_Server $server Server instance.
* @return true
*/
function _oembed_rest_pre_serve_request( $served, $result, $request, $server ) {
$params = $request->get_params();
if ( '/oembed/1.0/embed' !== $request->get_route() || 'GET' !== $request->get_method() ) {
return $served;
}
if ( ! isset( $params['format'] ) || 'xml' !== $params['format'] ) {
return $served;
}
// Embed links inside the request.
$data = $server->response_to_data( $result, false );
if ( 404 === $result->get_status() ) {
$data = $data[0];
}
if ( ! class_exists( 'SimpleXMLElement' ) ) {
status_header( 501 );
die( get_status_header_desc( 501 ) );
}
$result = _oembed_create_xml( $data );
// Bail if there's no XML.
if ( ! $result ) {
status_header( 501 );
return get_status_header_desc( 501 );
}
if ( ! headers_sent() ) {
$server->send_header( 'Content-Type', 'text/xml; charset=' . get_option( 'blog_charset' ) );
}
echo $result;
return true;
}
/**
* Creates an XML string from a given array.
*

View File

@ -2,217 +2,22 @@
/**
* @group oembed
* @group restapi
*/
class Test_oEmbed_Controller extends WP_UnitTestCase {
function test_request_with_bad_url() {
$request = array(
'url' => '',
'format' => 'json',
'maxwidth' => 600,
);
$legacy_controller = new WP_oEmbed_Controller();
$this->assertEquals( get_status_header_desc( 404 ), $legacy_controller->dispatch( $request ) );
}
function test_request_json() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
// WP_Query arguments.
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'json',
'maxwidth' => 400,
'callback' => '',
'oembed' => true,
);
$legacy_controller = new WP_oEmbed_Controller();
$data = json_decode( $legacy_controller->dispatch( $request ), true );
$this->assertTrue( is_array( $data ) );
$this->assertArrayHasKey( 'version', $data );
$this->assertArrayHasKey( 'provider_name', $data );
$this->assertArrayHasKey( 'provider_url', $data );
$this->assertArrayHasKey( 'author_name', $data );
$this->assertArrayHasKey( 'author_url', $data );
$this->assertArrayHasKey( 'title', $data );
$this->assertArrayHasKey( 'type', $data );
$this->assertArrayHasKey( 'width', $data );
$this->assertEquals( '1.0', $data['version'] );
$this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] );
$this->assertEquals( get_home_url(), $data['provider_url'] );
$this->assertEquals( $user->display_name, $data['author_name'] );
$this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
$this->assertEquals( $post->post_title, $data['title'] );
$this->assertEquals( 'rich', $data['type'] );
$this->assertTrue( $data['width'] <= $request['maxwidth'] );
}
function test_request_jsonp() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'json',
'maxwidth' => 600,
'callback' => 'mycallback',
);
$legacy_controller = new WP_oEmbed_Controller();
$data = $legacy_controller->dispatch( $request );
$this->assertEquals( 0, strpos( $data, '/**/mycallback(' ) );
}
function test_request_jsonp_invalid_callback() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'json',
'maxwidth' => 600,
'callback' => array( 'foo', 'bar' ),
);
$legacy_controller = new WP_oEmbed_Controller();
$data = $legacy_controller->dispatch( $request );
$this->assertFalse( strpos( $data, '/**/' ) );
}
function test_request_json_invalid_data() {
$request = array(
'callback' => '',
);
$legacy_controller = new WP_oEmbed_Controller();
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->json_response( null, $request ) );
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->json_response( 123, $request ) );
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->json_response( array(), $request ) );
}
function test_request_xml() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'xml',
'maxwidth' => 400,
'callback' => '',
);
$legacy_controller = new WP_oEmbed_Controller();
$data = $legacy_controller->dispatch( $request );
$data = simplexml_load_string( $data );
$this->assertInstanceOf( 'SimpleXMLElement', $data );
$data = (array) $data;
$this->assertArrayHasKey( 'version', $data );
$this->assertArrayHasKey( 'provider_name', $data );
$this->assertArrayHasKey( 'provider_url', $data );
$this->assertArrayHasKey( 'author_name', $data );
$this->assertArrayHasKey( 'author_url', $data );
$this->assertArrayHasKey( 'title', $data );
$this->assertArrayHasKey( 'type', $data );
$this->assertArrayHasKey( 'width', $data );
$this->assertEquals( '1.0', $data['version'] );
$this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] );
$this->assertEquals( get_home_url(), $data['provider_url'] );
$this->assertEquals( $user->display_name, $data['author_name'] );
$this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
$this->assertEquals( $post->post_title, $data['title'] );
$this->assertEquals( 'rich', $data['type'] );
$this->assertTrue( $data['width'] <= $request['maxwidth'] );
}
function test_request_xml_invalid_data() {
$legacy_controller = new WP_oEmbed_Controller();
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->xml_response( null ) );
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->xml_response( 123 ) );
$this->assertEquals( get_status_header_desc( 501 ), $legacy_controller->xml_response( array() ) );
}
/**
* @group multisite
* @var WP_REST_Server
*/
function test_request_ms_child_in_root_blog() {
if ( ! is_multisite() ) {
$this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' );
}
protected $server;
$child = self::factory()->blog->create();
public function setUp() {
parent::setUp();
switch_to_blog( $child );
/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$this->server = $wp_rest_server = new Spy_REST_Server();
$post = self::factory()->post->create_and_get( array(
'post_title' => 'Hello Child Blog',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'json',
'maxwidth' => 600,
'callback' => '',
);
$legacy_controller = new WP_oEmbed_Controller();
$data = json_decode( $legacy_controller->dispatch( $request ), true );
$this->assertInternalType( 'array', $data );
$this->assertNotEmpty( $data );
restore_current_blog();
}
function test_get_oembed_endpoint_url() {
$this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url() );
$this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'json' ) );
$this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'xml' ) );
$post_id = self::factory()->post->create();
$url = get_permalink( $post_id );
$url_encoded = urlencode( $url );
$this->assertEquals( home_url() . '/?oembed=true&url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
$this->assertEquals( home_url() . '/?oembed=true&url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
do_action( 'rest_api_init', $this->server );
}
function test_wp_oembed_ensure_format() {
@ -271,4 +76,236 @@ class Test_oEmbed_Controller extends WP_UnitTestCase {
$this->assertStringEndsWith( $expected, trim( $actual ) );
}
public function test_route_availability() {
// Check the route was registered correctly.
$filtered_routes = $this->server->get_routes();
$this->assertArrayHasKey( '/oembed/1.0/embed', $filtered_routes );
$route = $filtered_routes['/oembed/1.0/embed'];
$this->assertCount( 1, $route );
$this->assertArrayHasKey( 'callback', $route[0] );
$this->assertArrayHasKey( 'methods', $route[0] );
$this->assertArrayHasKey( 'args', $route[0] );
}
function test_request_with_wrong_method() {
$request = new WP_REST_Request( 'POST', '/oembed/1.0/embed' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'rest_no_route', $data[0]['code'] );
}
function test_request_without_url_param() {
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'rest_missing_callback_param', $data[0]['code'] );
$this->assertEquals( 'url', $data[0]['data']['params'][0] );
}
function test_request_with_bad_url() {
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', 'http://google.com/' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'oembed_invalid_url', $data[0]['code'] );
}
function test_request_invalid_format() {
$post_id = $this->factory()->post->create();
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post_id ) );
$request->set_param( 'format', 'random' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertInternalType( 'array', $data );
$this->assertNotEmpty( $data );
}
function test_request_json() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'maxwidth', 400 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertInternalType( 'array', $data );
$this->assertNotEmpty( $data );
$this->assertArrayHasKey( 'version', $data );
$this->assertArrayHasKey( 'provider_name', $data );
$this->assertArrayHasKey( 'provider_url', $data );
$this->assertArrayHasKey( 'author_name', $data );
$this->assertArrayHasKey( 'author_url', $data );
$this->assertArrayHasKey( 'title', $data );
$this->assertArrayHasKey( 'type', $data );
$this->assertArrayHasKey( 'width', $data );
$this->assertEquals( '1.0', $data['version'] );
$this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] );
$this->assertEquals( get_home_url(), $data['provider_url'] );
$this->assertEquals( $user->display_name, $data['author_name'] );
$this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
$this->assertEquals( $post->post_title, $data['title'] );
$this->assertEquals( 'rich', $data['type'] );
$this->assertTrue( $data['width'] <= $request['maxwidth'] );
}
function test_request_xml() {
$user = self::factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = self::factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'format', 'xml' );
$request->set_param( 'maxwidth', 400 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertInternalType( 'array', $data );
$this->assertNotEmpty( $data );
$this->assertArrayHasKey( 'version', $data );
$this->assertArrayHasKey( 'provider_name', $data );
$this->assertArrayHasKey( 'provider_url', $data );
$this->assertArrayHasKey( 'author_name', $data );
$this->assertArrayHasKey( 'author_url', $data );
$this->assertArrayHasKey( 'title', $data );
$this->assertArrayHasKey( 'type', $data );
$this->assertArrayHasKey( 'width', $data );
$this->assertEquals( '1.0', $data['version'] );
$this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] );
$this->assertEquals( get_home_url(), $data['provider_url'] );
$this->assertEquals( $user->display_name, $data['author_name'] );
$this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
$this->assertEquals( $post->post_title, $data['title'] );
$this->assertEquals( 'rich', $data['type'] );
$this->assertTrue( $data['width'] <= $request['maxwidth'] );
}
/**
* @group multisite
*/
function test_request_ms_child_in_root_blog() {
if ( ! is_multisite() ) {
$this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' );
}
$child = self::factory()->blog->create();
switch_to_blog( $child );
$post = self::factory()->post->create_and_get( array(
'post_title' => 'Hello Child Blog',
) );
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'maxwidth', 400 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertInternalType( 'array', $data );
$this->assertNotEmpty( $data );
restore_current_blog();
}
function test_rest_pre_serve_request() {
$user = $this->factory()->user->create_and_get( array(
'display_name' => 'John Doe',
) );
$post = $this->factory()->post->create_and_get( array(
'post_author' => $user->ID,
'post_title' => 'Hello World',
) );
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'format', 'xml' );
$response = $this->server->dispatch( $request );
$output = get_echo( '_oembed_rest_pre_serve_request', array( true, $response, $request, $this->server ) );
$xml = simplexml_load_string( $output );
$this->assertInstanceOf( 'SimpleXMLElement', $xml );
}
function test_rest_pre_serve_request_wrong_format() {
$post = $this->factory()->post->create_and_get();
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'format', 'json' );
$response = $this->server->dispatch( $request );
$this->assertTrue( _oembed_rest_pre_serve_request( true, $response, $request, $this->server ) );
}
function test_rest_pre_serve_request_wrong_method() {
$post = $this->factory()->post->create_and_get();
$request = new WP_REST_Request( 'HEAD', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'format', 'xml' );
$response = $this->server->dispatch( $request );
$this->assertTrue( _oembed_rest_pre_serve_request( true, $response, $request, $this->server ) );
}
function test_get_oembed_endpoint_url() {
$this->assertEquals( home_url() . '/?rest_route=/oembed/1.0/embed', get_oembed_endpoint_url() );
$this->assertEquals( home_url() . '/?rest_route=/oembed/1.0/embed', get_oembed_endpoint_url( '', 'json' ) );
$this->assertEquals( home_url() . '/?rest_route=/oembed/1.0/embed', get_oembed_endpoint_url( '', 'xml' ) );
$post_id = $this->factory()->post->create();
$url = get_permalink( $post_id );
$url_encoded = urlencode( $url );
$this->assertEquals( home_url() . '/?rest_route=%2Foembed%2F1.0%2Fembed&url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
$this->assertEquals( home_url() . '/?rest_route=%2Foembed%2F1.0%2Fembed&url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
}
function test_get_oembed_endpoint_url_pretty_permalinks() {
update_option( 'permalink_structure', '/%postname%' );
$this->assertEquals( home_url() . '/wp-json/oembed/1.0/embed', get_oembed_endpoint_url() );
$this->assertEquals( home_url() . '/wp-json/oembed/1.0/embed', get_oembed_endpoint_url( '', 'xml' ) );
$post_id = $this->factory()->post->create();
$url = get_permalink( $post_id );
$url_encoded = urlencode( $url );
$this->assertEquals( home_url() . '/wp-json/oembed/1.0/embed?url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
$this->assertEquals( home_url() . '/wp-json/oembed/1.0/embed?url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
update_option( 'permalink_structure', '' );
}
}

View File

@ -5,26 +5,18 @@
*/
class Tests_oEmbed_Discovery extends WP_UnitTestCase {
function test_add_oembed_discovery_links_non_singular() {
ob_start();
wp_oembed_add_discovery_links();
$actual = ob_get_clean();
$this->assertSame( '', $actual );
$this->assertSame( '', get_echo( 'wp_oembed_add_discovery_links' ) );
}
function test_add_oembed_discovery_links_to_post() {
$post_id = self::factory()->post->create();
$this->go_to( get_permalink( $post_id ) );
$this->assertQueryTrue( 'is_single', 'is_singular' );
ob_start();
wp_oembed_add_discovery_links();
$actual = ob_get_clean();
$expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n";
$expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n";
$this->assertEquals( $expected, $actual );
$this->assertEquals( $expected, get_echo( 'wp_oembed_add_discovery_links' ) );
}
function test_add_oembed_discovery_links_to_page() {
@ -32,17 +24,12 @@ class Tests_oEmbed_Discovery extends WP_UnitTestCase {
'post_type' => 'page'
));
$this->go_to( get_permalink( $post_id ) );
$this->assertQueryTrue( 'is_page', 'is_singular' );
ob_start();
wp_oembed_add_discovery_links();
$actual = ob_get_clean();
$expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n";
$expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n";
$this->assertEquals( $expected, $actual );
$this->assertEquals( $expected, get_echo( 'wp_oembed_add_discovery_links' ) );
}
function test_add_oembed_discovery_links_to_attachment() {
@ -53,16 +40,11 @@ class Tests_oEmbed_Discovery extends WP_UnitTestCase {
) );
$this->go_to( get_permalink( $attachment_id ) );
$this->assertQueryTrue( 'is_attachment', 'is_singular', 'is_single' );
ob_start();
wp_oembed_add_discovery_links();
$actual = ob_get_clean();
$expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n";
$expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n";
$this->assertEquals( $expected, $actual );
$this->assertEquals( $expected, get_echo( 'wp_oembed_add_discovery_links' ) );
}
}

View File

@ -7,57 +7,24 @@
* @group oembed-headers
*/
class Tests_oEmbed_HTTP_Headers extends WP_UnitTestCase {
function test_request_json_response_headers() {
function test_rest_pre_serve_request_headers() {
if ( ! function_exists( 'xdebug_get_headers' ) ) {
$this->markTestSkipped( 'xdebug is required for this test' );
}
$post = self::factory()->post->create_and_get( array(
$post = $this->factory()->post->create_and_get( array(
'post_title' => 'Hello World',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'json',
'maxwidth' => 600,
'callback' => '',
);
$request = new WP_REST_Request( 'GET', '/oembed/1.0/embed' );
$request->set_param( 'url', get_permalink( $post->ID ) );
$request->set_param( 'format', 'xml' );
$legacy_controller = new WP_oEmbed_Controller();
$legacy_controller->dispatch( $request );
$server = new WP_REST_Server();
$response = $server->dispatch( $request );
$output = get_echo( '_oembed_rest_pre_serve_request', array( true, $response, $request, $server ) );
$headers = xdebug_get_headers();
$this->assertTrue( in_array( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ), $headers ) );
$this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) );
$request['callback'] = 'foobar';
$legacy_controller->dispatch( $request );
$headers = xdebug_get_headers();
$this->assertTrue( in_array( 'Content-Type: application/javascript; charset=' . get_option( 'blog_charset' ), $headers ) );
$this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) );
}
function test_request_xml_response_headers() {
if ( ! function_exists( 'xdebug_get_headers' ) ) {
$this->markTestSkipped( 'xdebug is required for this test' );
}
$post = self::factory()->post->create_and_get( array(
'post_title' => 'Hello World',
) );
$request = array(
'url' => get_permalink( $post->ID ),
'format' => 'xml',
'maxwidth' => 600,
);
$legacy_controller = new WP_oEmbed_Controller();
$legacy_controller->dispatch( $request );
$this->assertNotEmpty( $output );
$headers = xdebug_get_headers();

View File

@ -249,9 +249,7 @@ class Tests_Embed_Template extends WP_UnitTestCase {
}
function test_add_host_js() {
ob_start();
wp_oembed_add_host_js();
ob_end_clean();
$this->assertTrue( wp_script_is( 'wp-embed' ) );
}