: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$root = $previewed_setting->multidimensional_replace( $root, $previewed_setting->id_data['keys'], $value );
self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['root_value'] = $root;
// Mark this setting having been applied so that it will be skipped when the filter is called again.
self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['preview_applied_instances'][ $previewed_setting->id ] = true;
return self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
* Checks user capabilities and theme supports, and then saves
* the value of the setting.
* @return void|false Void on success, false if cap check fails
* or value isn't set or is invalid.
final public function save() {
$value = $this->post_value();
if ( ! $this->check_capabilities() || ! isset( $value ) ) {
$id_base = $this->id_data['base'];
* Fires when the WP_Customize_Setting::save() method is called.
* The dynamic portion of the hook name, `$id_base` refers to
* the base slug of the setting name.
* @param WP_Customize_Setting $setting WP_Customize_Setting instance.
do_action( "customize_save_{$id_base}", $this );
* Fetch and sanitize the $_POST value for the setting.
* During a save request prior to save, post_value() provides the new value while value() does not.
* @param mixed $default_value A default value which is used as a fallback. Default null.
* @return mixed The default value on failure, otherwise the sanitized and validated value.
final public function post_value( $default_value = null ) {
return $this->manager->post_value( $this, $default_value );
* @param string|array $value The value to sanitize.
* @return string|array|null|WP_Error Sanitized value, or `null`/`WP_Error` if invalid.
public function sanitize( $value ) {
* Filters a Customize setting value in un-slashed form.
* @param mixed $value Value of the setting.
* @param WP_Customize_Setting $setting WP_Customize_Setting instance.
return apply_filters( "customize_sanitize_{$this->id}", $value, $this );
* @see WP_REST_Request::has_valid_params()
* @param mixed $value Value to validate.
* @return true|WP_Error True if the input was validated, otherwise WP_Error.
public function validate( $value ) {
if ( is_wp_error( $value ) ) {
if ( is_null( $value ) ) {
return new WP_Error( 'invalid_value', __( 'Invalid value.' ) );
$validity = new WP_Error();
* Validates a Customize setting value.
* Plugins should amend the `$validity` object via its `WP_Error::add()` method.
* The dynamic portion of the hook name, `$this->ID`, refers to the setting ID.
* @param WP_Error $validity Filtered from `true` to `WP_Error` when invalid.
* @param mixed $value Value of the setting.
* @param WP_Customize_Setting $setting WP_Customize_Setting instance.
$validity = apply_filters( "customize_validate_{$this->id}", $validity, $value, $this );
if ( is_wp_error( $validity ) && ! $validity->has_errors() ) {
* Get the root value for a setting, especially for multidimensional ones.
* @param mixed $default_value Value to return if root does not exist.
protected function get_root_value( $default_value = null ) {
$id_base = $this->id_data['base'];
if ( 'option' === $this->type ) {
return get_option( $id_base, $default_value );
} elseif ( 'theme_mod' === $this->type ) {
return get_theme_mod( $id_base, $default_value );
* Any WP_Customize_Setting subclass implementing aggregate multidimensional
* will need to override this method to obtain the data from the appropriate
* Set the root value for a setting, especially for multidimensional ones.
* @param mixed $value Value to set as root of multidimensional setting.
* @return bool Whether the multidimensional root was updated successfully.
protected function set_root_value( $value ) {
$id_base = $this->id_data['base'];
if ( 'option' === $this->type ) {
if ( isset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'] ) ) {
$autoload = self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'];
return update_option( $id_base, $value, $autoload );
} elseif ( 'theme_mod' === $this->type ) {
set_theme_mod( $id_base, $value );
* Any WP_Customize_Setting subclass implementing aggregate multidimensional
* will need to override this method to obtain the data from the appropriate
* Save the value of the setting, using the related API.
* @param mixed $value The value to update.
* @return bool The result of saving the value.
protected function update( $value ) {
$id_base = $this->id_data['base'];
if ( 'option' === $this->type || 'theme_mod' === $this->type ) {
if ( ! $this->is_multidimensional_aggregated ) {
return $this->set_root_value( $value );
$root = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
$root = $this->multidimensional_replace( $root, $this->id_data['keys'], $value );
self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'] = $root;
return $this->set_root_value( $root );
* Fires when the WP_Customize_Setting::update() method is called for settings
* not handled as theme_mods or options.
* The dynamic portion of the hook name, `$this->type`, refers to the type of setting.
* @param mixed $value Value of the setting.
* @param WP_Customize_Setting $setting WP_Customize_Setting instance.
do_action( "customize_update_{$this->type}", $value, $this );
return has_action( "customize_update_{$this->type}" );
* @deprecated 4.4.0 Deprecated in favor of update() method.
protected function _update_theme_mod() {
_deprecated_function( __METHOD__, '4.4.0', __CLASS__ . '::update()' );
* @deprecated 4.4.0 Deprecated in favor of update() method.
protected function _update_option() {
_deprecated_function( __METHOD__, '4.4.0', __CLASS__ . '::update()' );
* Fetch the value of the setting.
* @return mixed The value.
public function value() {
$id_base = $this->id_data['base'];
$is_core_type = ( 'option' === $this->type || 'theme_mod' === $this->type );
if ( ! $is_core_type && ! $this->is_multidimensional_aggregated ) {
// Use post value if previewed and a post value is present.
if ( $this->is_previewed ) {
$value = $this->post_value( null );
$value = $this->get_root_value( $this->default );
* Filters a Customize setting value not handled as a theme_mod or option.
* The dynamic portion of the hook name, `$id_base`, refers to
* the base slug of the setting name, initialized from `$this->id_data['base']`.
* For settings handled as theme_mods or options, see those corresponding
* functions for available hooks.
* @since 4.6.0 Added the `$this` setting instance as the second parameter.
* @param mixed $default_value The setting default value. Default empty.
* @param WP_Customize_Setting $setting The setting instance.
$value = apply_filters( "customize_value_{$id_base}", $value, $this );
} elseif ( $this->is_multidimensional_aggregated ) {
$root_value = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
$value = $this->multidimensional_get( $root_value, $this->id_data['keys'], $this->default );
// Ensure that the post value is used if the setting is previewed, since preview filters aren't applying on cached $root_value.
if ( $this->is_previewed ) {
$value = $this->post_value( $value );
$value = $this->get_root_value( $this->default );
* Sanitize the setting's value for use in JavaScript.
* @return mixed The requested escaped value.
public function js_value() {
* Filters a Customize setting value for use in JavaScript.
* The dynamic portion of the hook name, `$this->id`, refers to the setting ID.
* @param mixed $value The setting value.
* @param WP_Customize_Setting $setting WP_Customize_Setting instance.
$value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
if ( is_string( $value ) ) {
return html_entity_decode( $value, ENT_QUOTES, 'UTF-8' );
* Retrieves the data to export to the client via JSON.
* @return array Array of parameters passed to JavaScript.
'value' => $this->js_value(),
'transport' => $this->transport,
* Validate user capabilities whether the theme supports the setting.
* @return bool False if theme doesn't support the setting or user can't change setting, otherwise true.
final public function check_capabilities() {
if ( $this->capability && ! current_user_can( $this->capability ) ) {
if ( $this->theme_supports && ! current_theme_supports( ...(array) $this->theme_supports ) ) {
* Multidimensional helper function.
* @param bool $create Default false.
* @return array|void Keys are 'root', 'node', and 'key'.
final protected function multidimensional( &$root, $keys, $create = false ) {
if ( $create && empty( $root ) ) {
if ( ! isset( $root ) || empty( $keys ) ) {
$last = array_pop( $keys );
foreach ( $keys as $key ) {
if ( $create && ! isset( $node[ $key ] ) ) {
if ( ! is_array( $node ) || ! isset( $node[ $key ] ) ) {
if ( ! is_array( $node ) ) {
// Account for an array overriding a string or object value.
if ( ! isset( $node[ $last ] ) ) {
$node[ $last ] = array();
if ( ! isset( $node[ $last ] ) ) {
* Will attempt to replace a specific value in a multidimensional array.
* @param mixed $value The value to update.
final protected function multidimensional_replace( $root, $keys, $value ) {
if ( ! isset( $value ) ) {
} elseif ( empty( $keys ) ) { // If there are no keys, we're replacing the root.
$result = $this->multidimensional( $root, $keys, true );
if ( isset( $result ) ) {
$result['node'][ $result['key'] ] = $value;
* Will attempt to fetch a specific value from a multidimensional array.
* @param mixed $default_value A default value which is used as a fallback. Default null.
* @return mixed The requested value or the default value.
final protected function multidimensional_get( $root, $keys, $default_value = null ) {
if ( empty( $keys ) ) { // If there are no keys, test the root.
return isset( $root ) ? $root : $default_value;
$result = $this->multidimensional( $root, $keys );
return isset( $result ) ? $result['node'][ $result['key'] ] : $default_value;
* Will attempt to check if a specific value in a multidimensional array is set.
* @return bool True if value is set, false if not.
final protected function multidimensional_isset( $root, $keys ) {
$result = $this->multidimensional_get( $root, $keys );
* WP_Customize_Filter_Setting class.
require_once ABSPATH . WPINC . '/customize/class-wp-customize-filter-setting.php';
* WP_Customize_Header_Image_Setting class.
require_once ABSPATH . WPINC . '/customize/class-wp-customize-header-image-setting.php';
* WP_Customize_Background_Image_Setting class.
require_once ABSPATH . WPINC . '/customize/class-wp-customize-background-image-setting.php';
* WP_Customize_Nav_Menu_Item_Setting class.
require_once ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-setting.php';
* WP_Customize_Nav_Menu_Setting class.
require_once ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-setting.php';