Customize: Introduce `settings_previewed` arg and getter on `WP_Customize_Manager` which controls whether `WP_Customize_Setting::preview()` should be called on settings.

The `settings_previewed` property eliminates the need for the Customizer components from having to look at global `doing_ajax` state. This is in particular needed when saving settings, as some settings will short-circuit the update operation if they detect no changes are introduced. This is also needed for low-level integrations with the Customizer, such as in REST API endpoints under development.

Props stubgo, westonruter, utkarshpatel for testing.
See #38900.
Fixes #39221.

Built from https://develop.svn.wordpress.org/trunk@41205


git-svn-id: http://core.svn.wordpress.org/trunk@41045 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Weston Ruter 2017-08-02 05:35:41 +00:00
parent eb658592df
commit a193916f46
5 changed files with 59 additions and 30 deletions

View File

@ -173,6 +173,14 @@ final class WP_Customize_Manager {
*/
protected $messenger_channel;
/**
* Whether settings should be previewed.
*
* @since 4.9.0
* @var bool
*/
protected $settings_previewed;
/**
* Unsanitized values for Customize Settings parsed from $_POST['customized'].
*
@ -216,12 +224,13 @@ final class WP_Customize_Manager {
* @type string $changeset_uuid Changeset UUID, the post_name for the customize_changeset post containing the customized state. Defaults to new UUID.
* @type string $theme Theme to be previewed (for theme switch). Defaults to customize_theme or theme query params.
* @type string $messenger_channel Messenger channel. Defaults to customize_messenger_channel query param.
* @type bool $settings_previewed If settings should be previewed. Defaults to true.
* }
*/
public function __construct( $args = array() ) {
$args = array_merge(
array_fill_keys( array( 'changeset_uuid', 'theme', 'messenger_channel' ), null ),
array_fill_keys( array( 'changeset_uuid', 'theme', 'messenger_channel', 'settings_previewed' ), null ),
$args
);
@ -242,9 +251,14 @@ final class WP_Customize_Manager {
$args['messenger_channel'] = sanitize_key( wp_unslash( $_REQUEST['customize_messenger_channel'] ) );
}
if ( ! isset( $args['settings_previewed'] ) ) {
$args['settings_previewed'] = true;
}
$this->original_stylesheet = get_stylesheet();
$this->theme = wp_get_theme( $args['theme'] );
$this->messenger_channel = $args['messenger_channel'];
$this->settings_previewed = ! empty( $args['settings_previewed'] );
$this->_changeset_uuid = $args['changeset_uuid'];
require_once( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
@ -621,6 +635,18 @@ final class WP_Customize_Manager {
do_action( 'stop_previewing_theme', $this );
}
/**
* Gets whether settings are or will be previewed.
*
* @since 4.9.0
* @see WP_Customize_Setting::preview()
*
* @return bool
*/
public function settings_previewed() {
return $this->settings_previewed;
}
/**
* Get the changeset UUID.
*
@ -728,15 +754,7 @@ final class WP_Customize_Manager {
*/
do_action( 'customize_register', $this );
/*
* Note that settings must be previewed here even outside the customizer preview
* and also in the customizer pane itself. This is to enable loading an existing
* changeset into the customizer. Previewing the settings only has to be prevented
* in the case of a customize_save action because then update_option()
* may short-circuit because it will detect that there are no changes to
* make.
*/
if ( ! $this->doing_ajax( 'customize_save' ) ) {
if ( $this->settings_previewed() ) {
foreach ( $this->settings as $setting ) {
$setting->preview();
}

View File

@ -526,15 +526,12 @@ final class WP_Customize_Nav_Menus {
$nav_menus_setting_ids[] = $setting_id;
}
}
$this->manager->add_dynamic_settings( $nav_menus_setting_ids );
if ( ! $this->manager->doing_ajax( 'customize_save' ) ) {
foreach ( $nav_menus_setting_ids as $setting_id ) {
$setting = $this->manager->get_setting( $setting_id );
if ( $setting ) {
$settings = $this->manager->add_dynamic_settings( $nav_menus_setting_ids );
if ( $this->manager->settings_previewed() ) {
foreach ( $settings as $setting ) {
$setting->preview();
}
}
}
// Require JS-rendered control types.
$this->manager->register_panel_type( 'WP_Customize_Nav_Menus_Panel' );

View File

@ -211,12 +211,7 @@ final class WP_Customize_Widgets {
$settings = $this->manager->add_dynamic_settings( array_unique( $widget_setting_ids ) );
/*
* Preview settings right away so that widgets and sidebars will get registered properly.
* But don't do this if a customize_save because this will cause WP to think there is nothing
* changed that needs to be saved.
*/
if ( ! $this->manager->doing_ajax( 'customize_save' ) ) {
if ( $this->manager->settings_previewed() ) {
foreach ( $settings as $setting ) {
$setting->preview();
}
@ -506,7 +501,7 @@ final class WP_Customize_Widgets {
}
}
if ( ! $this->manager->doing_ajax( 'customize_save' ) ) {
if ( $this->manager->settings_previewed() ) {
foreach ( $new_setting_ids as $new_setting_id ) {
$this->manager->get_setting( $new_setting_id )->preview();
}

View File

@ -2816,8 +2816,24 @@ function _wp_customize_include() {
$messenger_channel = sanitize_key( $input_vars['customize_messenger_channel'] );
}
/*
* Note that settings must be previewed even outside the customizer preview
* and also in the customizer pane itself. This is to enable loading an existing
* changeset into the customizer. Previewing the settings only has to be prevented
* here in the case of a customize_save action because this will cause WP to think
* there is nothing changed that needs to be saved.
*/
$is_customize_save_action = (
wp_doing_ajax()
&&
isset( $_REQUEST['action'] )
&&
'customize_save' === wp_unslash( $_REQUEST['action'] )
);
$settings_previewed = ! $is_customize_save_action;
require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
$GLOBALS['wp_customize'] = new WP_Customize_Manager( compact( 'changeset_uuid', 'theme', 'messenger_channel' ) );
$GLOBALS['wp_customize'] = new WP_Customize_Manager( compact( 'changeset_uuid', 'theme', 'messenger_channel', 'settings_previewed' ) );
}
/**
@ -2849,7 +2865,10 @@ function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_p
if ( empty( $wp_customize ) ) {
require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
$wp_customize = new WP_Customize_Manager( array( 'changeset_uuid' => $changeset_post->post_name ) );
$wp_customize = new WP_Customize_Manager( array(
'changeset_uuid' => $changeset_post->post_name,
'settings_previewed' => false,
) );
}
if ( ! did_action( 'customize_register' ) ) {

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.9-alpha-41204';
$wp_version = '4.9-alpha-41205';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.