diff --git a/wp-includes/class-wp-customize-manager.php b/wp-includes/class-wp-customize-manager.php index b695271d61..4947d274b6 100644 --- a/wp-includes/class-wp-customize-manager.php +++ b/wp-includes/class-wp-customize-manager.php @@ -63,9 +63,9 @@ final class WP_Customize_Manager { protected $registered_control_types = array(); /** - * $_POST values for Customize Settings. + * Unsanitized values for Customize Settings parsed from $_POST['customized']. * - * @var array + * @var array|false */ private $_post_values; @@ -75,11 +75,11 @@ final class WP_Customize_Manager { * @since 3.4.0 */ public function __construct() { - require( ABSPATH . WPINC . '/class-wp-customize-setting.php' ); - require( ABSPATH . WPINC . '/class-wp-customize-panel.php' ); - require( ABSPATH . WPINC . '/class-wp-customize-section.php' ); - require( ABSPATH . WPINC . '/class-wp-customize-control.php' ); - require( ABSPATH . WPINC . '/class-wp-customize-widgets.php' ); + require_once( ABSPATH . WPINC . '/class-wp-customize-setting.php' ); + require_once( ABSPATH . WPINC . '/class-wp-customize-panel.php' ); + require_once( ABSPATH . WPINC . '/class-wp-customize-section.php' ); + require_once( ABSPATH . WPINC . '/class-wp-customize-control.php' ); + require_once( ABSPATH . WPINC . '/class-wp-customize-widgets.php' ); $this->widgets = new WP_Customize_Widgets( $this ); @@ -399,23 +399,45 @@ final class WP_Customize_Manager { } /** - * Decode the $_POST['customized'] values for a specific Customize Setting. + * Parse the incoming $_POST['customized'] JSON data and store the unsanitized + * settings for subsequent post_value() lookups. + * + * @since 4.1.1 + * + * @return array + */ + public function unsanitized_post_values() { + if ( ! isset( $this->_post_values ) ) { + if ( isset( $_POST['customized'] ) ) { + $this->_post_values = json_decode( wp_unslash( $_POST['customized'] ), true ); + } + if ( empty( $this->_post_values ) ) { // if not isset or of JSON error + $this->_post_values = false; + } + } + if ( empty( $this->_post_values ) ) { + return array(); + } else { + return $this->_post_values; + } + } + + /** + * Return the sanitized value for a given setting from the request's POST data. * * @since 3.4.0 * * @param WP_Customize_Setting $setting A WP_Customize_Setting derived object - * @return string $post_value Sanitized value + * @param mixed $default value returned $setting has no post value (added in 4.2.0). + * @return string|mixed $post_value Sanitized value or the $default provided */ - public function post_value( $setting ) { - if ( ! isset( $this->_post_values ) ) { - if ( isset( $_POST['customized'] ) ) - $this->_post_values = json_decode( wp_unslash( $_POST['customized'] ), true ); - else - $this->_post_values = false; + public function post_value( $setting, $default = null ) { + $post_values = $this->unsanitized_post_values(); + if ( array_key_exists( $setting->id, $post_values ) ) { + return $setting->sanitize( $post_values[ $setting->id ] ); + } else { + return $default; } - - if ( isset( $this->_post_values[ $setting->id ] ) ) - return $setting->sanitize( $this->_post_values[ $setting->id ] ); } /** diff --git a/wp-includes/class-wp-customize-setting.php b/wp-includes/class-wp-customize-setting.php index 7a7be45efa..6cbaf3db62 100644 --- a/wp-includes/class-wp-customize-setting.php +++ b/wp-includes/class-wp-customize-setting.php @@ -100,12 +100,18 @@ class WP_Customize_Setting { add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 ); } + protected $_original_value; + /** * Handle previewing the setting. * * @since 3.4.0 */ public function preview() { + if ( ! isset( $this->_original_value ) ) { + $this->_original_value = $this->value(); + } + switch( $this->type ) { case 'theme_mod' : add_filter( 'theme_mod_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) ); @@ -156,7 +162,15 @@ class WP_Customize_Setting { * @return mixed New or old value. */ public function _preview_filter( $original ) { - return $this->multidimensional_replace( $original, $this->id_data[ 'keys' ], $this->post_value() ); + $undefined = new stdClass(); // symbol hack + $post_value = $this->manager->post_value( $this, $undefined ); + if ( $undefined === $post_value ) { + $value = $this->_original_value; + } else { + $value = $post_value; + } + + return $this->multidimensional_replace( $original, $this->id_data['keys'], $value ); } /** @@ -422,8 +436,15 @@ class WP_Customize_Setting { $node = &$node[ $key ]; } - if ( $create && ! isset( $node[ $last ] ) ) - $node[ $last ] = array(); + if ( $create ) { + if ( ! is_array( $node ) ) { + // account for an array overriding a string or object value + $node = array(); + } + if ( ! isset( $node[ $last ] ) ) { + $node[ $last ] = array(); + } + } if ( ! isset( $node[ $last ] ) ) return; diff --git a/wp-includes/version.php b/wp-includes/version.php index de1c79562e..ccd8f97f90 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.2-alpha-31328'; +$wp_version = '4.2-alpha-31329'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.