diff --git a/src/wp-includes/class-wp-oembed-controller.php b/src/wp-includes/class-wp-oembed-controller.php
index a613d0616d..0db5340e01 100644
--- a/src/wp-includes/class-wp-oembed-controller.php
+++ b/src/wp-includes/class-wp-oembed-controller.php
@@ -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;
}
}
diff --git a/src/wp-includes/class-wp.php b/src/wp-includes/class-wp.php
index 0f86251676..555167b1ea 100644
--- a/src/wp-includes/class-wp.php
+++ b/src/wp-includes/class-wp.php
@@ -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.
diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php
index 0bda80e1f4..70a9791ebc 100644
--- a/src/wp-includes/default-filters.php
+++ b/src/wp-includes/default-filters.php
@@ -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 );
diff --git a/src/wp-includes/embed-functions.php b/src/wp-includes/embed-functions.php
index 0b67ed5869..585b78e855 100644
--- a/src/wp-includes/embed-functions.php
+++ b/src/wp-includes/embed-functions.php
@@ -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.
*
diff --git a/tests/phpunit/tests/oembed/controller.php b/tests/phpunit/tests/oembed/controller.php
index 51c6302c32..9410e00fa0 100644
--- a/tests/phpunit/tests/oembed/controller.php
+++ b/tests/phpunit/tests/oembed/controller.php
@@ -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', '' );
+ }
}
diff --git a/tests/phpunit/tests/oembed/discovery.php b/tests/phpunit/tests/oembed/discovery.php
index e7615f9056..63eb5bbf3a 100644
--- a/tests/phpunit/tests/oembed/discovery.php
+++ b/tests/phpunit/tests/oembed/discovery.php
@@ -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 = '' . "\n";
$expected .= '' . "\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 = '' . "\n";
$expected .= '' . "\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 = '' . "\n";
$expected .= '' . "\n";
- $this->assertEquals( $expected, $actual );
+ $this->assertEquals( $expected, get_echo( 'wp_oembed_add_discovery_links' ) );
}
}
diff --git a/tests/phpunit/tests/oembed/headers.php b/tests/phpunit/tests/oembed/headers.php
index 3c9f80fcc6..b0bc2c89f1 100644
--- a/tests/phpunit/tests/oembed/headers.php
+++ b/tests/phpunit/tests/oembed/headers.php
@@ -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();
diff --git a/tests/phpunit/tests/oembed/template.php b/tests/phpunit/tests/oembed/template.php
index 04a07ba984..644a6d52b6 100644
--- a/tests/phpunit/tests/oembed/template.php
+++ b/tests/phpunit/tests/oembed/template.php
@@ -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' ) );
}