Customize: Ensure that a setting (especially a multidimensional one) can still be previewed when the post value to preview is set after `preview()` is invoked.
* Introduce `customize_post_value_set_{$setting_id}` and `customize_post_value_set` actions which are done when `WP_Customize_Manager::set_post_value()` is called. * Clear the `preview_applied` flag for aggregated multidimensional settings when a post value is set. This ensures the new value is used instead of a previously-cached previewed value. * Move `$is_preview` property from subclasses to `WP_Customize_Setting` parent class. * Deferred preview: Ensure that when `preview()` short-circuits due to not being applicable that it will be called again later when the post value is set. * Populate post value for updated-widget with the (unsanitized) JS-value in `WP_Customize_Widgets::call_widget_update()` so that value will be properly sanitized when accessed in `WP_Customize_Manager::post_value()`. Includes unit tests with assertions to check the reported issues and validate the fixes. Fixes defect introduced in [35007]. See #32103. Fixes #34738. Built from https://develop.svn.wordpress.org/trunk@35724 git-svn-id: http://core.svn.wordpress.org/trunk@35688 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
fd9bd77fe5
commit
5dae1386aa
|
@ -659,6 +659,36 @@ final class WP_Customize_Manager {
|
||||||
public function set_post_value( $setting_id, $value ) {
|
public function set_post_value( $setting_id, $value ) {
|
||||||
$this->unsanitized_post_values();
|
$this->unsanitized_post_values();
|
||||||
$this->_post_values[ $setting_id ] = $value;
|
$this->_post_values[ $setting_id ] = $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Announce when a specific setting's unsanitized post value has been set.
|
||||||
|
*
|
||||||
|
* Fires when the {@see WP_Customize_Manager::set_post_value()} method is called.
|
||||||
|
*
|
||||||
|
* The dynamic portion of the hook name, `$setting_id`, refers to the setting ID.
|
||||||
|
*
|
||||||
|
* @since 4.4.0
|
||||||
|
*
|
||||||
|
* @param mixed $value Unsanitized setting post value.
|
||||||
|
* @param WP_Customize_Manager $this WP_Customize_Manager instance.
|
||||||
|
*/
|
||||||
|
do_action( "customize_post_value_set_{$setting_id}", $value, $this );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Announce when any setting's unsanitized post value has been set.
|
||||||
|
*
|
||||||
|
* Fires when the {@see WP_Customize_Manager::set_post_value()} method is called.
|
||||||
|
*
|
||||||
|
* This is useful for <code>WP_Customize_Setting</code> instances to watch
|
||||||
|
* in order to update a cached previewed value.
|
||||||
|
*
|
||||||
|
* @since 4.4.0
|
||||||
|
*
|
||||||
|
* @param string $setting_id Setting ID.
|
||||||
|
* @param mixed $value Unsanitized setting post value.
|
||||||
|
* @param WP_Customize_Manager $this WP_Customize_Manager instance.
|
||||||
|
*/
|
||||||
|
do_action( 'customize_post_value_set', $setting_id, $value, $this );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -81,6 +81,15 @@ class WP_Customize_Setting {
|
||||||
*/
|
*/
|
||||||
protected $id_data = array();
|
protected $id_data = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not preview() was called.
|
||||||
|
*
|
||||||
|
* @since 4.4.0
|
||||||
|
* @access protected
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $is_previewed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of multidimensional values to improve performance.
|
* Cache of multidimensional values to improve performance.
|
||||||
*
|
*
|
||||||
|
@ -191,6 +200,8 @@ class WP_Customize_Setting {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $this->id_data['keys'] ) ) {
|
if ( ! empty( $this->id_data['keys'] ) ) {
|
||||||
|
// Note the preview-applied flag is cleared at priority 9 to ensure it is cleared before a deferred-preview runs.
|
||||||
|
add_action( "customize_post_value_set_{$this->id}", array( $this, '_clear_aggregated_multidimensional_preview_applied_flag' ), 9 );
|
||||||
$this->is_multidimensional_aggregated = true;
|
$this->is_multidimensional_aggregated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,6 +256,12 @@ class WP_Customize_Setting {
|
||||||
if ( ! isset( $this->_previewed_blog_id ) ) {
|
if ( ! isset( $this->_previewed_blog_id ) ) {
|
||||||
$this->_previewed_blog_id = get_current_blog_id();
|
$this->_previewed_blog_id = get_current_blog_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent re-previewing an already-previewed setting.
|
||||||
|
if ( $this->is_previewed ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$id_base = $this->id_data['base'];
|
$id_base = $this->id_data['base'];
|
||||||
$is_multidimensional = ! empty( $this->id_data['keys'] );
|
$is_multidimensional = ! empty( $this->id_data['keys'] );
|
||||||
$multidimensional_filter = array( $this, '_multidimensional_preview_filter' );
|
$multidimensional_filter = array( $this, '_multidimensional_preview_filter' );
|
||||||
|
@ -273,7 +290,11 @@ class WP_Customize_Setting {
|
||||||
$needs_preview = ( $undefined === $value ); // Because the default needs to be supplied.
|
$needs_preview = ( $undefined === $value ); // Because the default needs to be supplied.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the setting does not need previewing now, defer to when it has a value to preview.
|
||||||
if ( ! $needs_preview ) {
|
if ( ! $needs_preview ) {
|
||||||
|
if ( ! has_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) ) ) {
|
||||||
|
add_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) );
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,9 +348,28 @@ class WP_Customize_Setting {
|
||||||
*/
|
*/
|
||||||
do_action( "customize_preview_{$this->type}", $this );
|
do_action( "customize_preview_{$this->type}", $this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->is_previewed = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear out the previewed-applied flag for a multidimensional-aggregated value whenever its post value is updated.
|
||||||
|
*
|
||||||
|
* This ensures that the new value will get sanitized and used the next time
|
||||||
|
* that <code>WP_Customize_Setting::_multidimensional_preview_filter()</code>
|
||||||
|
* is called for this setting.
|
||||||
|
*
|
||||||
|
* @since 4.4.0
|
||||||
|
* @access private
|
||||||
|
* @see WP_Customize_Manager::set_post_value()
|
||||||
|
* @see WP_Customize_Setting::_multidimensional_preview_filter()
|
||||||
|
*/
|
||||||
|
final public function _clear_aggregated_multidimensional_preview_applied_flag() {
|
||||||
|
unset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['preview_applied_instances'][ $this->id ] );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function to filter non-multidimensional theme mods and options.
|
* Callback function to filter non-multidimensional theme mods and options.
|
||||||
*
|
*
|
||||||
|
@ -369,13 +409,13 @@ class WP_Customize_Setting {
|
||||||
* the first setting previewed will be used to apply the values for the others.
|
* the first setting previewed will be used to apply the values for the others.
|
||||||
*
|
*
|
||||||
* @since 4.4.0
|
* @since 4.4.0
|
||||||
* @access public
|
* @access private
|
||||||
*
|
*
|
||||||
* @see WP_Customize_Setting::$aggregated_multidimensionals
|
* @see WP_Customize_Setting::$aggregated_multidimensionals
|
||||||
* @param mixed $original Original root value.
|
* @param mixed $original Original root value.
|
||||||
* @return mixed New or old value.
|
* @return mixed New or old value.
|
||||||
*/
|
*/
|
||||||
public function _multidimensional_preview_filter( $original ) {
|
final public function _multidimensional_preview_filter( $original ) {
|
||||||
if ( ! $this->is_current_blog_previewed() ) {
|
if ( ! $this->is_current_blog_previewed() ) {
|
||||||
return $original;
|
return $original;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1380,7 +1380,7 @@ final class WP_Customize_Widgets {
|
||||||
* in place from WP_Customize_Setting::preview() will use this value
|
* in place from WP_Customize_Setting::preview() will use this value
|
||||||
* instead of the default widget instance value (an empty array).
|
* instead of the default widget instance value (an empty array).
|
||||||
*/
|
*/
|
||||||
$this->manager->set_post_value( $setting_id, $instance );
|
$this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance ) );
|
||||||
|
|
||||||
// Obtain the widget control with the updated instance in place.
|
// Obtain the widget control with the updated instance in place.
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
|
@ -119,15 +119,6 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
|
||||||
*/
|
*/
|
||||||
public $original_nav_menu_term_id;
|
public $original_nav_menu_term_id;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not preview() was called.
|
|
||||||
*
|
|
||||||
* @since 4.3.0
|
|
||||||
* @access protected
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $is_previewed = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not update() was called.
|
* Whether or not update() was called.
|
||||||
*
|
*
|
||||||
|
|
|
@ -88,15 +88,6 @@ class WP_Customize_Nav_Menu_Setting extends WP_Customize_Setting {
|
||||||
*/
|
*/
|
||||||
public $previous_term_id;
|
public $previous_term_id;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not preview() was called.
|
|
||||||
*
|
|
||||||
* @since 4.3.0
|
|
||||||
* @access protected
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $is_previewed = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not update() was called.
|
* Whether or not update() was called.
|
||||||
*
|
*
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '4.4-beta4-35723';
|
$wp_version = '4.4-beta4-35724';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue