From 46f03144b09cdf85bdcd5483f5a5b973a32a88d3 Mon Sep 17 00:00:00 2001 From: koopersmith Date: Thu, 24 May 2012 01:48:32 +0000 Subject: [PATCH] Theme Customizer: Properly handle redirects in the preview by setting wp_redirect_status to 200. props nacin, see #20507, #19910. git-svn-id: http://core.svn.wordpress.org/trunk@20861 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-customize-manager.php | 18 ++++++++++ wp-includes/js/customize-controls.dev.js | 40 +++++++++++++++------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/wp-includes/class-wp-customize-manager.php b/wp-includes/class-wp-customize-manager.php index 0c35df0b5..37ba2ddb5 100644 --- a/wp-includes/class-wp-customize-manager.php +++ b/wp-includes/class-wp-customize-manager.php @@ -34,6 +34,9 @@ final class WP_Customize_Manager { add_action( 'setup_theme', array( $this, 'setup_theme' ) ); add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); + // Run wp_redirect_status late to make sure we override the status last. + add_action( 'wp_redirect_status', array( $this, 'wp_redirect_status' ), 1000 ); + add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); add_action( 'customize_register', array( $this, 'register_controls' ) ); @@ -210,6 +213,21 @@ final class WP_Customize_Manager { $this->customize_preview_init(); } + /** + * Prevents AJAX requests from following redirects when previewing a theme + * by issuing a 200 response instead of a 30x. + * + * Instead, the JS will sniff out the location header. + * + * @since 3.4.0 + */ + public function wp_redirect_status( $status ) { + if ( $this->is_preview() && ! is_admin() ) + return 200; + + return $status; + } + /** * Decode the $_POST attribute used to override the WP_Customize_Setting values. * diff --git a/wp-includes/js/customize-controls.dev.js b/wp-includes/js/customize-controls.dev.js index f1f29f3fc..fe6e8a894 100644 --- a/wp-includes/js/customize-controls.dev.js +++ b/wp-includes/js/customize-controls.dev.js @@ -318,23 +318,29 @@ api.Messenger.prototype.initialize.call( this, params.url ); + // We're dynamically generating the iframe, so the origin is set + // to the current window's location, not the url's. + this.origin.unlink( this.url ).set( window.location.href ); + + // Limit the URL to internal, front-end links. + this.url.setter( function( to ) { + // Bail if we're navigating to a different origin or wp-admin. + if ( 0 !== to.indexOf( self.origin() + '/' ) || -1 !== to.indexOf( 'wp-admin' ) ) + return null; + + return to; + }); + + // Refresh the preview when the URL is changed. + this.url.bind( this.refresh ); + this.scroll = 0; this.bind( 'scroll', function( distance ) { this.scroll = distance; }); - // We're dynamically generating the iframe, so the origin is set - // to the current window's location, not the url's. - this.origin.unlink( this.url ).set( window.location.href ); - - this.bind( 'url', function( url ) { - // Bail if we're navigating to the current url, to a different origin, or wp-admin. - if ( this.url() == url || 0 !== url.indexOf( this.origin() + '/' ) || -1 !== url.indexOf( 'wp-admin' ) ) - return; - - this.url( url ); - this.refresh(); - }); + // Update the URL when the iframe sends a URL message. + this.bind( 'url', this.url ); }, loader: function() { if ( this.loading ) @@ -365,7 +371,15 @@ type: 'POST', data: this.query() || {}, success: function( response ) { - var iframe = self.loader()[0].contentWindow; + var iframe = self.loader()[0].contentWindow, + location = self.request.getResponseHeader('Location'); + + // Check if the location response header differs from the current URL. + // If so, the request was redirected; try loading the requested page. + if ( location && location != self.url() ) { + self.url( location ); + return; + } self.loader().one( 'load', self.loaded );