Make WordPress Core

Ticket #38573: 38573.wip.diff

File 38573.wip.diff, 11.4 KB (added by westonruter, 8 years ago)
  • src/wp-admin/js/customize-controls.js

    diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
    index 56c061f..779bc0b 100644
     
    50955095                        api.control.add( id, control );
    50965096                });
    50975097
     5098                // @todo Pass allowed arrays?
     5099                $.ajaxPrefilter( api.utils.prefilterAjaxPreviewingRequests );
     5100
    50985101                // Focus the autofocused element
    50995102                _.each( [ 'panel', 'section', 'control' ], function( type ) {
    51005103                        var id = api.settings.autofocus[ type ];
  • src/wp-includes/js/customize-base.js

    diff --git src/wp-includes/js/customize-base.js src/wp-includes/js/customize-base.js
    index a1528de..131d5ff 100644
    window.wp = window.wp || {}; 
    844844                return queryParams;
    845845        };
    846846
     847        /**
     848         * Should the supplied URL be previewable.
     849         *
     850         * @since 4.7.0
     851         * @access public
     852         *
     853         * @param {string|HTMLAnchorElement|HTMLAreaElement} url URL.
     854         * @param {string} element.search Query string.
     855         * @param {string} element.pathname Path.
     856         * @param {string} element.host Host.
     857         * @param {object} [options]
     858         * @param {object} [options.allowAdminAjax=false] Allow admin-ajax.php requests.
     859         * @param {object} [options.allowedUrls] Allowed URLs. Defaults to wp.customize.settings.url.allowed.
     860         * @returns {boolean} Is appropriate for changeset link.
     861         */
     862        api.utils.isUrlPreviewable = function isUrlPreviewable( url, options ) {
     863                var matchesAllowedUrl, parsedAllowedUrl, args, element;
     864
     865                if ( _.isString( url ) ) {
     866                        element = document.createElement( 'a' );
     867                        element.href = url;
     868                } else {
     869                        element = url;
     870                }
     871
     872                args = _.extend( {}, { allowAdminAjax: false }, options || {} );
     873
     874                if ( 'javascript:' === element.protocol ) { // jshint ignore:line
     875                        return true;
     876                }
     877
     878                // Only web URLs can be previewed.
     879                if ( 'https:' !== element.protocol && 'http:' !== element.protocol ) {
     880                        return false;
     881                }
     882
     883                parsedAllowedUrl = document.createElement( 'a' );
     884                matchesAllowedUrl = ! _.isUndefined( _.find( args.allowedUrls || api.settings.url.allowed, function( allowedUrl ) {
     885                        parsedAllowedUrl.href = allowedUrl;
     886                        return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host === element.host && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
     887                } ) );
     888                if ( ! matchesAllowedUrl ) {
     889                        return false;
     890                }
     891
     892                // Skip wp login and signup pages.
     893                if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) ) {
     894                        return false;
     895                }
     896
     897                // Allow links to admin ajax as faux frontend URLs.
     898                if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) ) {
     899                        return args.allowAdminAjax;
     900                }
     901
     902                // Disallow links to admin, includes, and content.
     903                if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) ) {
     904                        return false;
     905                }
     906
     907                return true;
     908        };
     909
     910        api.utils.addAjaxRequestPrefilter = function() {
     911                // @todo allowed URLs.
     912                // @todo allow Admin ajax, true on frontend but false in admin.
     913                // @todo This depends on having instantiated settings anyway so really the
     914        };
     915
     916        /**
     917         * Rewrite Ajax requests to inject customizer state.
     918         *
     919         * @since 4.7.0
     920         * @access protected
     921         *
     922         * @param {object} options Options.
     923         * @param {string} options.type Type.
     924         * @param {string} options.url URL.
     925         * @param {object} originalOptions Original options.
     926         * @param {XMLHttpRequest} xhr XHR.
     927         * @returns {void}
     928         */
     929        api.utils.prefilterAjaxPreviewingRequests = function prefilterAjaxPreviewingRequests( options, originalOptions, xhr ) {
     930                var urlParser, queryParams, requestMethod, dirtyValues = {};
     931                urlParser = document.createElement( 'a' );
     932                urlParser.href = options.url;
     933
     934                // Abort if the request is not for this site.
     935                if ( ! api.utils.isUrlPreviewable( urlParser, { allowAdminAjax: _.isUndefined( window.pagenow ), allowedUrls: api.settings.url.allowed } ) ) {
     936                        return;
     937                }
     938
     939                queryParams = api.utils.parseQueryString( urlParser.search.substring( 1 ) );
     940
     941                // Abort if if changeset UUID is already present.
     942                if ( queryParams.customize_changeset_uuid ) {
     943                        return;
     944                }
     945
     946                if ( _.isFunction( api.dirtyValues ) ) {
     947                        dirtyValues = api.dirtyValues( { unsaved: true } );
     948                } else if ( api.extended( api.Values ) ) {
     949                        api.each( function( setting ) {
     950                                if ( setting._dirty ) {
     951                                        dirtyValues[ setting.id ] = setting.get();
     952                                }
     953                        } );
     954                }
     955
     956                if ( ! _.isEmpty( dirtyValues ) ) {
     957                        requestMethod = options.type.toUpperCase();
     958
     959                        // Override underlying request method to ensure unsaved changes to changeset can be included (force Backbone.emulateHTTP).
     960                        if ( 'POST' !== requestMethod ) {
     961                                xhr.setRequestHeader( 'X-HTTP-Method-Override', requestMethod );
     962                                queryParams._method = requestMethod;
     963                                options.type = 'POST';
     964                        }
     965
     966                        // Amend the post data with the customized values.
     967                        if ( options.data ) {
     968                                options.data += '&';
     969                        } else {
     970                                options.data = '';
     971                        }
     972                        options.data += $.param( {
     973                                customized: JSON.stringify( dirtyValues )
     974                        } );
     975                }
     976
     977                // Include customized state query params in URL.
     978                queryParams.customize_changeset_uuid = api.settings.changeset.uuid;
     979                if ( ! api.settings.theme.active ) {
     980                        queryParams.customize_theme = api.settings.theme.stylesheet;
     981                }
     982                urlParser.search = $.param( queryParams );
     983                options.url = urlParser.href;
     984        };
     985
    847986        // Expose the API publicly on window.wp.customize
    848987        exports.customize = api;
    849988})( wp, jQuery );
  • src/wp-includes/js/customize-preview.js

    diff --git src/wp-includes/js/customize-preview.js src/wp-includes/js/customize-preview.js
    index 484ccf4..ffe1c22 100644
     
    152152                        }
    153153
    154154                        // If the link is not previewable, prevent the browser from navigating to it.
    155                         if ( ! api.isLinkPreviewable( link[0] ) ) {
     155                        if ( ! api.utils.isUrlPreviewable( link[0], { allowedUrls: api.settings.url.allowed } ) ) {
    156156                                wp.a11y.speak( api.settings.l10n.linkUnpreviewable );
    157157                                event.preventDefault();
    158158                                return;
     
    193193                        urlParser.href = form.prop( 'action' );
    194194
    195195                        // If the link is not previewable, prevent the browser from navigating to it.
    196                         if ( 'GET' !== form.prop( 'method' ).toUpperCase() || ! api.isLinkPreviewable( urlParser ) ) {
     196                        if ( 'GET' !== form.prop( 'method' ).toUpperCase() || ! api.utils.isUrlPreviewable( urlParser, { allowedUrls: api.settings.url.allowed } ) ) {
    197197                                wp.a11y.speak( api.settings.l10n.formUnpreviewable );
    198198                                event.preventDefault();
    199199                                return;
     
    268268        };
    269269
    270270        /**
    271          * Should the supplied link is previewable.
    272          *
    273          * @since 4.7.0
    274          * @access public
    275          *
    276          * @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
    277          * @param {string} element.search Query string.
    278          * @param {string} element.pathname Path.
    279          * @param {string} element.host Host.
    280          * @param {object} [options]
    281          * @param {object} [options.allowAdminAjax=false] Allow admin-ajax.php requests.
    282          * @returns {boolean} Is appropriate for changeset link.
    283          */
    284         api.isLinkPreviewable = function isLinkPreviewable( element, options ) {
    285                 var matchesAllowedUrl, parsedAllowedUrl, args;
    286 
    287                 args = _.extend( {}, { allowAdminAjax: false }, options || {} );
    288 
    289                 if ( 'javascript:' === element.protocol ) { // jshint ignore:line
    290                         return true;
    291                 }
    292 
    293                 // Only web URLs can be previewed.
    294                 if ( 'https:' !== element.protocol && 'http:' !== element.protocol ) {
    295                         return false;
    296                 }
    297 
    298                 parsedAllowedUrl = document.createElement( 'a' );
    299                 matchesAllowedUrl = ! _.isUndefined( _.find( api.settings.url.allowed, function( allowedUrl ) {
    300                         parsedAllowedUrl.href = allowedUrl;
    301                         return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host === element.host && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
    302                 } ) );
    303                 if ( ! matchesAllowedUrl ) {
    304                         return false;
    305                 }
    306 
    307                 // Skip wp login and signup pages.
    308                 if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) ) {
    309                         return false;
    310                 }
    311 
    312                 // Allow links to admin ajax as faux frontend URLs.
    313                 if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) ) {
    314                         return args.allowAdminAjax;
    315                 }
    316 
    317                 // Disallow links to admin, includes, and content.
    318                 if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) ) {
    319                         return false;
    320                 }
    321 
    322                 return true;
    323         };
    324 
    325         /**
    326271         * Inject the customize_changeset_uuid query param into links on the frontend.
    327272         *
    328273         * @since 4.7.0
     
    352297                        element.protocol = 'https:';
    353298                }
    354299
    355                 if ( ! api.isLinkPreviewable( element ) ) {
     300                if ( ! api.utils.isUrlPreviewable( element, { allowedUrls: api.settings.url.allowed } ) ) {
    356301                        $( element ).addClass( 'customize-unpreviewable' );
    357302                        return;
    358303                }
     
    375320        };
    376321
    377322        /**
    378          * Inject the changeset UUID into Ajax requests.
    379          *
    380          * @since 4.7.0
    381          * @access protected
    382          *
    383          * @return {void}
    384          */
    385         api.addRequestPreviewing = function addRequestPreviewing() {
    386 
    387                 /**
    388                  * Rewrite Ajax requests to inject customizer state.
    389                  *
    390                  * @param {object} options Options.
    391                  * @param {string} options.type Type.
    392                  * @param {string} options.url URL.
    393                  * @param {object} originalOptions Original options.
    394                  * @param {XMLHttpRequest} xhr XHR.
    395                  * @returns {void}
    396                  */
    397                 var prefilterAjax = function( options, originalOptions, xhr ) {
    398                         var urlParser, queryParams, requestMethod, dirtyValues = {};
    399                         urlParser = document.createElement( 'a' );
    400                         urlParser.href = options.url;
    401 
    402                         // Abort if the request is not for this site.
    403                         if ( ! api.isLinkPreviewable( urlParser, { allowAdminAjax: true } ) ) {
    404                                 return;
    405                         }
    406                         queryParams = api.utils.parseQueryString( urlParser.search.substring( 1 ) );
    407 
    408                         // Note that _dirty flag will be cleared with changeset updates.
    409                         api.each( function( setting ) {
    410                                 if ( setting._dirty ) {
    411                                         dirtyValues[ setting.id ] = setting.get();
    412                                 }
    413                         } );
    414 
    415                         if ( ! _.isEmpty( dirtyValues ) ) {
    416                                 requestMethod = options.type.toUpperCase();
    417 
    418                                 // Override underlying request method to ensure unsaved changes to changeset can be included (force Backbone.emulateHTTP).
    419                                 if ( 'POST' !== requestMethod ) {
    420                                         xhr.setRequestHeader( 'X-HTTP-Method-Override', requestMethod );
    421                                         queryParams._method = requestMethod;
    422                                         options.type = 'POST';
    423                                 }
    424 
    425                                 // Amend the post data with the customized values.
    426                                 if ( options.data ) {
    427                                         options.data += '&';
    428                                 } else {
    429                                         options.data = '';
    430                                 }
    431                                 options.data += $.param( {
    432                                         customized: JSON.stringify( dirtyValues )
    433                                 } );
    434                         }
    435 
    436                         // Include customized state query params in URL.
    437                         queryParams.customize_changeset_uuid = api.settings.changeset.uuid;
    438                         if ( ! api.settings.theme.active ) {
    439                                 queryParams.customize_theme = api.settings.theme.stylesheet;
    440                         }
    441                         urlParser.search = $.param( queryParams );
    442                         options.url = urlParser.href;
    443                 };
    444 
    445                 $.ajaxPrefilter( prefilterAjax );
    446         };
    447 
    448         /**
    449323         * Inject changeset UUID into forms, allowing preview to persist through submissions.
    450324         *
    451325         * @since 4.7.0
     
    501375                        form.action = urlParser.href;
    502376                }
    503377
    504                 if ( 'GET' !== form.method.toUpperCase() || ! api.isLinkPreviewable( urlParser ) ) {
     378                if ( 'GET' !== form.method.toUpperCase() || ! api.utils.isUrlPreviewable( urlParser, { allowedUrls: api.settings.url.allowed } ) ) {
    505379                        $( form ).addClass( 'customize-unpreviewable' );
    506380                        return;
    507381                }
     
    608482                });
    609483
    610484                api.addLinkPreviewing();
    611                 api.addRequestPreviewing();
     485                $.ajaxPrefilter( api.utils.prefilterAjaxPreviewingRequests );
    612486                api.addFormPreviewing();
    613487
    614488                /**