Make WordPress Core

Ticket #40450: 40450.1.diff

File 40450.1.diff, 22.7 KB (added by jnylen0, 8 years ago)

https://patch-diff.githubusercontent.com/raw/xwp/wordpress-develop/pull/225.diff

  • src/wp-includes/class-oembed.php

    diff --git a/src/wp-includes/class-oembed.php b/src/wp-includes/class-oembed.php
    index 49a189f..0a64305 100644
    a b public static function _remove_provider_early( $format ) { 
    317317        }
    318318
    319319        /**
     320         * Takes a URL and attempts to return the oEmbed data.
     321         *
     322         * @see WP_oEmbed::fetch()
     323         *
     324         * @since 4.8.0
     325         * @access public
     326         *
     327         * @param string       $url  The URL to the content that should be attempted to be embedded.
     328         * @param array|string $args Optional. Arguments, usually passed from a shortcode. Default empty.
     329         * @return false|object False on failure, otherwise the result in the form of an object.
     330         */
     331        public function get_data( $url, $args = '' ) {
     332                $args = wp_parse_args( $args );
     333
     334                $provider = $this->get_provider( $url, $args );
     335
     336                if ( ! $provider ) {
     337                        return false;
     338                }
     339
     340                $data = $this->fetch( $provider, $url, $args );
     341
     342                if ( false === $data ) {
     343                        return false;
     344                }
     345
     346                return $data;
     347        }
     348
     349        /**
    320350         * The do-it-all function that takes a URL and attempts to return the HTML.
    321351         *
    322352         * @see WP_oEmbed::fetch()
    public static function _remove_provider_early( $format ) { 
    330360         * @return false|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed.
    331361         */
    332362        public function get_html( $url, $args = '' ) {
    333                 $args = wp_parse_args( $args );
    334 
    335363                /**
    336364                 * Filters the oEmbed result before any HTTP requests are made.
    337365                 *
    public function get_html( $url, $args = '' ) { 
    353381                        return $pre;
    354382                }
    355383
    356                 $provider = $this->get_provider( $url, $args );
     384                $data = $this->get_data( $url, $args );
    357385
    358                 if ( ! $provider || false === $data = $this->fetch( $provider, $url, $args ) ) {
     386                if ( false === $data ) {
    359387                        return false;
    360388                }
    361389
  • src/wp-includes/class-wp-oembed-controller.php

    diff --git a/src/wp-includes/class-wp-oembed-controller.php b/src/wp-includes/class-wp-oembed-controller.php
    index 13fed83..d825c41 100644
    a b public function register_routes() { 
    5252                                ),
    5353                        ),
    5454                ) );
     55
     56                register_rest_route( 'oembed/1.0', '/proxy', array(
     57                        array(
     58                                'methods'  => WP_REST_Server::READABLE,
     59                                'callback' => array( $this, 'get_proxy_item' ),
     60                                'permission_callback' => array( $this, 'get_proxy_item_permissions_check' ),
     61                                'args'     => array(
     62                                        'url'      => array(
     63                                                'description'       => __( 'The URL of the resource for which to fetch oEmbed data.' ),
     64                                                'type'              => 'string',
     65                                                'required'          => true,
     66                                                'sanitize_callback' => 'esc_url_raw',
     67                                        ),
     68                                        'format'   => array(
     69                                                'description'       => __( 'The oEmbed format to use.' ),
     70                                                'type'              => 'string',
     71                                                'default'           => 'json',
     72                                                'enum'              => array(
     73                                                        'json',
     74                                                        'xml',
     75                                                ),
     76                                        ),
     77                                        'maxwidth' => array(
     78                                                'description'       => __( 'The maximum width of the embed frame in pixels.' ),
     79                                                'type'              => 'integer',
     80                                                'default'           => $maxwidth,
     81                                                'sanitize_callback' => 'absint',
     82                                        ),
     83                                        'maxheight' => array(
     84                                                'description'       => __( 'The maximum height of the embed frame in pixels.' ),
     85                                                'type'              => 'integer',
     86                                                'sanitize_callback' => 'absint',
     87                                        ),
     88                                        'discover' => array(
     89                                                'description'       => __( 'Whether to perform an oEmbed discovery request for non-whitelisted providers.' ),
     90                                                'type'              => 'boolean',
     91                                                'default'           => true,
     92                                        ),
     93                                ),
     94                        ),
     95                ) );
    5596        }
    5697
    5798        /**
    58          * Callback for the API endpoint.
     99         * Callback for the embed API endpoint.
    59100         *
    60101         * Returns the JSON object for the post.
    61102         *
    public function get_item( $request ) { 
    86127
    87128                return $data;
    88129        }
     130
     131        /**
     132         * Checks if current user can make a proxy oEmbed request.
     133         *
     134         * @since 4.8.0
     135         * @access public
     136         *
     137         * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
     138         */
     139        public function get_proxy_item_permissions_check() {
     140                if ( ! current_user_can( 'edit_posts' ) ) {
     141                        return new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to make proxied oEmbed requests.' ), array( 'status' => rest_authorization_required_code() ) );
     142                }
     143                return true;
     144        }
     145
     146        /**
     147         * Callback for the proxy API endpoint.
     148         *
     149         * Returns the JSON object for the proxied item.
     150         *
     151         * @since 4.8.0
     152         * @access public
     153         *
     154         * @see WP_oEmbed::get_html()
     155         * @param WP_REST_Request $request Full data about the request.
     156         * @return WP_Error|array oEmbed response data or WP_Error on failure.
     157         */
     158        public function get_proxy_item( $request ) {
     159                $args = $request->get_params();
     160
     161                // Serve oEmbed data from cache if set.
     162                $cache_key = 'oembed_' . md5( serialize( $args ) );
     163                $data = get_transient( $cache_key );
     164                if ( ! empty( $data ) ) {
     165                        return $data;
     166                }
     167
     168                $url = $request['url'];
     169                unset( $args['url'] );
     170
     171                $data = _wp_oembed_get_object()->get_data( $url, $args );
     172
     173                if ( false === $data ) {
     174                        return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) );
     175                }
     176
     177                /**
     178                 * Filters the oEmbed TTL value (time to live).
     179                 *
     180                 * Similar to the {@see 'oembed_ttl'} filter, but for the REST API
     181                 * oEmbed proxy endpoint.
     182                 *
     183                 * @since 4.8.0
     184                 *
     185                 * @param int    $time    Time to live (in seconds).
     186                 * @param string $url     The attempted embed URL.
     187                 * @param array  $args    An array of embed request arguments.
     188                 */
     189                $ttl = apply_filters( 'rest_oembed_ttl', DAY_IN_SECONDS, $url, $args );
     190
     191                set_transient( $cache_key, $data, $ttl );
     192
     193                return $data;
     194        }
    89195}
  • src/wp-includes/js/media-views.js

    diff --git a/src/wp-includes/js/media-views.js b/src/wp-includes/js/media-views.js
    index be802d7..6c1aa51 100644
    a b EmbedLink = wp.media.view.Settings.extend({ 
    46244624        }, wp.media.controller.Embed.sensitivity ),
    46254625
    46264626        fetch: function() {
    4627                 var embed;
    46284627
    46294628                // check if they haven't typed in 500 ms
    46304629                if ( $('#embed-url-field').val() !== this.model.get('url') ) {
    EmbedLink = wp.media.view.Settings.extend({ 
    46354634                        this.dfd.abort();
    46364635                }
    46374636
    4638                 embed = new wp.shortcode({
    4639                         tag: 'embed',
    4640                         attrs: _.pick( this.model.attributes, [ 'width', 'height', 'src' ] ),
    4641                         content: this.model.get('url')
    4642                 });
    4643 
    46444637                this.dfd = $.ajax({
    4645                         type:    'POST',
    4646                         url:     wp.ajax.settings.url,
    4647                         context: this,
    4648                         data:    {
    4649                                 action: 'parse-embed',
    4650                                 post_ID: wp.media.view.settings.post.id,
    4651                                 shortcode: embed.string()
    4652                         }
     4638                        url: wp.media.view.settings.oEmbedProxyUrl,
     4639                        data: {
     4640                                url: this.model.get( 'url' ),
     4641                                maxwidth: this.model.get( 'width' ),
     4642                                maxheight: this.model.get( 'height' ),
     4643                                _wpnonce: wp.media.view.settings.nonce.wpRestApi
     4644                        },
     4645                        type: 'GET',
     4646                        dataType: 'json',
     4647                        context: this
    46534648                })
    4654                         .done( this.renderoEmbed )
     4649                        .done( function( response ) {
     4650                                this.renderoEmbed( {
     4651                                        data: {
     4652                                                body: response.html || ''
     4653                                        }
     4654                                } );
     4655                        } )
    46554656                        .fail( this.renderFail );
    46564657        },
    46574658
  • src/wp-includes/js/media/views/embed/link.js

    diff --git a/src/wp-includes/js/media/views/embed/link.js b/src/wp-includes/js/media/views/embed/link.js
    index 86aa5c8..1af96cf 100644
    a b EmbedLink = wp.media.view.Settings.extend({ 
    3535        }, wp.media.controller.Embed.sensitivity ),
    3636
    3737        fetch: function() {
    38                 var embed;
    3938
    4039                // check if they haven't typed in 500 ms
    4140                if ( $('#embed-url-field').val() !== this.model.get('url') ) {
    EmbedLink = wp.media.view.Settings.extend({ 
    4645                        this.dfd.abort();
    4746                }
    4847
    49                 embed = new wp.shortcode({
    50                         tag: 'embed',
    51                         attrs: _.pick( this.model.attributes, [ 'width', 'height', 'src' ] ),
    52                         content: this.model.get('url')
    53                 });
    54 
    5548                this.dfd = $.ajax({
    56                         type:    'POST',
    57                         url:     wp.ajax.settings.url,
    58                         context: this,
    59                         data:    {
    60                                 action: 'parse-embed',
    61                                 post_ID: wp.media.view.settings.post.id,
    62                                 shortcode: embed.string()
    63                         }
     49                        url: wp.media.view.settings.oEmbedProxyUrl,
     50                        data: {
     51                                url: this.model.get( 'url' ),
     52                                maxwidth: this.model.get( 'width' ),
     53                                maxheight: this.model.get( 'height' ),
     54                                _wpnonce: wp.media.view.settings.nonce.wpRestApi
     55                        },
     56                        type: 'GET',
     57                        dataType: 'json',
     58                        context: this
    6459                })
    65                         .done( this.renderoEmbed )
     60                        .done( function( response ) {
     61                                this.renderoEmbed( {
     62                                        data: {
     63                                                body: response.html || ''
     64                                        }
     65                                } );
     66                        } )
    6667                        .fail( this.renderFail );
    6768        },
    6869
  • src/wp-includes/media.php

    diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
    index 6253bd5..76aaa1c 100644
    a b function wp_enqueue_media( $args = array() ) { 
    34143414                'captions'  => ! apply_filters( 'disable_captions', '' ),
    34153415                'nonce'     => array(
    34163416                        'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
     3417                        'wpRestApi'    => wp_create_nonce( 'wp_rest' ),
    34173418                ),
    34183419                'post'    => array(
    34193420                        'id' => 0,
    function wp_enqueue_media( $args = array() ) { 
    34233424                        'audio' => ( $show_audio_playlist ) ? 1 : 0,
    34243425                        'video' => ( $show_video_playlist ) ? 1 : 0,
    34253426                ),
     3427                'oEmbedProxyUrl' => rest_url( 'oembed/1.0/proxy' ),
    34263428                'embedExts'    => $exts,
    34273429                'embedMimes'   => $ext_mimes,
    34283430                'contentWidth' => $content_width,
  • tests/phpunit/tests/oembed/controller.php

    diff --git a/tests/phpunit/tests/oembed/controller.php b/tests/phpunit/tests/oembed/controller.php
    index 3c9d051..db88a65 100644
    a b class Test_oEmbed_Controller extends WP_UnitTestCase { 
    99         * @var WP_REST_Server
    1010         */
    1111        protected $server;
     12        protected static $editor;
     13        protected static $subscriber;
     14        const YOUTUBE_VIDEO_ID = 'OQSNhk5ICTI';
     15        const INVALID_OEMBED_URL = 'https://www.notreallyanoembedprovider.com/watch?v=awesome-cat-video';
     16
     17        public static function wpSetUpBeforeClass( $factory ) {
     18                self::$subscriber = $factory->user->create( array(
     19                        'role' => 'subscriber',
     20                ) );
     21                self::$editor = $factory->user->create( array(
     22                        'role'       => 'editor',
     23                        'user_email' => 'editor@example.com',
     24                ) );
     25        }
     26
     27        public static function wpTearDownAfterClass() {
     28                self::delete_user( self::$subscriber );
     29                self::delete_user( self::$editor );
     30        }
    1231
    1332        public function setUp() {
    1433                parent::setUp();
    public function setUp() { 
    1837                $this->server = $wp_rest_server = new Spy_REST_Server();
    1938
    2039                do_action( 'rest_api_init', $this->server );
     40                add_filter( 'pre_http_request', array( $this, 'mock_embed_request' ), 10, 3 );
     41                $this->request_count = 0;
     42        }
     43
     44        public function tearDown() {
     45                parent::tearDown();
     46
     47                remove_filter( 'pre_http_request', array( $this, 'mock_embed_request' ), 10, 3 );
     48        }
     49
     50        /**
     51         * Count of the number of requests attempted.
     52         *
     53         * @var int
     54         */
     55        public $request_count = 0;
     56
     57        /**
     58         * Intercept oEmbed requests and mock responses.
     59         *
     60         * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.
     61         * @param mixed  $r       HTTP request arguments.
     62         * @param string $url     The request URL.
     63         * @return array Response data.
     64         */
     65        public function mock_embed_request( $preempt, $r, $url ) {
     66                unset( $preempt, $r );
     67
     68                $this->request_count += 1;
     69
     70                // Mock request to YouTube Embed.
     71                if ( false !== strpos( $url, self::YOUTUBE_VIDEO_ID ) ) {
     72                        return array(
     73                                'response' => array(
     74                                        'code' => 200,
     75                                ),
     76                                'body' => wp_json_encode(
     77                                        array(
     78                                                'version'          => '1.0',
     79                                                'type'             => 'video',
     80                                                'provider_name'    => 'YouTube',
     81                                                'provider_url'     => 'https://www.youtube.com',
     82                                                'thumbnail_width'  => 480,
     83                                                'width'            => 500,
     84                                                'thumbnail_height' => 360,
     85                                                'html'             => '<iframe width="500" height="375" src="https://www.youtube.com/embed/' . self::YOUTUBE_VIDEO_ID . '?feature=oembed" frameborder="0" allowfullscreen></iframe>',
     86                                                'author_name'      => 'Yosemitebear62',
     87                                                'thumbnail_url'    => 'https://i.ytimg.com/vi/' . self::YOUTUBE_VIDEO_ID . '/hqdefault.jpg',
     88                                                'title'            => 'Yosemitebear Mountain Double Rainbow 1-8-10',
     89                                                'height'           => 375,
     90                                        )
     91                                ),
     92                        );
     93                } else {
     94                        return array(
     95                                'response' => array(
     96                                        'code' => 404,
     97                                ),
     98                        );
     99                }
    21100        }
    22101
    23102        function test_wp_oembed_ensure_format() {
    public function test_route_availability() { 
    86165                $this->assertArrayHasKey( 'callback', $route[0] );
    87166                $this->assertArrayHasKey( 'methods', $route[0] );
    88167                $this->assertArrayHasKey( 'args', $route[0] );
     168
     169                // Check proxy route registration.
     170                $this->assertArrayHasKey( '/oembed/1.0/proxy', $filtered_routes );
     171                $proxy_route = $filtered_routes['/oembed/1.0/proxy'];
     172                $this->assertCount( 1, $proxy_route );
     173                $this->assertArrayHasKey( 'callback', $proxy_route[0] );
     174                $this->assertArrayHasKey( 'permission_callback', $proxy_route[0] );
     175                $this->assertArrayHasKey( 'methods', $proxy_route[0] );
     176                $this->assertArrayHasKey( 'args', $proxy_route[0] );
    89177        }
    90178
    91179        function test_request_with_wrong_method() {
    function test_get_oembed_endpoint_url_pretty_permalinks() { 
    351439
    352440                update_option( 'permalink_structure', '' );
    353441        }
     442
     443        public function test_proxy_without_permission() {
     444                // Test without a login.
     445                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     446                $response = $this->server->dispatch( $request );
     447
     448                $this->assertEquals( 400, $response->get_status() );
     449
     450                // Test with a user that does not have edit_posts capability.
     451                wp_set_current_user( self::$subscriber );
     452                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     453                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     454                $response = $this->server->dispatch( $request );
     455
     456                $this->assertEquals( 403, $response->get_status() );
     457                $data = $response->get_data();
     458                $this->assertEquals( $data['code'], 'rest_forbidden' );
     459        }
     460
     461        public function test_proxy_with_invalid_oembed_provider() {
     462                wp_set_current_user( self::$editor );
     463                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     464                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     465                $response = $this->server->dispatch( $request );
     466                $this->assertEquals( 404, $response->get_status() );
     467                $data = $response->get_data();
     468                $this->assertEquals( 'oembed_invalid_url', $data['code'] );
     469        }
     470
     471        public function test_proxy_with_invalid_type() {
     472                wp_set_current_user( self::$editor );
     473                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     474                $request->set_param( 'type', 'xml' );
     475                $response = $this->server->dispatch( $request );
     476
     477                $this->assertEquals( 400, $response->get_status() );
     478                $data = $response->get_data();
     479        }
     480
     481        public function test_proxy_with_valid_oembed_provider() {
     482                wp_set_current_user( self::$editor );
     483
     484                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     485                $request->set_param( 'url', 'https://www.youtube.com/watch?v=' . self::YOUTUBE_VIDEO_ID );
     486                $response = $this->server->dispatch( $request );
     487                $this->assertEquals( 200, $response->get_status() );
     488                $this->assertEquals( 1, $this->request_count );
     489
     490                // Subsequent request is cached and so it should not cause a request.
     491                $response = $this->server->dispatch( $request );
     492                $this->assertEquals( 1, $this->request_count );
     493
     494                // Test data object.
     495                $data = $response->get_data();
     496
     497                $this->assertNotEmpty( $data );
     498                $this->assertTrue( is_object( $data ) );
     499                $this->assertEquals( 'YouTube', $data->provider_name );
     500                $this->assertEquals( 'https://i.ytimg.com/vi/' . self::YOUTUBE_VIDEO_ID . '/hqdefault.jpg', $data->thumbnail_url );
     501        }
     502
     503        public function test_proxy_with_invalid_oembed_provider_no_discovery() {
     504                wp_set_current_user( self::$editor );
     505
     506                // If discover is false for an unkown provider, no discovery request should take place.
     507                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     508                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     509                $request->set_param( 'discover', 0 );
     510                $response = $this->server->dispatch( $request );
     511                $this->assertEquals( 404, $response->get_status() );
     512                $this->assertEquals( 0, $this->request_count );
     513        }
     514
     515        public function test_proxy_with_invalid_oembed_provider_with_default_discover_param() {
     516                wp_set_current_user( self::$editor );
     517
     518                // For an unkown provider, a discovery request should happen.
     519                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     520                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     521                $response = $this->server->dispatch( $request );
     522                $this->assertEquals( 404, $response->get_status() );
     523                $this->assertEquals( 1, $this->request_count );
     524        }
     525
     526        public function test_proxy_with_invalid_discover_param() {
     527                wp_set_current_user( self::$editor );
     528                $request = new WP_REST_Request( 'GET', '/oembed/1.0/proxy' );
     529                $request->set_param( 'url', self::INVALID_OEMBED_URL );
     530                $request->set_param( 'discover', 'notaboolean' );
     531
     532                $response = $this->server->dispatch( $request );
     533
     534                $this->assertEquals( 400, $response->get_status() );
     535                $data = $response->get_data();
     536                $this->assertEquals( $data['code'], 'rest_invalid_param' );
     537        }
    354538}
  • tests/phpunit/tests/rest-api/rest-schema-setup.php

    diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php
    index 360a075..0c86255 100644
    a b public function test_expected_routes_in_schema() { 
    4343                        '/',
    4444                        '/oembed/1.0',
    4545                        '/oembed/1.0/embed',
     46                        '/oembed/1.0/proxy',
    4647                        '/wp/v2',
    4748                        '/wp/v2/posts',
    4849                        '/wp/v2/posts/(?P<id>[\\d]+)',
    public function test_build_wp_api_client_fixtures() { 
    166167                                'name'  => 'oembeds',
    167168                        ),
    168169                        array(
     170                                'route' => '/oembed/1.0/proxy',
     171                                'name'  => 'oembedProxy',
     172                        ),
     173                        array(
    169174                                'route' => '/wp/v2/posts',
    170175                                'name'  => 'PostsCollection',
    171176                        ),
  • tests/qunit/fixtures/wp-api-generated.js

    diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js
    index 0df5b9e..f6a5bfe 100644
    a b mockedApiResponse.Schema = { 
    9595                "self": "http://example.org/?rest_route=/oembed/1.0/embed"
    9696            }
    9797        },
     98        "/oembed/1.0/proxy": {
     99            "namespace": "oembed/1.0",
     100            "methods": [
     101                "GET"
     102            ],
     103            "endpoints": [
     104                {
     105                    "methods": [
     106                        "GET"
     107                    ],
     108                    "args": {
     109                        "url": {
     110                            "required": true,
     111                            "description": "The URL of the resource for which to fetch oEmbed data.",
     112                            "type": "string"
     113                        },
     114                        "format": {
     115                            "required": false,
     116                            "default": "json",
     117                            "enum": [
     118                                "json",
     119                                "xml"
     120                            ],
     121                            "description": "The oEmbed format to use.",
     122                            "type": "string"
     123                        },
     124                        "maxwidth": {
     125                            "required": false,
     126                            "default": 600,
     127                            "description": "The maximum width of the embed frame in pixels.",
     128                            "type": "integer"
     129                        },
     130                        "maxheight": {
     131                            "required": false,
     132                            "description": "The maximum height of the embed frame in pixels.",
     133                            "type": "integer"
     134                        },
     135                        "discover": {
     136                            "required": false,
     137                            "default": true,
     138                            "description": "Whether to perform an oEmbed discovery request for non-whitelisted providers.",
     139                            "type": "boolean"
     140                        }
     141                    }
     142                }
     143            ],
     144            "_links": {
     145                "self": "http://example.org/?rest_route=/oembed/1.0/proxy"
     146            }
     147        },
    98148        "/wp/v2": {
    99149            "namespace": "wp/v2",
    100150            "methods": [
    mockedApiResponse.oembed = { 
    33873437            "_links": {
    33883438                "self": "http://example.org/?rest_route=/oembed/1.0/embed"
    33893439            }
     3440        },
     3441        "/oembed/1.0/proxy": {
     3442            "namespace": "oembed/1.0",
     3443            "methods": [
     3444                "GET"
     3445            ],
     3446            "endpoints": [
     3447                {
     3448                    "methods": [
     3449                        "GET"
     3450                    ],
     3451                    "args": {
     3452                        "url": {
     3453                            "required": true,
     3454                            "description": "The URL of the resource for which to fetch oEmbed data.",
     3455                            "type": "string"
     3456                        },
     3457                        "format": {
     3458                            "required": false,
     3459                            "default": "json",
     3460                            "enum": [
     3461                                "json",
     3462                                "xml"
     3463                            ],
     3464                            "description": "The oEmbed format to use.",
     3465                            "type": "string"
     3466                        },
     3467                        "maxwidth": {
     3468                            "required": false,
     3469                            "default": 600,
     3470                            "description": "The maximum width of the embed frame in pixels.",
     3471                            "type": "integer"
     3472                        },
     3473                        "maxheight": {
     3474                            "required": false,
     3475                            "description": "The maximum height of the embed frame in pixels.",
     3476                            "type": "integer"
     3477                        },
     3478                        "discover": {
     3479                            "required": false,
     3480                            "default": true,
     3481                            "description": "Whether to perform an oEmbed discovery request for non-whitelisted providers.",
     3482                            "type": "boolean"
     3483                        }
     3484                    }
     3485                }
     3486            ],
     3487            "_links": {
     3488                "self": "http://example.org/?rest_route=/oembed/1.0/proxy"
     3489            }
    33903490        }
    33913491    }
    33923492};
    mockedApiResponse.oembeds = { 
    34023502    }
    34033503};
    34043504
     3505mockedApiResponse.oembedProxy = {
     3506    "code": "rest_missing_callback_param",
     3507    "message": "Missing parameter(s): url",
     3508    "data": {
     3509        "status": 400,
     3510        "params": [
     3511            "url"
     3512        ]
     3513    }
     3514};
     3515
    34053516mockedApiResponse.PostsCollection = [
    34063517    {
    34073518        "id": 3,