Ticket #40919: 40919.5.diff
File 40919.5.diff, 15.5 KB (added by , 6 years ago) |
---|
-
src/wp-admin/js/widgets/media-video-widget.js
diff --git a/src/wp-admin/js/widgets/media-video-widget.js b/src/wp-admin/js/widgets/media-video-widget.js index 07b203f..9eb532c 100644
a b 110 110 control.fetchEmbedDfd.abort(); 111 111 } 112 112 113 control.fetchEmbedDfd = jQuery.ajax({113 control.fetchEmbedDfd = wp.apiRequest({ 114 114 url: wp.media.view.settings.oEmbedProxyUrl, 115 115 data: { 116 116 url: control.model.get( 'url' ), 117 117 maxwidth: control.model.get( 'width' ), 118 118 maxheight: control.model.get( 'height' ), 119 _wpnonce: wp.media.view.settings.nonce.wpRestApi,120 119 discover: false 121 120 }, 122 121 type: 'GET', -
src/wp-admin/js/widgets/media-widgets.js
diff --git a/src/wp-admin/js/widgets/media-widgets.js b/src/wp-admin/js/widgets/media-widgets.js index e922670..c4f23e1 100644
a b wp.mediaWidgets = ( function( $ ) { 200 200 embedLinkView.model.attributes.url = url; 201 201 } 202 202 203 embedLinkView.dfd = $.ajax({203 embedLinkView.dfd = wp.apiRequest({ 204 204 url: wp.media.view.settings.oEmbedProxyUrl, 205 205 data: { 206 206 url: url, 207 207 maxwidth: embedLinkView.model.get( 'width' ), 208 208 maxheight: embedLinkView.model.get( 'height' ), 209 _wpnonce: wp.media.view.settings.nonce.wpRestApi,210 209 discover: false 211 210 }, 212 211 type: 'GET', -
new file src/wp-includes/js/api-request.js
diff --git a/src/wp-includes/js/api-request.js b/src/wp-includes/js/api-request.js new file mode 100644 index 0000000..2b4ac4b
- + 1 /** 2 * Thin jQuery.ajax wrapper for WP REST API requests. 3 * 4 * Currently only applies to requests that do not use the `wp-api.js` Backbone 5 * client library, though this may change. Serves several purposes: 6 * 7 * - Allows overriding these requests as needed by customized WP installations. 8 * - Sends the REST API nonce as a request header. 9 * - Allows specifying only an endpoint namespace/path instead of a full URL. 10 * 11 * @namespace wp.apiRequest 12 * @since 4.9.0 13 */ 14 15 ( function( $ ) { 16 var wpApiSettings = window.wpApiSettings; 17 18 function apiRequest( options ) { 19 options = apiRequest.buildAjaxOptions( options ); 20 return apiRequest.transport( options ); 21 }; 22 23 apiRequest.buildAjaxOptions = function( options ) { 24 var url = options.url; 25 var path = options.path; 26 var namespaceTrimmed, endpointTrimmed; 27 var headers, addNonceHeader, headerName; 28 29 if ( 30 typeof options.namespace === 'string' && 31 typeof options.endpoint === 'string' 32 ) { 33 namespaceTrimmed = options.namespace.replace( /^\/|\/$/g, '' ); 34 endpointTrimmed = options.endpoint.replace( /^\//, '' ); 35 if ( endpointTrimmed ) { 36 path = namespaceTrimmed + '/' + endpointTrimmed; 37 } else { 38 path = namespaceTrimmed; 39 } 40 } 41 if ( typeof path === 'string' ) { 42 url = wpApiSettings.root + path.replace( /^\//, '' ); 43 } 44 45 // If ?_wpnonce=... is present, no need to add a nonce header. 46 addNonceHeader = ! ( options.data && options.data._wpnonce ); 47 48 headers = options.headers || {}; 49 50 // If an 'X-WP-Nonce' header (or any case-insensitive variation 51 // thereof) was specified, no need to add a nonce header. 52 if ( addNonceHeader ) { 53 for ( headerName in headers ) { 54 if ( headers.hasOwnProperty( headerName ) ) { 55 if ( headerName.toLowerCase() === 'x-wp-nonce' ) { 56 addNonceHeader = false; 57 break; 58 } 59 } 60 } 61 } 62 63 if ( addNonceHeader ) { 64 // Do not mutate the original headers object, if any. 65 headers = $.extend( { 66 'X-WP-Nonce': wpApiSettings.nonce 67 }, headers ); 68 } 69 70 // Do not mutate the original options object. 71 options = $.extend( {}, options, { 72 headers: headers, 73 url: url 74 } ); 75 76 delete options.path; 77 delete options.namespace; 78 delete options.endpoint; 79 80 return options; 81 }; 82 83 apiRequest.transport = $.ajax; 84 85 window.wp = window.wp || {}; 86 window.wp.apiRequest = apiRequest; 87 } )( jQuery ); -
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 991b3d0..6d46229 100644
a b EmbedLink = wp.media.view.Settings.extend({ 4642 4642 url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ]; 4643 4643 } 4644 4644 4645 this.dfd = $.ajax({4645 this.dfd = wp.apiRequest({ 4646 4646 url: wp.media.view.settings.oEmbedProxyUrl, 4647 4647 data: { 4648 4648 url: url, 4649 4649 maxwidth: this.model.get( 'width' ), 4650 maxheight: this.model.get( 'height' ), 4651 _wpnonce: wp.media.view.settings.nonce.wpRestApi 4650 maxheight: this.model.get( 'height' ) 4652 4651 }, 4653 4652 type: 'GET', 4654 4653 dataType: 'json', -
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 36925f4..12126d8 100644
a b EmbedLink = wp.media.view.Settings.extend({ 53 53 url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ]; 54 54 } 55 55 56 this.dfd = $.ajax({56 this.dfd = wp.apiRequest({ 57 57 url: wp.media.view.settings.oEmbedProxyUrl, 58 58 data: { 59 59 url: url, 60 60 maxwidth: this.model.get( 'width' ), 61 maxheight: this.model.get( 'height' ), 62 _wpnonce: wp.media.view.settings.nonce.wpRestApi 61 maxheight: this.model.get( 'height' ) 63 62 }, 64 63 type: 'GET', 65 64 dataType: 'json', -
src/wp-includes/media.php
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 81dc502..6c4fce4 100644
a b function wp_enqueue_media( $args = array() ) { 3437 3437 'captions' => ! apply_filters( 'disable_captions', '' ), 3438 3438 'nonce' => array( 3439 3439 'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ), 3440 'wpRestApi' => wp_create_nonce( 'wp_rest' ),3441 3440 ), 3442 3441 'post' => array( 3443 3442 'id' => 0, -
src/wp-includes/script-loader.php
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 8858984..3c3659e 100644
a b function wp_default_scripts( &$scripts ) { 133 133 'broken' => __('An unidentified error has occurred.') 134 134 ) ); 135 135 136 $scripts->add( 'wp-api-request', "/wp-includes/js/api-request$suffix.js", array( 'jquery' ), false, 1 ); 137 // `wpApiSettings` is also used by `wp-api`, which depends on this script. 138 did_action( 'init' ) && $scripts->localize( 'wp-api-request', 'wpApiSettings', array( 139 'root' => esc_url_raw( get_rest_url() ), 140 'nonce' => ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ), 141 'versionString' => 'wp/v2/', 142 ) ); 143 136 144 $scripts->add( 'wp-pointer', "/wp-includes/js/wp-pointer$suffix.js", array( 'jquery-ui-widget', 'jquery-ui-position' ), '20111129a', 1 ); 137 145 did_action( 'init' ) && $scripts->localize( 'wp-pointer', 'wpPointerL10n', array( 138 146 'dismiss' => __('Dismiss'), … … function wp_default_scripts( &$scripts ) { 566 574 567 575 // To enqueue media-views or media-editor, call wp_enqueue_media(). 568 576 // Both rely on numerous settings, styles, and templates to operate correctly. 569 $scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement' ), false, 1 );577 $scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'wp-api-request' ), false, 1 ); 570 578 $scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 ); 571 579 $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 ); 572 580 $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'jquery', 'media-views', 'media-audiovideo' ), false, 1 ); 573 581 574 $scripts->add( 'wp-api', "/wp-includes/js/wp-api$suffix.js", array( 'jquery', 'backbone', 'underscore' ), false, 1 ); 575 did_action( 'init' ) && $scripts->localize( 'wp-api', 'wpApiSettings', array( 576 'root' => esc_url_raw( get_rest_url() ), 577 'nonce' => ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ), 578 'versionString' => 'wp/v2/', 579 ) ); 582 $scripts->add( 'wp-api', "/wp-includes/js/wp-api$suffix.js", array( 'jquery', 'backbone', 'underscore', 'wp-api-request' ), false, 1 ); 580 583 581 584 if ( is_admin() ) { 582 585 $scripts->add( 'admin-tags', "/wp-admin/js/tags$suffix.js", array( 'jquery', 'wp-ajax-response' ), false, 1 ); … … function wp_default_scripts( &$scripts ) { 669 672 $scripts->add( 'admin-gallery', "/wp-admin/js/gallery$suffix.js", array( 'jquery-ui-sortable' ) ); 670 673 671 674 $scripts->add( 'admin-widgets', "/wp-admin/js/widgets$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), false, 1 ); 672 $scripts->add( 'media-widgets', "/wp-admin/js/widgets/media-widgets$suffix.js", array( 'jquery', 'media-models', 'media-views' ) );675 $scripts->add( 'media-widgets', "/wp-admin/js/widgets/media-widgets$suffix.js", array( 'jquery', 'media-models', 'media-views', 'wp-api-request' ) ); 673 676 $scripts->add_inline_script( 'media-widgets', 'wp.mediaWidgets.init();', 'after' ); 674 677 675 678 $scripts->add( 'media-audio-widget', "/wp-admin/js/widgets/media-audio-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) ); 676 679 $scripts->add( 'media-image-widget', "/wp-admin/js/widgets/media-image-widget$suffix.js", array( 'media-widgets' ) ); 677 $scripts->add( 'media-video-widget', "/wp-admin/js/widgets/media-video-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) );680 $scripts->add( 'media-video-widget', "/wp-admin/js/widgets/media-video-widget$suffix.js", array( 'media-widgets', 'media-audiovideo', 'wp-api-request' ) ); 678 681 $scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util', 'wp-a11y' ) ); 679 682 $scripts->add_inline_script( 'text-widgets', 'wp.textWidgets.init();', 'after' ); 680 683 -
tests/qunit/index.html
diff --git a/tests/qunit/index.html b/tests/qunit/index.html index c41fffe..2ca82b3 100644
a b 19 19 </script> 20 20 <script> 21 21 var wpApiSettings = { 22 'root': 'http://localhost/wp-json/' 22 root: 'http://localhost/wp-json/', 23 nonce: 'not_a_real_nonce' 23 24 }; 24 25 </script> 25 26 <script src="../../src/wp-includes/js/wp-util.js"></script> … … 77 78 <script src="../../src/wp-includes/js/customize-models.js"></script> 78 79 <script src="../../src/wp-includes/js/shortcode.js"></script> 79 80 <script src="../../src/wp-admin/js/customize-controls.js"></script> 81 <script src="../../src/wp-includes/js/api-request.js"></script> 80 82 <script src="../../src/wp-includes/js/wp-api.js"></script> 81 83 82 84 <script type='text/javascript' src='../../src/wp-includes/js/jquery/ui/core.js'></script> … … 122 124 <script src="wp-admin/js/customize-base.js"></script> 123 125 <script src="wp-admin/js/customize-header.js"></script> 124 126 <script src="wp-includes/js/shortcode.js"></script> 127 <script src="wp-includes/js/api-request.js"></script> 125 128 <script src="wp-includes/js/wp-api.js"></script> 126 129 <script src="wp-admin/js/customize-controls.js"></script> 127 130 <script src="wp-admin/js/customize-controls-utils.js"></script> -
new file tests/qunit/wp-includes/js/api-request.js
diff --git a/tests/qunit/wp-includes/js/api-request.js b/tests/qunit/wp-includes/js/api-request.js new file mode 100644 index 0000000..079ef49
- + 1 /* global wp, wpApiSettings */ 2 ( function( QUnit ) { 3 var originalRootUrl = window.wpApiSettings.root; 4 5 var nonceHeader = { 'X-WP-Nonce': 'not_a_real_nonce' }; 6 7 QUnit.module( 'wp-api-request', { 8 afterEach: function() { 9 window.wpApiSettings.root = originalRootUrl; 10 } 11 } ); 12 13 QUnit.test( 'does not mutate original object', function( assert ) { 14 var settingsOriginal = { 15 url: 'aaaaa', 16 path: 'wp/v2/posts', 17 headers: { 18 'Header-Name': 'value' 19 }, 20 data: { 21 orderby: 'something' 22 } 23 }; 24 25 var settings = wp.apiRequest.buildAjaxOptions( settingsOriginal ); 26 27 assert.notStrictEqual( settings, settingsOriginal ); 28 assert.notStrictEqual( settings.headers, settingsOriginal.headers ); 29 assert.strictEqual( settings.data, settingsOriginal.data ); 30 31 assert.deepEqual( settings, { 32 url: 'http://localhost/wp-json/wp/v2/posts', 33 headers: { 34 'X-WP-Nonce': 'not_a_real_nonce', 35 'Header-Name': 'value' 36 }, 37 data: { 38 orderby: 'something' 39 } 40 } ); 41 42 assert.deepEqual( settingsOriginal, { 43 url: 'aaaaa', 44 path: 'wp/v2/posts', 45 headers: { 46 'Header-Name': 'value' 47 }, 48 data: { 49 orderby: 'something' 50 } 51 } ); 52 } ); 53 54 QUnit.test( 'does not add nonce header if already present', function( assert ) { 55 [ 'X-WP-Nonce', 'x-wp-nonce', 'X-WP-NONCE' ].forEach( function( headerName ) { 56 var nonceHeader = {}; 57 nonceHeader[ headerName ] = 'still_not_a_real_nonce'; 58 59 var settingsOriginal = { 60 url: 'aaaa', 61 headers: JSON.parse( JSON.stringify( nonceHeader ) ) 62 }; 63 64 var settings = wp.apiRequest.buildAjaxOptions( settingsOriginal ); 65 66 assert.notStrictEqual( settings, settingsOriginal ); 67 assert.strictEqual( settings.headers, settingsOriginal.headers ); 68 69 assert.deepEqual( settings, { 70 url: 'aaaa', 71 headers: nonceHeader 72 } ); 73 } ); 74 } ); 75 76 QUnit.test( 'does not add nonce header if ?_wpnonce=... present', function( assert ) { 77 var settingsOriginal = { 78 url: 'aaaa', 79 data: { 80 _wpnonce: 'definitely_not_a_real_nonce' 81 } 82 }; 83 84 var settings = wp.apiRequest.buildAjaxOptions( settingsOriginal ); 85 86 assert.notStrictEqual( settings, settingsOriginal ); 87 88 assert.deepEqual( settings, { 89 url: 'aaaa', 90 headers: {}, 91 data: { 92 _wpnonce: 'definitely_not_a_real_nonce' 93 } 94 } ); 95 } ); 96 97 QUnit.test( 'accepts namespace and endpoint', function( assert ) { 98 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 99 namespace: 'wp/v2', 100 endpoint: 'posts' 101 } ), { 102 url: 'http://localhost/wp-json/wp/v2/posts', 103 headers: nonceHeader 104 } ); 105 } ); 106 107 QUnit.test( 'accepts namespace and endpoint with slashes', function( assert ) { 108 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 109 namespace: '/wp/v2/', 110 endpoint: '/posts' 111 } ), { 112 url: 'http://localhost/wp-json/wp/v2/posts', 113 headers: nonceHeader 114 } ); 115 } ); 116 117 QUnit.test( 'accepts namespace and empty endpoint', function( assert ) { 118 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 119 namespace: 'wp/v2', 120 endpoint: '' 121 } ), { 122 url: 'http://localhost/wp-json/wp/v2', 123 headers: nonceHeader 124 } ); 125 } ); 126 127 QUnit.test( 'accepts empty namespace and empty endpoint', function( assert ) { 128 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 129 namespace: '', 130 endpoint: '' 131 } ), { 132 url: 'http://localhost/wp-json/', 133 headers: nonceHeader 134 } ); 135 } ); 136 137 QUnit.test( 138 'accepts namespace and endpoint with slashes (plain permalinks)', 139 function( assert ) { 140 window.wpApiSettings.root = 'http://localhost/?rest_route=/'; 141 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 142 namespace: '/wp/v2/', 143 endpoint: '/posts' 144 } ), { 145 url: 'http://localhost/?rest_route=/wp/v2/posts', 146 headers: nonceHeader 147 } ); 148 } 149 ); 150 151 QUnit.test( 152 'accepts empty namespace and empty endpoint (plain permalinks)', 153 function( assert ) { 154 window.wpApiSettings.root = 'http://localhost/?rest_route=/'; 155 assert.deepEqual( wp.apiRequest.buildAjaxOptions( { 156 namespace: '', 157 endpoint: '' 158 } ), { 159 url: 'http://localhost/?rest_route=/', 160 headers: nonceHeader 161 } ); 162 } 163 ); 164 } )( window.QUnit );