Make WordPress Core

Ticket #34207: 34207.diff

File 34207.diff, 30.8 KB (added by swissspidy, 8 years ago)
  • src/wp-includes/class-wp-oembed-controller.php

    diff --git src/wp-includes/class-wp-oembed-controller.php src/wp-includes/class-wp-oembed-controller.php
    index 2da7f3e..b971183 100644
     
    1010/**
    1111 * oEmbed API endpoint controller.
    1212 *
    13  * Parses the oEmbed API requests and delivers
    14  * XML and JSON responses.
     13 * Registers the API route and delivers the response data.
     14 * The output format (XML or JSON) is handled by the REST API.
    1515 *
    1616 * @since 4.4.0
    1717 */
    1818final class WP_oEmbed_Controller {
    1919        /**
    20          * Hook into the query parsing to detect oEmbed requests.
    21          *
    22          * If an oEmbed request is made, trigger the output.
     20         * Register the oEmbed REST API route.
    2321         *
    2422         * @since 4.4.0
    25          *
    26          * @param WP_Query $wp_query The WP_Query instance (passed by reference).
    2723         */
    28         public function parse_query( $wp_query ) {
    29                 if ( false === $wp_query->get( 'oembed', false ) ) {
    30                         return;
    31                 }
    32 
    33                 if ( false === $wp_query->get( 'url', false ) ) {
    34                         status_header( 400 );
    35                         echo 'URL parameter missing';
    36                         exit;
    37                 }
    38 
    39                 $url = esc_url_raw( get_query_var( 'url' ) );
    40 
    41                 $format = wp_oembed_ensure_format( get_query_var( 'format' ) );
    42 
    43                 /**
    44                  * Filter the maxwidth oEmbed parameter.
    45                  *
    46                  * @since 4.4.0
    47                  *
    48                  * @param int $maxwidth Maximum allowed width. Default 600.
    49                  */
    50                 $maxwidth = apply_filters( 'oembed_default_width', 600 );
    51                 $maxwidth = absint( get_query_var( 'maxwidth', $maxwidth ) );
    52 
    53                 $callback = get_query_var( '_jsonp', false );
    54 
    55                 $request = array(
    56                         'url'      => $url,
    57                         'format'   => $format,
    58                         'maxwidth' => $maxwidth,
    59                         'callback' => $callback,
    60                 );
    61 
    62                 echo $this->dispatch( $request );
    63                 exit;
     24        public function register_routes() {
     25                register_rest_route( 'wp/v2', '/oembed', array(
     26                        array(
     27                                'methods'  => WP_REST_Server::READABLE,
     28                                'callback' => array( $this, 'get_item' ),
     29                                'args'     => array(
     30                                        'url'      => array(
     31                                                'required'          => true,
     32                                                'sanitize_callback' => 'esc_url_raw',
     33                                        ),
     34                                        'format'   => array(
     35                                                'default'           => 'json',
     36                                                'sanitize_callback' => 'wp_oembed_ensure_format',
     37                                        ),
     38                                        'maxwidth' => array(
     39                                                'default'           => apply_filters( 'oembed_default_width', 600 ),
     40                                                'sanitize_callback' => 'absint',
     41                                        ),
     42                                ),
     43                        ),
     44                        'schema' => array( $this, 'get_public_item_schema' ),
     45                ) );
    6446        }
    6547
    6648        /**
    67          * Handle the whole request and print the response.
     49         * Callback for the API endpoint.
    6850         *
    69          * @since 4.4.0
     51         * Returns the JSON object for the post.
    7052         *
    71          * @param array $request The request arguments.
    72          * @return string The oEmbed API response.
     53         * @param WP_REST_Request $request Full data about the request.
     54         * @return WP_Error|WP_REST_Response
    7355         */
    74         public function dispatch( $request ) {
     56        public function get_item( $request ) {
    7557                $post_id = url_to_postid( $request['url'] );
    7658
    7759                /**
    final class WP_oEmbed_Controller { 
    8466                 */
    8567                $post_id = apply_filters( 'oembed_request_post_id', $post_id, $request['url'] );
    8668
    87                 $data = get_oembed_response_data( $post_id, $request['maxwidth'] );
    88 
    89                 if ( false === $data ) {
    90                         status_header( 404 );
    91                         return __( 'Invalid URL.' );
    92                 }
    93 
    94                 if ( 'json' === $request['format'] ) {
    95                         return $this->json_response( $data, $request );
     69                if ( 0 === $post_id ) {
     70                        return new WP_Error( 'oembed_invalid_url', __( 'Invalid URL.', 'oembed-api' ), array( 'status' => 404 ) );
    9671                }
    9772
    98                 return $this->xml_response( $data );
     73                return get_oembed_response_data( $post_id, $request['maxwidth'] );
    9974        }
    10075
    10176        /**
    102          * Print the oEmbed JSON response.
     77         * Get the item's schema for display / public consumption purposes, conforming to JSON Schema.
    10378         *
    10479         * @since 4.4.0
    10580         *
    106          * @param array $data     The oEmbed response data.
    107          * @param array $request  The request arguments.
    108          * @return string The JSON response data.
     81         * @return array The item's schema.
    10982         */
    110         public function json_response( $data, $request ) {
    111                 if ( ! is_string( $request['callback'] ) || preg_match( '/[^\w\.]/', $request['callback'] ) ) {
    112                         $request['callback'] = false;
    113                 }
    114 
    115                 $result = wp_json_encode( $data );
    116 
    117                 // Bail if the result couldn't be JSON encoded.
    118                 if ( ! $result || ! is_array( $data ) || empty( $data ) ) {
    119                         status_header( 501 );
    120                         return 'Not implemented';
    121                 }
    122 
    123                 if ( ! headers_sent() ) {
    124                         $content_type = $request['callback'] ? 'application/javascript' : 'application/json';
    125                         header( 'Content-Type: ' . $content_type . '; charset=' . get_option( 'blog_charset' ) );
    126                         header( 'X-Content-Type-Options: nosniff' );
    127                 }
    128 
    129                 if ( $request['callback'] ) {
    130                         return '/**/' . $request['callback'] . '(' . $result . ')';
    131                 }
    132 
    133                 return $result;
    134         }
    135 
    136         /**
    137          * Print the oEmbed XML response.
    138          *
    139          * @since 4.4.0
    140          *
    141          * @param array $data The oEmbed response data.
    142          * @return string The XML response data.
    143          */
    144         public function xml_response( $data ) {
    145                 $result = _oembed_create_xml( $data );
    146 
    147                 // Bail if there's no XML.
    148                 if ( ! $result ) {
    149                         status_header( 501 );
    150                         return 'Not implemented';
    151                 }
    152 
    153                 if ( ! headers_sent() ) {
    154                         header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) );
    155                 }
     83        public function get_public_item_schema() {
     84                $schema = array(
     85                        '$schema'    => 'http://json-schema.org/draft-04/schema#',
     86                        'title'      => 'oembed',
     87                        'type'       => 'object',
     88                        'properties' => array(
     89                                'type'          => array(
     90                                        'description' => 'The resource type. Either photo, video, link, or rich.',
     91                                        'type'        => 'string',
     92                                ),
     93                                'version'       => array(
     94                                        'description' => 'The oEmbed version number.',
     95                                        'type'        => 'number',
     96                                ),
     97                                'width'         => array(
     98                                        'description' => 'Width of the embeddable post',
     99                                        'type'        => 'integer',
     100                                ),
     101                                'height'        => array(
     102                                        'description' => 'Height of the embeddable post',
     103                                        'type'        => 'integer',
     104                                ),
     105                                'title'         => array(
     106                                        'description' => 'The title for the object.',
     107                                        'type'        => 'string',
     108                                ),
     109                                'url'           => array(
     110                                        'description' => 'URL to the object.',
     111                                        'type'        => 'string',
     112                                        'format'      => 'uri',
     113                                ),
     114                                'html'          => array(
     115                                        'description' => 'HTML to embed the object.',
     116                                        'type'        => 'string',
     117                                ),
     118                                'author_name'   => array(
     119                                        'description' => 'The name of the object\'s author.',
     120                                        'type'        => 'string',
     121                                ),
     122                                'author_url'    => array(
     123                                        'description' => 'URL to the object\'s author.',
     124                                        'type'        => 'string',
     125                                        'format'      => 'uri',
     126                                ),
     127                                'provider_name' => array(
     128                                        'description' => 'The name of the object\'s provider.',
     129                                        'type'        => 'string',
     130                                ),
     131                                'provider_url'  => array(
     132                                        'description' => 'URL to the object\'s provider.',
     133                                        'type'        => 'string',
     134                                        'format'      => 'uri',
     135                                ),
     136                        ),
     137                );
    156138
    157                 return $result;
     139                return $schema;
    158140        }
    159141}
  • src/wp-includes/class-wp.php

    diff --git src/wp-includes/class-wp.php src/wp-includes/class-wp.php
    index bba47ff..608a1c7 100644
    class WP { 
    1515         * @access public
    1616         * @var array
    1717         */
    18         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' );
     18        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' );
    1919
    2020        /**
    2121         * Private query variables.
  • src/wp-includes/default-filters.php

    diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php
    index cfdd709..b6d622b 100644
    add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 ); 
    440440
    441441// Embeds
    442442
    443 add_action( 'parse_query', 'wp_oembed_parse_query' );
     443add_action( 'rest_api_init', 'wp_oembed_register_route' );
     444add_filter( 'rest_pre_serve_request', '_oembed_rest_pre_serve_request', 10, 4 );
    444445
    445446add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
    446447add_action( 'wp_head', 'wp_oembed_add_host_js' );
  • src/wp-includes/embed-functions.php

    diff --git src/wp-includes/embed-functions.php src/wp-includes/embed-functions.php
    index 48c0a29..4df553f 100644
    function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) { 
    328328}
    329329
    330330/**
    331  * Parse an oEmbed API query.
     331 * Registers the oEmbed REST API route.
    332332 *
    333333 * @since 4.4.0
    334334 */
    335 function wp_oembed_parse_query( $wp_query ) {
     335function wp_oembed_register_route() {
    336336        $controller = new WP_oEmbed_Controller;
    337         $controller->parse_query( $wp_query );
     337        $controller->register_routes();
    338338}
    339339
    340340/**
    function get_post_embed_url( $post = null ) { 
    415415 * @return string The oEmbed endpoint URL.
    416416 */
    417417function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) {
    418         $url = add_query_arg( array( 'oembed' => 'true' ), home_url( '/' ) );
     418        $url = rest_url( 'wp/v2/oembed' );
    419419
    420420        if ( 'json' === $format ) {
    421421                $format = false;
    function get_oembed_response_data( $post = null, $width ) { 
    523523        /**
    524524         * Filter the allowed minimum width for the oEmbed response.
    525525         *
     526         * @since 4.4.0
     527         *
    526528         * @param int $width The minimum width. Defaults to 200.
    527529         */
    528530        $minwidth = apply_filters( 'oembed_minwidth', 200 );
    function wp_oembed_ensure_format( $format ) { 
    636638}
    637639
    638640/**
     641 * Hooks into the REST API output to print XML instead of JSON.
     642 *
     643 * This is only done for the oEmbed API endpoint,
     644 * which supports both formats.
     645 *
     646 * @access private
     647 * @since 4.4.0
     648 *
     649 * @param bool                      $served  Whether the request has already been served.
     650 * @param WP_HTTP_ResponseInterface $result  Result to send to the client. Usually a WP_REST_Response.
     651 * @param WP_REST_Request           $request Request used to generate the response.
     652 * @param WP_REST_Server            $server  Server instance.
     653 * @return true
     654 */
     655function _oembed_rest_pre_serve_request( $served, $result, $request, $server ) {
     656        $params = $request->get_params();
     657
     658        if ( '/wp/v2/oembed' !== $request->get_route() || 'GET' !== $request->get_method() ) {
     659                return $served;
     660        }
     661
     662        if ( ! isset( $params['format'] ) || 'xml' !== $params['format'] ) {
     663                return $served;
     664        }
     665
     666        // Embed links inside the request.
     667        $data = $server->response_to_data( $result, false );
     668
     669        if ( 404 === $result->get_status() ) {
     670                $data = $data[0];
     671        }
     672
     673        $result = _oembed_create_xml( $data );
     674
     675        // Bail if there's no XML.
     676        if ( ! $result ) {
     677                status_header( 501 );
     678                die( 'Not implemented' );
     679        }
     680
     681        if ( ! headers_sent() ) {
     682                $server->send_header( 'Content-Type', 'text/xml; charset=' . get_option( 'blog_charset' ) );
     683        }
     684
     685        echo $result;
     686
     687        return true;
     688}
     689
     690/**
    639691 * Creates an XML string from a given array.
    640692 *
    641693 * @since 4.4.0
  • tests/phpunit/tests/oembed/controller.php

    diff --git tests/phpunit/tests/oembed/controller.php tests/phpunit/tests/oembed/controller.php
    index 4c0771b..eada230 100644
     
    22
    33/**
    44 * @group oembed
     5 * @group restapi
    56 */
    67class Test_oEmbed_Controller extends WP_UnitTestCase {
     8        /**
     9         * @var WP_REST_Server
     10         */
     11        protected $server;
     12
     13        public function setUp() {
     14                parent::setUp();
     15
     16                /** @var WP_REST_Server $wp_rest_server */
     17                global $wp_rest_server;
     18                $this->server = $wp_rest_server = new Spy_REST_Server();
     19
     20                do_action( 'rest_api_init', $this->server );
     21        }
     22
     23        function test_wp_oembed_ensure_format() {
     24                $this->assertEquals( 'json', wp_oembed_ensure_format( 'json' ) );
     25                $this->assertEquals( 'xml', wp_oembed_ensure_format( 'xml' ) );
     26                $this->assertEquals( 'json', wp_oembed_ensure_format( 123 ) );
     27                $this->assertEquals( 'json', wp_oembed_ensure_format( 'random' ) );
     28                $this->assertEquals( 'json', wp_oembed_ensure_format( array() ) );
     29        }
     30
     31        function test_oembed_create_xml() {
     32                $actual = _oembed_create_xml( array(
     33                        'foo'  => 'bar',
     34                        'bar'  => 'baz',
     35                        'ping' => 'pong',
     36                ) );
     37
     38                $expected = '<oembed><foo>bar</foo><bar>baz</bar><ping>pong</ping></oembed>';
     39
     40                $this->assertStringEndsWith( $expected, trim( $actual ) );
     41
     42                $actual = _oembed_create_xml( array(
     43                        'foo'  => array(
     44                                'bar' => 'baz',
     45                        ),
     46                        'ping' => 'pong',
     47                ) );
     48
     49                $expected = '<oembed><foo><bar>baz</bar></foo><ping>pong</ping></oembed>';
     50
     51                $this->assertStringEndsWith( $expected, trim( $actual ) );
     52
     53                $actual = _oembed_create_xml( array(
     54                        'foo'   => array(
     55                                'bar' => array(
     56                                        'ping' => 'pong',
     57                                ),
     58                        ),
     59                        'hello' => 'world',
     60                ) );
     61
     62                $expected = '<oembed><foo><bar><ping>pong</ping></bar></foo><hello>world</hello></oembed>';
     63
     64                $this->assertStringEndsWith( $expected, trim( $actual ) );
     65
     66                $actual = _oembed_create_xml( array(
     67                        array(
     68                                'foo' => array(
     69                                        'bar',
     70                                ),
     71                        ),
     72                        'helloworld',
     73                ) );
     74
     75                $expected = '<oembed><oembed><foo><oembed>bar</oembed></foo></oembed><oembed>helloworld</oembed></oembed>';
     76
     77                $this->assertStringEndsWith( $expected, trim( $actual ) );
     78        }
     79
     80        public function test_route_availability() {
     81                // Check the route was registered correctly.
     82                $filtered_routes = $this->server->get_routes();
     83                $this->assertArrayHasKey( '/wp/v2/oembed', $filtered_routes );
     84                $route = $filtered_routes['/wp/v2/oembed'];
     85                $this->assertCount( 1, $route );
     86                $this->assertArrayHasKey( 'callback', $route[0] );
     87                $this->assertArrayHasKey( 'methods', $route[0] );
     88                $this->assertArrayHasKey( 'args', $route[0] );
     89        }
     90
     91        function test_request_with_wrong_method() {
     92                $request = new WP_REST_Request( 'POST', '/wp/v2/oembed' );
     93
     94                $response = $this->server->dispatch( $request );
     95                $data     = $response->get_data();
     96
     97                $this->assertEquals( 'rest_no_route', $data[0]['code'] );
     98        }
     99
     100        function test_request_without_url_param() {
     101                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     102
     103                $response = $this->server->dispatch( $request );
     104                $data     = $response->get_data();
     105
     106                $this->assertEquals( 'rest_missing_callback_param', $data[0]['code'] );
     107                $this->assertEquals( 'url', $data[0]['data']['params'][0] );
     108        }
     109
    7110        function test_request_with_bad_url() {
    8                 $request = array(
    9                         'url'      => '',
    10                         'format'   => 'json',
    11                         'maxwidth' => 600,
    12                 );
     111                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     112                $request->set_param( 'url', 'http://google.com/' );
    13113
    14                 $legacy_controller = new WP_oEmbed_Controller();
     114                $response = $this->server->dispatch( $request );
     115                $data     = $response->get_data();
    15116
    16                 $this->assertEquals( 'Invalid URL.', $legacy_controller->dispatch( $request ) );
     117                $this->assertEquals( 'oembed_invalid_url', $data[0]['code'] );
     118        }
     119
     120        function test_request_invalid_format() {
     121                $post_id = $this->factory->post->create();
     122
     123                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     124                $request->set_param( 'url', get_permalink( $post_id ) );
     125                $request->set_param( 'format', 'random' );
     126
     127                $response = $this->server->dispatch( $request );
     128                $data     = $response->get_data();
     129
     130                $this->assertTrue( is_array( $data ) );
    17131        }
    18132
    19133        function test_request_json() {
    class Test_oEmbed_Controller extends WP_UnitTestCase { 
    25139                        'post_title'  => 'Hello World',
    26140                ) );
    27141
    28                 // WP_Query arguments.
    29                 $request = array(
    30                         'url'     => get_permalink( $post->ID ),
    31                         'format'   => 'json',
    32                         'maxwidth' => 400,
    33                         'callback' => '',
    34                         'oembed'   => true,
    35                 );
     142                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     143                $request->set_param( 'url', get_permalink( $post->ID ) );
     144                $request->set_param( 'maxwidth', 400 );
    36145
    37                 $legacy_controller = new WP_oEmbed_Controller();
    38 
    39                 $data = json_decode( $legacy_controller->dispatch( $request ), true );
     146                $response = $this->server->dispatch( $request );
     147                $data     = $response->get_data();
    40148
    41149                $this->assertTrue( is_array( $data ) );
    42150
    class Test_oEmbed_Controller extends WP_UnitTestCase { 
    56164                $this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
    57165                $this->assertEquals( $post->post_title, $data['title'] );
    58166                $this->assertEquals( 'rich', $data['type'] );
    59                 $this->assertTrue( $data['width'] <= $request['maxwidth'] );
    60         }
    61 
    62         function test_request_jsonp() {
    63                 $user = $this->factory->user->create_and_get( array(
    64                         'display_name' => 'John Doe',
    65                 ) );
    66                 $post = $this->factory->post->create_and_get( array(
    67                         'post_author' => $user->ID,
    68                         'post_title'  => 'Hello World',
    69                 ) );
    70 
    71                 $request = array(
    72                         'url'     => get_permalink( $post->ID ),
    73                         'format'   => 'json',
    74                         'maxwidth' => 600,
    75                         'callback' => 'mycallback',
    76                 );
    77 
    78                 $legacy_controller = new WP_oEmbed_Controller();
    79 
    80                 $data = $legacy_controller->dispatch( $request );
    81 
    82                 $this->assertEquals( 0, strpos( $data, '/**/mycallback(' ) );
    83         }
    84 
    85         function test_request_jsonp_invalid_callback() {
    86                 $user = $this->factory->user->create_and_get( array(
    87                         'display_name' => 'John Doe',
    88                 ) );
    89                 $post = $this->factory->post->create_and_get( array(
    90                         'post_author' => $user->ID,
    91                         'post_title'  => 'Hello World',
    92                 ) );
    93 
    94                 $request = array(
    95                         'url'     => get_permalink( $post->ID ),
    96                         'format'   => 'json',
    97                         'maxwidth' => 600,
    98                         'callback' => array( 'foo', 'bar' ),
    99                 );
    100 
    101                 $legacy_controller = new WP_oEmbed_Controller();
    102 
    103                 $data = $legacy_controller->dispatch( $request );
    104 
    105                 $this->assertFalse( strpos( $data, '/**/' ) );
    106         }
    107 
    108         function test_request_json_invalid_data() {
    109                 $request = array(
    110                         'callback' => '',
    111                 );
    112 
    113                 $legacy_controller = new WP_oEmbed_Controller();
    114 
    115                 $this->assertEquals( 'Not implemented',  $legacy_controller->json_response( null, $request ) );
    116                 $this->assertEquals( 'Not implemented',  $legacy_controller->json_response( 123, $request ) );
    117                 $this->assertEquals( 'Not implemented',  $legacy_controller->json_response( array(), $request ) );
     167                $this->assertTrue( $data['width'] <= $request->get_param( 'maxwidth' ) );
    118168        }
    119169
    120170        function test_request_xml() {
    class Test_oEmbed_Controller extends WP_UnitTestCase { 
    126176                        'post_title'  => 'Hello World',
    127177                ) );
    128178
    129                 $request = array(
    130                         'url'     => get_permalink( $post->ID ),
    131                         'format'   => 'xml',
    132                         'maxwidth' => 400,
    133                         'callback' => '',
    134                 );
    135 
    136                 $legacy_controller = new WP_oEmbed_Controller();
    137 
    138                 $data = $legacy_controller->dispatch( $request );
     179                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     180                $request->set_param( 'url', get_permalink( $post->ID ) );
     181                $request->set_param( 'format', 'xml' );
     182                $request->set_param( 'maxwidth', 400 );
    139183
    140                 $data = simplexml_load_string( $data );
    141                 $this->assertInstanceOf( 'SimpleXMLElement', $data );
     184                $response = $this->server->dispatch( $request );
     185                $data     = $response->get_data();
    142186
    143                 $data = (array) $data;
     187                $this->assertTrue( is_array( $data ) );
    144188
    145189                $this->assertArrayHasKey( 'version', $data );
    146190                $this->assertArrayHasKey( 'provider_name', $data );
    class Test_oEmbed_Controller extends WP_UnitTestCase { 
    158202                $this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] );
    159203                $this->assertEquals( $post->post_title, $data['title'] );
    160204                $this->assertEquals( 'rich', $data['type'] );
    161                 $this->assertTrue( $data['width'] <= $request['maxwidth'] );
     205                $this->assertTrue( $data['width'] <= $request->get_param( 'maxwidth' ) );
    162206        }
    163207
    164         function test_request_xml_invalid_data() {
    165                 $legacy_controller = new WP_oEmbed_Controller();
     208        function test_rest_pre_serve_request() {
     209                $user = $this->factory->user->create_and_get( array(
     210                        'display_name' => 'John Doe',
     211                ) );
     212                $post = $this->factory->post->create_and_get( array(
     213                        'post_author' => $user->ID,
     214                        'post_title'  => 'Hello World',
     215                ) );
    166216
    167                 $this->assertEquals( 'Not implemented',  $legacy_controller->xml_response( null ) );
    168                 $this->assertEquals( 'Not implemented',  $legacy_controller->xml_response( 123 ) );
    169                 $this->assertEquals( 'Not implemented',  $legacy_controller->xml_response( array() ) );
    170         }
     217                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     218                $request->set_param( 'url', get_permalink( $post->ID ) );
     219                $request->set_param( 'format', 'xml' );
    171220
    172         /**
    173          * @group multisite
    174          */
    175         function test_request_ms_child_in_root_blog() {
    176                 if ( ! is_multisite() ) {
    177                         $this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' );
    178                 }
     221                $response = $this->server->dispatch( $request );
    179222
    180                 $child = $this->factory->blog->create();
     223                ob_start();
     224                _oembed_rest_pre_serve_request( true, $response, $request, $this->server );
     225                $output = ob_get_clean();
    181226
    182                 switch_to_blog( $child );
     227                $xml = simplexml_load_string( $output );
     228                $this->assertInstanceOf( 'SimpleXMLElement', $xml );
     229        }
    183230
    184                 $post = $this->factory->post->create_and_get( array(
    185                         'post_title' => 'Hello Child Blog',
    186                 ) );
     231        function test_rest_pre_serve_request_wrong_format() {
     232                $post = $this->factory->post->create_and_get();
     233
     234                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     235                $request->set_param( 'url', get_permalink( $post->ID ) );
     236                $request->set_param( 'format', 'json' );
    187237
    188                 $request = array(
    189                         'url'      => get_permalink( $post->ID ),
    190                         'format'   => 'json',
    191                         'maxwidth' => 600,
    192                         'callback' => '',
    193                 );
     238                $response = $this->server->dispatch( $request );
    194239
    195                 $legacy_controller = new WP_oEmbed_Controller();
     240                $this->assertTrue( _oembed_rest_pre_serve_request( true, $response, $request, $this->server ) );
     241        }
    196242
    197                 $data = json_decode( $legacy_controller->dispatch( $request ), true );
     243        function test_rest_pre_serve_request_wrong_method() {
     244                $post = $this->factory->post->create_and_get();
    198245
    199                 $this->assertInternalType( 'array', $data );
    200                 $this->assertNotEmpty( $data );
     246                $request = new WP_REST_Request( 'HEAD', '/wp/v2/oembed' );
     247                $request->set_param( 'url', get_permalink( $post->ID ) );
     248                $request->set_param( 'format', 'xml' );
    201249
    202                 restore_current_blog();
     250                $response = $this->server->dispatch( $request );
     251
     252                $this->assertTrue( _oembed_rest_pre_serve_request( true, $response, $request, $this->server ) );
    203253        }
    204254
    205255        function test_get_oembed_endpoint_url() {
    206                 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url() );
    207                 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'json' ) );
    208                 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'xml' ) );
     256                $this->assertEquals( home_url() . '/?rest_route=/wp/v2/oembed', get_oembed_endpoint_url() );
     257                $this->assertEquals( home_url() . '/?rest_route=/wp/v2/oembed', get_oembed_endpoint_url( '', 'json' ) );
     258                $this->assertEquals( home_url() . '/?rest_route=/wp/v2/oembed', get_oembed_endpoint_url( '', 'xml' ) );
    209259
    210260                $post_id     = $this->factory->post->create();
    211261                $url         = get_permalink( $post_id );
    212262                $url_encoded = urlencode( $url );
    213263
    214                 $this->assertEquals( home_url() . '/?oembed=true&url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
    215                 $this->assertEquals( home_url() . '/?oembed=true&url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
     264                $this->assertEquals( home_url() . '/?rest_route=%2Fwp%2Fv2%2Foembed&url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
     265                $this->assertEquals( home_url() . '/?rest_route=%2Fwp%2Fv2%2Foembed&url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
    216266        }
    217267
    218         function test_wp_oembed_ensure_format() {
    219                 $this->assertEquals( 'json', wp_oembed_ensure_format( 'json' ) );
    220                 $this->assertEquals( 'xml', wp_oembed_ensure_format( 'xml' ) );
    221                 $this->assertEquals( 'json', wp_oembed_ensure_format( 123 ) );
    222                 $this->assertEquals( 'json', wp_oembed_ensure_format( 'random' ) );
    223                 $this->assertEquals( 'json', wp_oembed_ensure_format( array() ) );
    224         }
     268        function test_get_oembed_endpoint_url_pretty_permalinks() {
     269                update_option( 'permalink_structure', '/%postname%' );
    225270
    226         function test_oembed_create_xml() {
    227                 $actual = _oembed_create_xml( array(
    228                         'foo'  => 'bar',
    229                         'bar'  => 'baz',
    230                         'ping' => 'pong',
    231                 ) );
     271                $this->assertEquals( home_url() . '/wp-json/wp/v2/oembed', get_oembed_endpoint_url() );
     272                $this->assertEquals( home_url() . '/wp-json/wp/v2/oembed', get_oembed_endpoint_url( '', 'xml' ) );
    232273
    233                 $expected = '<oembed><foo>bar</foo><bar>baz</bar><ping>pong</ping></oembed>';
     274                $post_id     = $this->factory->post->create();
     275                $url         = get_permalink( $post_id );
     276                $url_encoded = urlencode( $url );
    234277
    235                 $this->assertStringEndsWith( $expected, trim( $actual ) );
     278                $this->assertEquals( home_url() . '/wp-json/wp/v2/oembed?url=' . $url_encoded, get_oembed_endpoint_url( $url ) );
     279                $this->assertEquals( home_url() . '/wp-json/wp/v2/oembed?url=' . $url_encoded . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) );
    236280
    237                 $actual = _oembed_create_xml( array(
    238                         'foo'  => array(
    239                                 'bar' => 'baz',
    240                         ),
    241                         'ping' => 'pong',
    242                 ) );
     281                update_option( 'permalink_structure', '' );
     282        }
    243283
    244                 $expected = '<oembed><foo><bar>baz</bar></foo><ping>pong</ping></oembed>';
     284        public function test_get_item_schema() {
     285                $request    = new WP_REST_Request( 'OPTIONS', '/wp/v2/oembed' );
     286                $response   = rest_handle_options_request( null, $this->server, $request );
     287                $data       = $response->get_data();
     288                $properties = $data['schema']['properties'];
     289                $this->assertEquals( 11, count( $properties ) );
     290                $this->assertArrayHasKey( 'type', $properties );
     291                $this->assertArrayHasKey( 'version', $properties );
     292                $this->assertArrayHasKey( 'width', $properties );
     293                $this->assertArrayHasKey( 'height', $properties );
     294                $this->assertArrayHasKey( 'title', $properties );
     295                $this->assertArrayHasKey( 'url', $properties );
     296                $this->assertArrayHasKey( 'html', $properties );
     297                $this->assertArrayHasKey( 'author_name', $properties );
     298                $this->assertArrayHasKey( 'author_url', $properties );
     299                $this->assertArrayHasKey( 'provider_name', $properties );
     300                $this->assertArrayHasKey( 'provider_url', $properties );
     301        }
    245302
    246                 $this->assertStringEndsWith( $expected, trim( $actual ) );
     303        function test_request_ms_child_in_root_blog() {
     304                if ( ! is_multisite() ) {
     305                        $this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' );
     306                }
    247307
    248                 $actual = _oembed_create_xml( array(
    249                         'foo'   => array(
    250                                 'bar' => array(
    251                                         'ping' => 'pong',
    252                                 ),
    253                         ),
    254                         'hello' => 'world',
    255                 ) );
     308                $child = $this->factory->blog->create();
    256309
    257                 $expected = '<oembed><foo><bar><ping>pong</ping></bar></foo><hello>world</hello></oembed>';
     310                switch_to_blog( $child );
    258311
    259                 $this->assertStringEndsWith( $expected, trim( $actual ) );
     312                $post = $this->factory->post->create_and_get( array(
     313                        'post_title' => 'Hello Child Blog',
     314                ) );
    260315
    261                 $actual = _oembed_create_xml( array(
    262                         array(
    263                                 'foo' => array(
    264                                         'bar',
    265                                 ),
    266                         ),
    267                         'helloworld',
     316                $user = $this->factory->user->create_and_get( array(
     317                        'display_name' => 'John Doe',
     318                ) );
     319                $post = $this->factory->post->create_and_get( array(
     320                        'post_author' => $user->ID,
     321                        'post_title'  => 'Hello World',
    268322                ) );
    269323
    270                 $expected = '<oembed><oembed><foo><oembed>bar</oembed></foo></oembed><oembed>helloworld</oembed></oembed>';
     324                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     325                $request->set_param( 'url', get_permalink( $post->ID ) );
    271326
    272                 $this->assertStringEndsWith( $expected, trim( $actual ) );
     327                $response = $this->server->dispatch( $request );
     328                $data     = $response->get_data();
     329
     330                $this->assertTrue( is_array( $data ) );
     331
     332                $this->assertArrayHasKey( 'version', $data );
     333                $this->assertArrayHasKey( 'provider_name', $data );
     334                $this->assertArrayHasKey( 'provider_url', $data );
     335                $this->assertArrayHasKey( 'author_name', $data );
     336                $this->assertArrayHasKey( 'author_url', $data );
     337                $this->assertArrayHasKey( 'title', $data );
     338                $this->assertArrayHasKey( 'type', $data );
     339
     340                restore_current_blog();
    273341        }
    274342}
  • tests/phpunit/tests/oembed/headers.php

    diff --git tests/phpunit/tests/oembed/headers.php tests/phpunit/tests/oembed/headers.php
    index 2ee7a4f..8079534 100644
     
    55 * @preserveGlobalState disabled
    66 * @group oembed
    77 * @group oembed-headers
     8 * @group restapi
    89 */
    910class Tests_oEmbed_HTTP_Headers extends WP_UnitTestCase {
    10         function test_request_json_response_headers() {
     11        /**
     12         * Test HTTP headers set by the rest_pre_serve_request method.
     13         */
     14        function test_rest_pre_serve_request_headers() {
    1115                if ( ! function_exists( 'xdebug_get_headers' ) ) {
    1216                        $this->markTestSkipped( 'xdebug is required for this test' );
    1317                }
    1418
     19                $user = $this->factory->user->create_and_get( array(
     20                        'display_name' => 'John Doe',
     21                ) );
    1522                $post = $this->factory->post->create_and_get( array(
     23                        'post_author' => $user->ID,
    1624                        'post_title'  => 'Hello World',
    1725                ) );
    1826
    19                 $request = array(
    20                         'url'      => get_permalink( $post->ID ),
    21                         'format'   => 'json',
    22                         'maxwidth' => 600,
    23                         'callback' => '',
    24                 );
    25 
    26                 $legacy_controller = new WP_oEmbed_Controller();
    27                 $legacy_controller->dispatch( $request );
    28 
    29                 $headers = xdebug_get_headers();
    30 
    31                 $this->assertTrue( in_array( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ), $headers ) );
    32                 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) );
     27                $request = new WP_REST_Request( 'GET', '/wp/v2/oembed' );
     28                $request->set_param( 'url', get_permalink( $post->ID ) );
     29                $request->set_param( 'format', 'xml' );
    3330
    34                 $request['callback'] = 'foobar';
     31                $server = new WP_REST_Server;
    3532
    36                 $legacy_controller->dispatch( $request );
    37 
    38                 $headers = xdebug_get_headers();
    39 
    40                 $this->assertTrue( in_array( 'Content-Type: application/javascript; charset=' . get_option( 'blog_charset' ), $headers ) );
    41                 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) );
    42         }
    43 
    44         function test_request_xml_response_headers() {
    45                 if ( ! function_exists( 'xdebug_get_headers' ) ) {
    46                         $this->markTestSkipped( 'xdebug is required for this test' );
    47                 }
    48 
    49                 $post = $this->factory->post->create_and_get( array(
    50                         'post_title'  => 'Hello World',
    51                 ) );
     33                $response = $server->dispatch( $request );
    5234
    53                 $request = array(
    54                         'url'      => get_permalink( $post->ID ),
    55                         'format'   => 'xml',
    56                         'maxwidth' => 600,
    57                 );
     35                ob_start();
     36                _oembed_rest_pre_serve_request( true, $response, $request, $server );
     37                $output = ob_get_clean();
    5838
    59                 $legacy_controller = new WP_oEmbed_Controller();
    60                 $legacy_controller->dispatch( $request );
     39                $this->assertNotEmpty( $output );
    6140
    6241                $headers = xdebug_get_headers();
    6342