Make WordPress Core

Ticket #40919: 40919.5.diff

File 40919.5.diff, 15.5 KB (added by jnylen0, 6 years ago)

Refresh against latest trunk

  • 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  
    110110                                control.fetchEmbedDfd.abort();
    111111                        }
    112112
    113                         control.fetchEmbedDfd = jQuery.ajax({
     113                        control.fetchEmbedDfd = wp.apiRequest({
    114114                                url: wp.media.view.settings.oEmbedProxyUrl,
    115115                                data: {
    116116                                        url: control.model.get( 'url' ),
    117117                                        maxwidth: control.model.get( 'width' ),
    118118                                        maxheight: control.model.get( 'height' ),
    119                                         _wpnonce: wp.media.view.settings.nonce.wpRestApi,
    120119                                        discover: false
    121120                                },
    122121                                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( $ ) { 
    200200                                                        embedLinkView.model.attributes.url = url;
    201201                                                }
    202202
    203                                                 embedLinkView.dfd = $.ajax({
     203                                                embedLinkView.dfd = wp.apiRequest({
    204204                                                        url: wp.media.view.settings.oEmbedProxyUrl,
    205205                                                        data: {
    206206                                                                url: url,
    207207                                                                maxwidth: embedLinkView.model.get( 'width' ),
    208208                                                                maxheight: embedLinkView.model.get( 'height' ),
    209                                                                 _wpnonce: wp.media.view.settings.nonce.wpRestApi,
    210209                                                                discover: false
    211210                                                        },
    212211                                                        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({ 
    46424642                        url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ];
    46434643                }
    46444644
    4645                 this.dfd = $.ajax({
     4645                this.dfd = wp.apiRequest({
    46464646                        url: wp.media.view.settings.oEmbedProxyUrl,
    46474647                        data: {
    46484648                                url: url,
    46494649                                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' )
    46524651                        },
    46534652                        type: 'GET',
    46544653                        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({ 
    5353                        url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ];
    5454                }
    5555
    56                 this.dfd = $.ajax({
     56                this.dfd = wp.apiRequest({
    5757                        url: wp.media.view.settings.oEmbedProxyUrl,
    5858                        data: {
    5959                                url: url,
    6060                                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' )
    6362                        },
    6463                        type: 'GET',
    6564                        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() ) { 
    34373437                'captions'  => ! apply_filters( 'disable_captions', '' ),
    34383438                'nonce'     => array(
    34393439                        'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
    3440                         'wpRestApi'    => wp_create_nonce( 'wp_rest' ),
    34413440                ),
    34423441                'post'    => array(
    34433442                        '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 ) { 
    133133                'broken' => __('An unidentified error has occurred.')
    134134        ) );
    135135
     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
    136144        $scripts->add( 'wp-pointer', "/wp-includes/js/wp-pointer$suffix.js", array( 'jquery-ui-widget', 'jquery-ui-position' ), '20111129a', 1 );
    137145        did_action( 'init' ) && $scripts->localize( 'wp-pointer', 'wpPointerL10n', array(
    138146                'dismiss' => __('Dismiss'),
    function wp_default_scripts( &$scripts ) { 
    566574
    567575        // To enqueue media-views or media-editor, call wp_enqueue_media().
    568576        // 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 );
    570578        $scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
    571579        $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 );
    572580        $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'jquery', 'media-views', 'media-audiovideo' ), false, 1 );
    573581
    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 );
    580583
    581584        if ( is_admin() ) {
    582585                $scripts->add( 'admin-tags', "/wp-admin/js/tags$suffix.js", array( 'jquery', 'wp-ajax-response' ), false, 1 );
    function wp_default_scripts( &$scripts ) { 
    669672                $scripts->add( 'admin-gallery', "/wp-admin/js/gallery$suffix.js", array( 'jquery-ui-sortable' ) );
    670673
    671674                $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' ) );
    673676                $scripts->add_inline_script( 'media-widgets', 'wp.mediaWidgets.init();', 'after' );
    674677
    675678                $scripts->add( 'media-audio-widget', "/wp-admin/js/widgets/media-audio-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) );
    676679                $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' ) );
    678681                $scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util', 'wp-a11y' ) );
    679682                $scripts->add_inline_script( 'text-widgets', 'wp.textWidgets.init();', 'after' );
    680683
  • tests/qunit/index.html

    diff --git a/tests/qunit/index.html b/tests/qunit/index.html
    index c41fffe..2ca82b3 100644
    a b  
    1919                </script>
    2020                <script>
    2121                        var wpApiSettings = {
    22                                 'root': 'http://localhost/wp-json/'
     22                                root: 'http://localhost/wp-json/',
     23                                nonce: 'not_a_real_nonce'
    2324                        };
    2425                </script>
    2526                <script src="../../src/wp-includes/js/wp-util.js"></script>
     
    7778                <script src="../../src/wp-includes/js/customize-models.js"></script>
    7879                <script src="../../src/wp-includes/js/shortcode.js"></script>
    7980                <script src="../../src/wp-admin/js/customize-controls.js"></script>
     81                <script src="../../src/wp-includes/js/api-request.js"></script>
    8082                <script src="../../src/wp-includes/js/wp-api.js"></script>
    8183
    8284                <script type='text/javascript' src='../../src/wp-includes/js/jquery/ui/core.js'></script>
     
    122124                <script src="wp-admin/js/customize-base.js"></script>
    123125                <script src="wp-admin/js/customize-header.js"></script>
    124126                <script src="wp-includes/js/shortcode.js"></script>
     127                <script src="wp-includes/js/api-request.js"></script>
    125128                <script src="wp-includes/js/wp-api.js"></script>
    126129                <script src="wp-admin/js/customize-controls.js"></script>
    127130                <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 );