Customizer: Export `nonce`, `theme`, and `url` app settings in preview as exported in pane.

* Introduce `WP_Customize_Manager::get_nonces()` to consolidate logic for retrieving nonces.
* Export nonces centrally in `wp.customize.settings.nonce` with each request and update nav menus preview to utilize.
* Send updated nonces to preview upon `nonce-refresh`.
* Request full preview refresh if Nav Menu selective refresh request fails (e.g. due to bad nonce).
* Update nav menus and widgets in Customizer to utilize `customize_refresh_nonces` for exporting nonces and keeping them up to date.

See #27355.
Fixes #35617.


git-svn-id: https://develop.svn.wordpress.org/trunk@36414 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Weston Ruter 2016-01-27 17:54:39 +00:00
parent fe7495efdf
commit 304ab7c0e4
10 changed files with 128 additions and 60 deletions

View File

@ -3375,6 +3375,7 @@
api.bind( 'nonce-refresh', function( nonce ) {
$.extend( api.settings.nonce, nonce );
$.extend( api.previewer.nonce, nonce );
api.previewer.send( 'nonce-refresh', nonce );
});
// Create Settings

View File

@ -323,7 +323,7 @@
availableMenuItemContainer.find( '.accordion-section-title' ).addClass( 'loading' );
self.loading = true;
params = {
'customize-menus-nonce': api.Menus.data.nonce,
'customize-menus-nonce': api.settings.nonce['customize-menus'],
'wp_customize': 'on',
'type': type,
'object': object,

View File

@ -1107,7 +1107,7 @@
params = {};
params.action = 'update-widget';
params.wp_customize = 'on';
params.nonce = api.Widgets.data.nonce;
params.nonce = api.settings.nonce['update-widget'];
params.theme = api.settings.theme.stylesheet;
params.customized = wp.customize.previewer.query().customized;
@ -2058,11 +2058,6 @@
sidebar_widgets: api.Widgets.SidebarControl
});
// Refresh the nonce if login sends updated nonces over.
api.bind( 'nonce-refresh', function( nonces ) {
api.Widgets.data.nonce = nonces['update-widget'];
});
/**
* Init Customizer for widgets.
*/

View File

@ -801,20 +801,21 @@ final class WP_Customize_Manager {
*/
public function customize_preview_settings() {
$settings = array(
'theme' => array(
'stylesheet' => $this->get_stylesheet(),
'active' => $this->is_theme_active(),
),
'url' => array(
'self' => empty( $_SERVER['REQUEST_URI'] ) ? home_url( '/' ) : esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ),
),
'channel' => wp_unslash( $_POST['customize_messenger_channel'] ),
'activePanels' => array(),
'activeSections' => array(),
'activeControls' => array(),
'nonce' => $this->get_nonces(),
'_dirty' => array_keys( $this->unsanitized_post_values() ),
);
if ( 2 == $this->nonce_tick ) {
$settings['nonce'] = array(
'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ),
'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() )
);
}
foreach ( $this->panels as $panel_id => $panel ) {
if ( $panel->check_capabilities() ) {
$settings['activePanels'][ $panel_id ] = $panel->active();
@ -1025,22 +1026,7 @@ final class WP_Customize_Manager {
wp_send_json_error( 'not_preview' );
}
$nonces = array(
'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ),
'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ),
);
/**
* Filter nonces for a customize_refresh_nonces AJAX request.
*
* @since 4.2.0
*
* @param array $nonces Array of refreshed nonces for save and
* preview actions.
* @param WP_Customize_Manager $this WP_Customize_Manager instance.
*/
$nonces = apply_filters( 'customize_refresh_nonces', $nonces, $this );
wp_send_json_success( $nonces );
wp_send_json_success( $this->get_nonces() );
}
/**
@ -1635,6 +1621,32 @@ final class WP_Customize_Manager {
return $this->autofocus;
}
/**
* Get nonces for the Customizer.
*
* @since 4.5.0
* @return array Nonces.
*/
public function get_nonces() {
$nonces = array(
'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ),
'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ),
);
/**
* Filter nonces for Customizer.
*
* @since 4.2.0
*
* @param array $nonces Array of refreshed nonces for save and
* preview actions.
* @param WP_Customize_Manager $this WP_Customize_Manager instance.
*/
$nonces = apply_filters( 'customize_refresh_nonces', $nonces, $this );
return $nonces;
}
/**
* Print JavaScript settings for parent window.
*
@ -1695,10 +1707,7 @@ final class WP_Customize_Manager {
),
'panels' => array(),
'sections' => array(),
'nonce' => array(
'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ),
'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ),
),
'nonce' => $this->get_nonces(),
'autofocus' => array(),
'documentTitleTmpl' => $this->get_document_title_template(),
);

View File

@ -48,6 +48,7 @@ final class WP_Customize_Nav_Menus {
$this->previewed_menus = array();
$this->manager = $manager;
add_filter( 'customize_refresh_nonces', array( $this, 'filter_nonces' ) );
add_action( 'wp_ajax_load-available-menu-items-customizer', array( $this, 'ajax_load_available_items' ) );
add_action( 'wp_ajax_search-available-menu-items-customizer', array( $this, 'ajax_search_available_items' ) );
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
@ -62,6 +63,20 @@ final class WP_Customize_Nav_Menus {
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
}
/**
* Add nonce for customizing menus.
*
* @since 4.5.0
* @access public
*
* @param array $nonces Array of nonces.
* @return array $nonces Array of nonces.
*/
public function filter_nonces( $nonces ) {
$nonces['customize-menus'] = wp_create_nonce( 'customize-menus' );
return $nonces;
}
/**
* Ajax handler for loading available menu items.
*
@ -329,7 +344,6 @@ final class WP_Customize_Nav_Menus {
// Pass data to JS.
$settings = array(
'nonce' => wp_create_nonce( 'customize-menus' ),
'allMenus' => wp_get_nav_menus(),
'itemTypes' => $this->available_item_types(),
'l10n' => array(
@ -939,12 +953,6 @@ final class WP_Customize_Nav_Menus {
'renderQueryVar' => self::RENDER_QUERY_VAR,
'renderNonceValue' => wp_create_nonce( self::RENDER_AJAX_ACTION ),
'renderNoncePostKey' => self::RENDER_NONCE_POST_KEY,
'requestUri' => empty( $_SERVER['REQUEST_URI'] ) ? home_url( '/' ) : esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ),
'theme' => array(
'stylesheet' => $this->manager->get_stylesheet(),
'active' => $this->manager->is_theme_active(),
),
'previewCustomizeNonce' => wp_create_nonce( 'preview-customize_' . $this->manager->get_stylesheet() ),
'navMenuInstanceArgs' => $this->preview_nav_menu_instance_args,
'l10n' => array(
'editNavMenuItemTooltip' => __( 'Shift-click to edit this menu item.' ),

View File

@ -661,7 +661,6 @@ final class WP_Customize_Widgets {
);
$settings = array(
'nonce' => wp_create_nonce( 'update-widget' ),
'registeredSidebars' => array_values( $wp_registered_sidebars ),
'registeredWidgets' => $wp_registered_widgets,
'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets

View File

@ -13,12 +13,7 @@
renderQueryVar: null,
renderNonceValue: null,
renderNoncePostKey: null,
previewCustomizeNonce: null,
requestUri: '/',
theme: {
active: false,
stylesheet: ''
},
navMenuInstanceArgs: {},
l10n: {}
};
@ -200,11 +195,11 @@
menuId = parseInt( menuId, 10 );
data = {
nonce: settings.previewCustomizeNonce, // for Customize Preview
nonce: wp.customize.settings.nonce.preview,
wp_customize: 'on'
};
if ( ! settings.theme.active ) {
data.theme = settings.theme.stylesheet;
if ( ! wp.customize.settings.theme.active ) {
data.theme = wp.customize.settings.theme.stylesheet;
}
data[ settings.renderQueryVar ] = '1';
@ -239,7 +234,7 @@
request = wp.ajax.send( null, {
data: data,
url: settings.requestUri
url: api.settings.url.self
} );
request.done( function( data ) {
// If the menu is now not visible, refresh since the page layout may have changed.
@ -263,6 +258,9 @@
container.removeClass( 'customize-partial-refreshing' );
$( document ).trigger( 'customize-preview-menu-refreshed', [ eventParam ] );
} );
request.fail( function() {
api.preview.send( 'refresh' );
} );
},
refreshMenuInstanceDebounced : function( instanceNumber ) {

View File

@ -146,9 +146,7 @@
});
api.preview.bind( 'active', function() {
if ( api.settings.nonce ) {
api.preview.send( 'nonce', api.settings.nonce );
}
api.preview.send( 'nonce', api.settings.nonce );
api.preview.send( 'documentTitle', document.title );
});
@ -163,6 +161,10 @@
} );
} );
api.preview.bind( 'nonce-refresh', function( nonce ) {
$.extend( api.settings.nonce, nonce );
} );
/*
* Send a message to the parent customize frame with a list of which
* containers and controls are active.

View File

@ -368,6 +368,36 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
$this->assertEmpty( $this->manager->get_autofocus() );
}
/**
* Test get_nonces() method.
*
* @see WP_Customize_Manager::get_nonces()
*/
function test_nonces() {
$nonces = $this->manager->get_nonces();
$this->assertInternalType( 'array', $nonces );
$this->assertArrayHasKey( 'save', $nonces );
$this->assertArrayHasKey( 'preview', $nonces );
add_filter( 'customize_refresh_nonces', array( $this, 'filter_customize_refresh_nonces' ), 10, 2 );
$nonces = $this->manager->get_nonces();
$this->assertArrayHasKey( 'foo', $nonces );
$this->assertEquals( wp_create_nonce( 'foo' ), $nonces['foo'] );
}
/**
* Filter for customize_refresh_nonces.
*
* @param array $nonces Nonces.
* @param WP_Customize_Manager $manager Manager.
* @return array Nonces.
*/
function filter_customize_refresh_nonces( $nonces, $manager ) {
$this->assertInstanceOf( 'WP_Customize_Manager', $manager );
$nonces['foo'] = wp_create_nonce( 'foo' );
return $nonces;
}
/**
* Test customize_pane_settings() method.
*
@ -401,6 +431,38 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
$this->assertArrayHasKey( 'preview', $data['nonce'] );
}
/**
* Test customize_preview_settings() method.
*
* @see WP_Customize_Manager::customize_preview_settings()
*/
function test_customize_preview_settings() {
wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
$this->manager->register_controls();
$this->manager->prepare_controls();
$this->manager->set_post_value( 'foo', 'bar' );
$_POST['customize_messenger_channel'] = 'preview-0';
ob_start();
$this->manager->customize_preview_settings();
$content = ob_get_clean();
$this->assertEquals( 1, preg_match( '/var _wpCustomizeSettings = ({.+});/', $content, $matches ) );
$settings = json_decode( $matches[1], true );
$this->assertArrayHasKey( 'theme', $settings );
$this->assertArrayHasKey( 'url', $settings );
$this->assertArrayHasKey( 'channel', $settings );
$this->assertArrayHasKey( 'activePanels', $settings );
$this->assertArrayHasKey( 'activeSections', $settings );
$this->assertArrayHasKey( 'activeControls', $settings );
$this->assertArrayHasKey( 'nonce', $settings );
$this->assertArrayHasKey( '_dirty', $settings );
$this->assertArrayHasKey( 'preview', $settings['nonce'] );
$this->assertEquals( array( 'foo' ), $settings['_dirty'] );
}
/**
* @ticket 33552
*/

View File

@ -647,12 +647,6 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
$this->assertContains( 'renderQueryVar', $data );
$this->assertContains( 'renderNonceValue', $data );
$this->assertContains( 'renderNoncePostKey', $data );
$this->assertContains( 'requestUri', $data );
$this->assertContains( 'theme', $data );
$this->assertContains( 'previewCustomizeNonce', $data );
$this->assertContains( 'navMenuInstanceArgs', $data );
$this->assertContains( 'requestUri', $data );
}
}