[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> class-wp-customize-setting.php (source)

   1  <?php
   2  /**
   3   * WordPress Customize Setting classes
   4   *
   5   * @package WordPress
   6   * @subpackage Customize
   7   * @since 3.4.0
   8   */
   9  
  10  /**
  11   * Customize Setting class.
  12   *
  13   * Handles saving and sanitizing of settings.
  14   *
  15   * @since 3.4.0
  16   * @link https://developer.wordpress.org/themes/customize-api
  17   *
  18   * @see WP_Customize_Manager
  19   */
  20  class WP_Customize_Setting {
  21      /**
  22       * Customizer bootstrap instance.
  23       *
  24       * @since 3.4.0
  25       * @var WP_Customize_Manager
  26       */
  27      public $manager;
  28  
  29      /**
  30       * Unique string identifier for the setting.
  31       *
  32       * @since 3.4.0
  33       * @var string
  34       */
  35      public $id;
  36  
  37      /**
  38       * Type of customize settings.
  39       *
  40       * @since 3.4.0
  41       * @var string
  42       */
  43      public $type = 'theme_mod';
  44  
  45      /**
  46       * Capability required to edit this setting.
  47       *
  48       * @since 3.4.0
  49       * @var string|array
  50       */
  51      public $capability = 'edit_theme_options';
  52  
  53      /**
  54       * Feature a theme is required to support to enable this setting.
  55       *
  56       * @since 3.4.0
  57       * @var string
  58       */
  59      public $theme_supports = '';
  60  
  61      /**
  62       * The default value for the setting.
  63       *
  64       * @since 3.4.0
  65       * @var string
  66       */
  67      public $default = '';
  68  
  69      /**
  70       * Options for rendering the live preview of changes in Customizer.
  71       *
  72       * Set this value to 'postMessage' to enable a custom JavaScript handler to render changes to this setting
  73       * as opposed to reloading the whole page.
  74       *
  75       * @since 3.4.0
  76       * @var string
  77       */
  78      public $transport = 'refresh';
  79  
  80      /**
  81       * Server-side validation callback for the setting's value.
  82       *
  83       * @since 4.6.0
  84       * @var callable
  85       */
  86      public $validate_callback = '';
  87  
  88      /**
  89       * Callback to filter a Customize setting value in un-slashed form.
  90       *
  91       * @since 3.4.0
  92       * @var callable
  93       */
  94      public $sanitize_callback = '';
  95  
  96      /**
  97       * Callback to convert a Customize PHP setting value to a value that is JSON serializable.
  98       *
  99       * @since 3.4.0
 100       * @var string
 101       */
 102      public $sanitize_js_callback = '';
 103  
 104      /**
 105       * Whether or not the setting is initially dirty when created.
 106       *
 107       * This is used to ensure that a setting will be sent from the pane to the
 108       * preview when loading the Customizer. Normally a setting only is synced to
 109       * the preview if it has been changed. This allows the setting to be sent
 110       * from the start.
 111       *
 112       * @since 4.2.0
 113       * @var bool
 114       */
 115      public $dirty = false;
 116  
 117      /**
 118       * ID Data.
 119       *
 120       * @since 3.4.0
 121       * @var array
 122       */
 123      protected $id_data = array();
 124  
 125      /**
 126       * Whether or not preview() was called.
 127       *
 128       * @since 4.4.0
 129       * @var bool
 130       */
 131      protected $is_previewed = false;
 132  
 133      /**
 134       * Cache of multidimensional values to improve performance.
 135       *
 136       * @since 4.4.0
 137       * @var array
 138       */
 139      protected static $aggregated_multidimensionals = array();
 140  
 141      /**
 142       * Whether the multidimensional setting is aggregated.
 143       *
 144       * @since 4.4.0
 145       * @var bool
 146       */
 147      protected $is_multidimensional_aggregated = false;
 148  
 149      /**
 150       * Constructor.
 151       *
 152       * Any supplied $args override class property defaults.
 153       *
 154       * @since 3.4.0
 155       *
 156       * @param WP_Customize_Manager $manager
 157       * @param string               $id      An specific ID of the setting. Can be a
 158       *                                      theme mod or option name.
 159       * @param array                $args    Setting arguments.
 160       */
 161  	public function __construct( $manager, $id, $args = array() ) {
 162          $keys = array_keys( get_object_vars( $this ) );
 163          foreach ( $keys as $key ) {
 164              if ( isset( $args[ $key ] ) ) {
 165                  $this->$key = $args[ $key ];
 166              }
 167          }
 168  
 169          $this->manager = $manager;
 170          $this->id      = $id;
 171  
 172          // Parse the ID for array keys.
 173          $this->id_data['keys'] = preg_split( '/\[/', str_replace( ']', '', $this->id ) );
 174          $this->id_data['base'] = array_shift( $this->id_data['keys'] );
 175  
 176          // Rebuild the ID.
 177          $this->id = $this->id_data['base'];
 178          if ( ! empty( $this->id_data['keys'] ) ) {
 179              $this->id .= '[' . implode( '][', $this->id_data['keys'] ) . ']';
 180          }
 181  
 182          if ( $this->validate_callback ) {
 183              add_filter( "customize_validate_{$this->id}", $this->validate_callback, 10, 3 );
 184          }
 185          if ( $this->sanitize_callback ) {
 186              add_filter( "customize_sanitize_{$this->id}", $this->sanitize_callback, 10, 2 );
 187          }
 188          if ( $this->sanitize_js_callback ) {
 189              add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 );
 190          }
 191  
 192          if ( 'option' === $this->type || 'theme_mod' === $this->type ) {
 193              // Other setting types can opt-in to aggregate multidimensional explicitly.
 194              $this->aggregate_multidimensional();
 195  
 196              // Allow option settings to indicate whether they should be autoloaded.
 197              if ( 'option' === $this->type && isset( $args['autoload'] ) ) {
 198                  self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'] = $args['autoload'];
 199              }
 200          }
 201      }
 202  
 203      /**
 204       * Get parsed ID data for multidimensional setting.
 205       *
 206       * @since 4.4.0
 207       *
 208       * @return array {
 209       *     ID data for multidimensional setting.
 210       *
 211       *     @type string $base ID base
 212       *     @type array  $keys Keys for multidimensional array.
 213       * }
 214       */
 215  	final public function id_data() {
 216          return $this->id_data;
 217      }
 218  
 219      /**
 220       * Set up the setting for aggregated multidimensional values.
 221       *
 222       * When a multidimensional setting gets aggregated, all of its preview and update
 223       * calls get combined into one call, greatly improving performance.
 224       *
 225       * @since 4.4.0
 226       */
 227  	protected function aggregate_multidimensional() {
 228          $id_base = $this->id_data['base'];
 229          if ( ! isset( self::$aggregated_multidimensionals[ $this->type ] ) ) {
 230              self::$aggregated_multidimensionals[ $this->type ] = array();
 231          }
 232          if ( ! isset( self::$aggregated_multidimensionals[ $this->type ][ $id_base ] ) ) {
 233              self::$aggregated_multidimensionals[ $this->type ][ $id_base ] = array(
 234                  'previewed_instances'       => array(), // Calling preview() will add the $setting to the array.
 235                  'preview_applied_instances' => array(), // Flags for which settings have had their values applied.
 236                  'root_value'                => $this->get_root_value( array() ), // Root value for initial state, manipulated by preview and update calls.
 237              );
 238          }
 239  
 240          if ( ! empty( $this->id_data['keys'] ) ) {
 241              // Note the preview-applied flag is cleared at priority 9 to ensure it is cleared before a deferred-preview runs.
 242              add_action( "customize_post_value_set_{$this->id}", array( $this, '_clear_aggregated_multidimensional_preview_applied_flag' ), 9 );
 243              $this->is_multidimensional_aggregated = true;
 244          }
 245      }
 246  
 247      /**
 248       * Reset `$aggregated_multidimensionals` static variable.
 249       *
 250       * This is intended only for use by unit tests.
 251       *
 252       * @since 4.5.0
 253       * @ignore
 254       */
 255  	static public function reset_aggregated_multidimensionals() {
 256          self::$aggregated_multidimensionals = array();
 257      }
 258  
 259      /**
 260       * The ID for the current site when the preview() method was called.
 261       *
 262       * @since 4.2.0
 263       * @var int
 264       */
 265      protected $_previewed_blog_id;
 266  
 267      /**
 268       * Return true if the current site is not the same as the previewed site.
 269       *
 270       * @since 4.2.0
 271       *
 272       * @return bool If preview() has been called.
 273       */
 274  	public function is_current_blog_previewed() {
 275          if ( ! isset( $this->_previewed_blog_id ) ) {
 276              return false;
 277          }
 278          return ( get_current_blog_id() === $this->_previewed_blog_id );
 279      }
 280  
 281      /**
 282       * Original non-previewed value stored by the preview method.
 283       *
 284       * @see WP_Customize_Setting::preview()
 285       * @since 4.1.1
 286       * @var mixed
 287       */
 288      protected $_original_value;
 289  
 290      /**
 291       * Add filters to supply the setting's value when accessed.
 292       *
 293       * If the setting already has a pre-existing value and there is no incoming
 294       * post value for the setting, then this method will short-circuit since
 295       * there is no change to preview.
 296       *
 297       * @since 3.4.0
 298       * @since 4.4.0 Added boolean return value.
 299       *
 300       * @return bool False when preview short-circuits due no change needing to be previewed.
 301       */
 302  	public function preview() {
 303          if ( ! isset( $this->_previewed_blog_id ) ) {
 304              $this->_previewed_blog_id = get_current_blog_id();
 305          }
 306  
 307          // Prevent re-previewing an already-previewed setting.
 308          if ( $this->is_previewed ) {
 309              return true;
 310          }
 311  
 312          $id_base                 = $this->id_data['base'];
 313          $is_multidimensional     = ! empty( $this->id_data['keys'] );
 314          $multidimensional_filter = array( $this, '_multidimensional_preview_filter' );
 315  
 316          /*
 317           * Check if the setting has a pre-existing value (an isset check),
 318           * and if doesn't have any incoming post value. If both checks are true,
 319           * then the preview short-circuits because there is nothing that needs
 320           * to be previewed.
 321           */
 322          $undefined     = new stdClass();
 323          $needs_preview = ( $undefined !== $this->post_value( $undefined ) );
 324          $value         = null;
 325  
 326          // Since no post value was defined, check if we have an initial value set.
 327          if ( ! $needs_preview ) {
 328              if ( $this->is_multidimensional_aggregated ) {
 329                  $root  = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
 330                  $value = $this->multidimensional_get( $root, $this->id_data['keys'], $undefined );
 331              } else {
 332                  $default       = $this->default;
 333                  $this->default = $undefined; // Temporarily set default to undefined so we can detect if existing value is set.
 334                  $value         = $this->value();
 335                  $this->default = $default;
 336              }
 337              $needs_preview = ( $undefined === $value ); // Because the default needs to be supplied.
 338          }
 339  
 340          // If the setting does not need previewing now, defer to when it has a value to preview.
 341          if ( ! $needs_preview ) {
 342              if ( ! has_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) ) ) {
 343                  add_action( "customize_post_value_set_{$this->id}", array( $this, 'preview' ) );
 344              }
 345              return false;
 346          }
 347  
 348          switch ( $this->type ) {
 349              case 'theme_mod':
 350                  if ( ! $is_multidimensional ) {
 351                      add_filter( "theme_mod_{$id_base}", array( $this, '_preview_filter' ) );
 352                  } else {
 353                      if ( empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] ) ) {
 354                          // Only add this filter once for this ID base.
 355                          add_filter( "theme_mod_{$id_base}", $multidimensional_filter );
 356                      }
 357                      self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'][ $this->id ] = $this;
 358                  }
 359                  break;
 360              case 'option':
 361                  if ( ! $is_multidimensional ) {
 362                      add_filter( "pre_option_{$id_base}", array( $this, '_preview_filter' ) );
 363                  } else {
 364                      if ( empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] ) ) {
 365                          // Only add these filters once for this ID base.
 366                          add_filter( "option_{$id_base}", $multidimensional_filter );
 367                          add_filter( "default_option_{$id_base}", $multidimensional_filter );
 368                      }
 369                      self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'][ $this->id ] = $this;
 370                  }
 371                  break;
 372              default:
 373                  /**
 374                   * Fires when the WP_Customize_Setting::preview() method is called for settings
 375                   * not handled as theme_mods or options.
 376                   *
 377                   * The dynamic portion of the hook name, `$this->id`, refers to the setting ID.
 378                   *
 379                   * @since 3.4.0
 380                   *
 381                   * @param WP_Customize_Setting $this WP_Customize_Setting instance.
 382                   */
 383                  do_action( "customize_preview_{$this->id}", $this );
 384  
 385                  /**
 386                   * Fires when the WP_Customize_Setting::preview() method is called for settings
 387                   * not handled as theme_mods or options.
 388                   *
 389                   * The dynamic portion of the hook name, `$this->type`, refers to the setting type.
 390                   *
 391                   * @since 4.1.0
 392                   *
 393                   * @param WP_Customize_Setting $this WP_Customize_Setting instance.
 394                   */
 395                  do_action( "customize_preview_{$this->type}", $this );
 396          }
 397  
 398          $this->is_previewed = true;
 399  
 400          return true;
 401      }
 402  
 403      /**
 404       * Clear out the previewed-applied flag for a multidimensional-aggregated value whenever its post value is updated.
 405       *
 406       * This ensures that the new value will get sanitized and used the next time
 407       * that `WP_Customize_Setting::_multidimensional_preview_filter()`
 408       * is called for this setting.
 409       *
 410       * @since 4.4.0
 411       *
 412       * @see WP_Customize_Manager::set_post_value()
 413       * @see WP_Customize_Setting::_multidimensional_preview_filter()
 414       */
 415      final public function _clear_aggregated_multidimensional_preview_applied_flag() {
 416          unset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['preview_applied_instances'][ $this->id ] );
 417      }
 418  
 419      /**
 420       * Callback function to filter non-multidimensional theme mods and options.
 421       *
 422       * If switch_to_blog() was called after the preview() method, and the current
 423       * site is now not the same site, then this method does a no-op and returns
 424       * the original value.
 425       *
 426       * @since 3.4.0
 427       *
 428       * @param mixed $original Old value.
 429       * @return mixed New or old value.
 430       */
 431  	public function _preview_filter( $original ) {
 432          if ( ! $this->is_current_blog_previewed() ) {
 433              return $original;
 434          }
 435  
 436          $undefined  = new stdClass(); // Symbol hack.
 437          $post_value = $this->post_value( $undefined );
 438          if ( $undefined !== $post_value ) {
 439              $value = $post_value;
 440          } else {
 441              /*
 442               * Note that we don't use $original here because preview() will
 443               * not add the filter in the first place if it has an initial value
 444               * and there is no post value.
 445               */
 446              $value = $this->default;
 447          }
 448          return $value;
 449      }
 450  
 451      /**
 452       * Callback function to filter multidimensional theme mods and options.
 453       *
 454       * For all multidimensional settings of a given type, the preview filter for
 455       * the first setting previewed will be used to apply the values for the others.
 456       *
 457       * @since 4.4.0
 458       *
 459       * @see WP_Customize_Setting::$aggregated_multidimensionals
 460       * @param mixed $original Original root value.
 461       * @return mixed New or old value.
 462       */
 463  	final public function _multidimensional_preview_filter( $original ) {
 464          if ( ! $this->is_current_blog_previewed() ) {
 465              return $original;
 466          }
 467  
 468          $id_base = $this->id_data['base'];
 469  
 470          // If no settings have been previewed yet (which should not be the case, since $this is), just pass through the original value.
 471          if ( empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] ) ) {
 472              return $original;
 473          }
 474  
 475          foreach ( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['previewed_instances'] as $previewed_setting ) {
 476              // Skip applying previewed value for any settings that have already been applied.
 477              if ( ! empty( self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['preview_applied_instances'][ $previewed_setting->id ] ) ) {
 478                  continue;
 479              }
 480  
 481              // Do the replacements of the posted/default sub value into the root value.
 482              $value = $previewed_setting->post_value( $previewed_setting->default );
 483              $root  = self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['root_value'];
 484              $root  = $previewed_setting->multidimensional_replace( $root, $previewed_setting->id_data['keys'], $value );
 485              self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['root_value'] = $root;
 486  
 487              // Mark this setting having been applied so that it will be skipped when the filter is called again.
 488              self::$aggregated_multidimensionals[ $previewed_setting->type ][ $id_base ]['preview_applied_instances'][ $previewed_setting->id ] = true;
 489          }
 490  
 491          return self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
 492      }
 493  
 494      /**
 495       * Checks user capabilities and theme supports, and then saves
 496       * the value of the setting.
 497       *
 498       * @since 3.4.0
 499       *
 500       * @return void|false False if cap check fails or value isn't set or is invalid.
 501       */
 502  	final public function save() {
 503          $value = $this->post_value();
 504  
 505          if ( ! $this->check_capabilities() || ! isset( $value ) ) {
 506              return false;
 507          }
 508  
 509          $id_base = $this->id_data['base'];
 510  
 511          /**
 512           * Fires when the WP_Customize_Setting::save() method is called.
 513           *
 514           * The dynamic portion of the hook name, `$id_base` refers to
 515           * the base slug of the setting name.
 516           *
 517           * @since 3.4.0
 518           *
 519           * @param WP_Customize_Setting $this WP_Customize_Setting instance.
 520           */
 521          do_action( "customize_save_{$id_base}", $this );
 522  
 523          $this->update( $value );
 524      }
 525  
 526      /**
 527       * Fetch and sanitize the $_POST value for the setting.
 528       *
 529       * During a save request prior to save, post_value() provides the new value while value() does not.
 530       *
 531       * @since 3.4.0
 532       *
 533       * @param mixed $default A default value which is used as a fallback. Default is null.
 534       * @return mixed The default value on failure, otherwise the sanitized and validated value.
 535       */
 536  	final public function post_value( $default = null ) {
 537          return $this->manager->post_value( $this, $default );
 538      }
 539  
 540      /**
 541       * Sanitize an input.
 542       *
 543       * @since 3.4.0
 544       *
 545       * @param string|array $value    The value to sanitize.
 546       * @return string|array|null|WP_Error Sanitized value, or `null`/`WP_Error` if invalid.
 547       */
 548  	public function sanitize( $value ) {
 549  
 550          /**
 551           * Filters a Customize setting value in un-slashed form.
 552           *
 553           * @since 3.4.0
 554           *
 555           * @param mixed                $value Value of the setting.
 556           * @param WP_Customize_Setting $this  WP_Customize_Setting instance.
 557           */
 558          return apply_filters( "customize_sanitize_{$this->id}", $value, $this );
 559      }
 560  
 561      /**
 562       * Validates an input.
 563       *
 564       * @since 4.6.0
 565       *
 566       * @see WP_REST_Request::has_valid_params()
 567       *
 568       * @param mixed $value Value to validate.
 569       * @return true|WP_Error True if the input was validated, otherwise WP_Error.
 570       */
 571  	public function validate( $value ) {
 572          if ( is_wp_error( $value ) ) {
 573              return $value;
 574          }
 575          if ( is_null( $value ) ) {
 576              return new WP_Error( 'invalid_value', __( 'Invalid value.' ) );
 577          }
 578  
 579          $validity = new WP_Error();
 580  
 581          /**
 582           * Validates a Customize setting value.
 583           *
 584           * Plugins should amend the `$validity` object via its `WP_Error::add()` method.
 585           *
 586           * The dynamic portion of the hook name, `$this->ID`, refers to the setting ID.
 587           *
 588           * @since 4.6.0
 589           *
 590           * @param WP_Error             $validity Filtered from `true` to `WP_Error` when invalid.
 591           * @param mixed                $value    Value of the setting.
 592           * @param WP_Customize_Setting $this     WP_Customize_Setting instance.
 593           */
 594          $validity = apply_filters( "customize_validate_{$this->id}", $validity, $value, $this );
 595  
 596          if ( is_wp_error( $validity ) && ! $validity->has_errors() ) {
 597              $validity = true;
 598          }
 599          return $validity;
 600      }
 601  
 602      /**
 603       * Get the root value for a setting, especially for multidimensional ones.
 604       *
 605       * @since 4.4.0
 606       *
 607       * @param mixed $default Value to return if root does not exist.
 608       * @return mixed
 609       */
 610  	protected function get_root_value( $default = null ) {
 611          $id_base = $this->id_data['base'];
 612          if ( 'option' === $this->type ) {
 613              return get_option( $id_base, $default );
 614          } elseif ( 'theme_mod' === $this->type ) {
 615              return get_theme_mod( $id_base, $default );
 616          } else {
 617              /*
 618               * Any WP_Customize_Setting subclass implementing aggregate multidimensional
 619               * will need to override this method to obtain the data from the appropriate
 620               * location.
 621               */
 622              return $default;
 623          }
 624      }
 625  
 626      /**
 627       * Set the root value for a setting, especially for multidimensional ones.
 628       *
 629       * @since 4.4.0
 630       *
 631       * @param mixed $value Value to set as root of multidimensional setting.
 632       * @return bool Whether the multidimensional root was updated successfully.
 633       */
 634  	protected function set_root_value( $value ) {
 635          $id_base = $this->id_data['base'];
 636          if ( 'option' === $this->type ) {
 637              $autoload = true;
 638              if ( isset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'] ) ) {
 639                  $autoload = self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'];
 640              }
 641              return update_option( $id_base, $value, $autoload );
 642          } elseif ( 'theme_mod' === $this->type ) {
 643              set_theme_mod( $id_base, $value );
 644              return true;
 645          } else {
 646              /*
 647               * Any WP_Customize_Setting subclass implementing aggregate multidimensional
 648               * will need to override this method to obtain the data from the appropriate
 649               * location.
 650               */
 651              return false;
 652          }
 653      }
 654  
 655      /**
 656       * Save the value of the setting, using the related API.
 657       *
 658       * @since 3.4.0
 659       *
 660       * @param mixed $value The value to update.
 661       * @return bool The result of saving the value.
 662       */
 663  	protected function update( $value ) {
 664          $id_base = $this->id_data['base'];
 665          if ( 'option' === $this->type || 'theme_mod' === $this->type ) {
 666              if ( ! $this->is_multidimensional_aggregated ) {
 667                  return $this->set_root_value( $value );
 668              } else {
 669                  $root = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
 670                  $root = $this->multidimensional_replace( $root, $this->id_data['keys'], $value );
 671                  self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'] = $root;
 672                  return $this->set_root_value( $root );
 673              }
 674          } else {
 675              /**
 676               * Fires when the WP_Customize_Setting::update() method is called for settings
 677               * not handled as theme_mods or options.
 678               *
 679               * The dynamic portion of the hook name, `$this->type`, refers to the type of setting.
 680               *
 681               * @since 3.4.0
 682               *
 683               * @param mixed                $value Value of the setting.
 684               * @param WP_Customize_Setting $this  WP_Customize_Setting instance.
 685               */
 686              do_action( "customize_update_{$this->type}", $value, $this );
 687  
 688              return has_action( "customize_update_{$this->type}" );
 689          }
 690      }
 691  
 692      /**
 693       * Deprecated method.
 694       *
 695       * @since 3.4.0
 696       * @deprecated 4.4.0 Deprecated in favor of update() method.
 697       */
 698  	protected function _update_theme_mod() {
 699          _deprecated_function( __METHOD__, '4.4.0', __CLASS__ . '::update()' );
 700      }
 701  
 702      /**
 703       * Deprecated method.
 704       *
 705       * @since 3.4.0
 706       * @deprecated 4.4.0 Deprecated in favor of update() method.
 707       */
 708  	protected function _update_option() {
 709          _deprecated_function( __METHOD__, '4.4.0', __CLASS__ . '::update()' );
 710      }
 711  
 712      /**
 713       * Fetch the value of the setting.
 714       *
 715       * @since 3.4.0
 716       *
 717       * @return mixed The value.
 718       */
 719  	public function value() {
 720          $id_base      = $this->id_data['base'];
 721          $is_core_type = ( 'option' === $this->type || 'theme_mod' === $this->type );
 722  
 723          if ( ! $is_core_type && ! $this->is_multidimensional_aggregated ) {
 724  
 725              // Use post value if previewed and a post value is present.
 726              if ( $this->is_previewed ) {
 727                  $value = $this->post_value( null );
 728                  if ( null !== $value ) {
 729                      return $value;
 730                  }
 731              }
 732  
 733              $value = $this->get_root_value( $this->default );
 734  
 735              /**
 736               * Filters a Customize setting value not handled as a theme_mod or option.
 737               *
 738               * The dynamic portion of the hook name, `$id_base`, refers to
 739               * the base slug of the setting name, initialized from `$this->id_data['base']`.
 740               *
 741               * For settings handled as theme_mods or options, see those corresponding
 742               * functions for available hooks.
 743               *
 744               * @since 3.4.0
 745               * @since 4.6.0 Added the `$this` setting instance as the second parameter.
 746               *
 747               * @param mixed                $default The setting default value. Default empty.
 748               * @param WP_Customize_Setting $this    The setting instance.
 749               */
 750              $value = apply_filters( "customize_value_{$id_base}", $value, $this );
 751          } elseif ( $this->is_multidimensional_aggregated ) {
 752              $root_value = self::$aggregated_multidimensionals[ $this->type ][ $id_base ]['root_value'];
 753              $value      = $this->multidimensional_get( $root_value, $this->id_data['keys'], $this->default );
 754  
 755              // Ensure that the post value is used if the setting is previewed, since preview filters aren't applying on cached $root_value.
 756              if ( $this->is_previewed ) {
 757                  $value = $this->post_value( $value );
 758              }
 759          } else {
 760              $value = $this->get_root_value( $this->default );
 761          }
 762          return $value;
 763      }
 764  
 765      /**
 766       * Sanitize the setting's value for use in JavaScript.
 767       *
 768       * @since 3.4.0
 769       *
 770       * @return mixed The requested escaped value.
 771       */
 772  	public function js_value() {
 773  
 774          /**
 775           * Filters a Customize setting value for use in JavaScript.
 776           *
 777           * The dynamic portion of the hook name, `$this->id`, refers to the setting ID.
 778           *
 779           * @since 3.4.0
 780           *
 781           * @param mixed                $value The setting value.
 782           * @param WP_Customize_Setting $this  WP_Customize_Setting instance.
 783           */
 784          $value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this );
 785  
 786          if ( is_string( $value ) ) {
 787              return html_entity_decode( $value, ENT_QUOTES, 'UTF-8' );
 788          }
 789  
 790          return $value;
 791      }
 792  
 793      /**
 794       * Retrieves the data to export to the client via JSON.
 795       *
 796       * @since 4.6.0
 797       *
 798       * @return array Array of parameters passed to JavaScript.
 799       */
 800  	public function json() {
 801          return array(
 802              'value'     => $this->js_value(),
 803              'transport' => $this->transport,
 804              'dirty'     => $this->dirty,
 805              'type'      => $this->type,
 806          );
 807      }
 808  
 809      /**
 810       * Validate user capabilities whether the theme supports the setting.
 811       *
 812       * @since 3.4.0
 813       *
 814       * @return bool False if theme doesn't support the setting or user can't change setting, otherwise true.
 815       */
 816  	final public function check_capabilities() {
 817          if ( $this->capability && ! current_user_can( $this->capability ) ) {
 818              return false;
 819          }
 820  
 821          if ( $this->theme_supports && ! current_theme_supports( ... (array) $this->theme_supports ) ) {
 822              return false;
 823          }
 824  
 825          return true;
 826      }
 827  
 828      /**
 829       * Multidimensional helper function.
 830       *
 831       * @since 3.4.0
 832       *
 833       * @param $root
 834       * @param $keys
 835       * @param bool $create Default is false.
 836       * @return array|void Keys are 'root', 'node', and 'key'.
 837       */
 838  	final protected function multidimensional( &$root, $keys, $create = false ) {
 839          if ( $create && empty( $root ) ) {
 840              $root = array();
 841          }
 842  
 843          if ( ! isset( $root ) || empty( $keys ) ) {
 844              return;
 845          }
 846  
 847          $last = array_pop( $keys );
 848          $node = &$root;
 849  
 850          foreach ( $keys as $key ) {
 851              if ( $create && ! isset( $node[ $key ] ) ) {
 852                  $node[ $key ] = array();
 853              }
 854  
 855              if ( ! is_array( $node ) || ! isset( $node[ $key ] ) ) {
 856                  return;
 857              }
 858  
 859              $node = &$node[ $key ];
 860          }
 861  
 862          if ( $create ) {
 863              if ( ! is_array( $node ) ) {
 864                  // account for an array overriding a string or object value
 865                  $node = array();
 866              }
 867              if ( ! isset( $node[ $last ] ) ) {
 868                  $node[ $last ] = array();
 869              }
 870          }
 871  
 872          if ( ! isset( $node[ $last ] ) ) {
 873              return;
 874          }
 875  
 876          return array(
 877              'root' => &$root,
 878              'node' => &$node,
 879              'key'  => $last,
 880          );
 881      }
 882  
 883      /**
 884       * Will attempt to replace a specific value in a multidimensional array.
 885       *
 886       * @since 3.4.0
 887       *
 888       * @param $root
 889       * @param $keys
 890       * @param mixed $value The value to update.
 891       * @return mixed
 892       */
 893  	final protected function multidimensional_replace( $root, $keys, $value ) {
 894          if ( ! isset( $value ) ) {
 895              return $root;
 896          } elseif ( empty( $keys ) ) { // If there are no keys, we're replacing the root.
 897              return $value;
 898          }
 899  
 900          $result = $this->multidimensional( $root, $keys, true );
 901  
 902          if ( isset( $result ) ) {
 903              $result['node'][ $result['key'] ] = $value;
 904          }
 905  
 906          return $root;
 907      }
 908  
 909      /**
 910       * Will attempt to fetch a specific value from a multidimensional array.
 911       *
 912       * @since 3.4.0
 913       *
 914       * @param $root
 915       * @param $keys
 916       * @param mixed $default A default value which is used as a fallback. Default is null.
 917       * @return mixed The requested value or the default value.
 918       */
 919  	final protected function multidimensional_get( $root, $keys, $default = null ) {
 920          if ( empty( $keys ) ) { // If there are no keys, test the root.
 921              return isset( $root ) ? $root : $default;
 922          }
 923  
 924          $result = $this->multidimensional( $root, $keys );
 925          return isset( $result ) ? $result['node'][ $result['key'] ] : $default;
 926      }
 927  
 928      /**
 929       * Will attempt to check if a specific value in a multidimensional array is set.
 930       *
 931       * @since 3.4.0
 932       *
 933       * @param $root
 934       * @param $keys
 935       * @return bool True if value is set, false if not.
 936       */
 937  	final protected function multidimensional_isset( $root, $keys ) {
 938          $result = $this->multidimensional_get( $root, $keys );
 939          return isset( $result );
 940      }
 941  }
 942  
 943  /**
 944   * WP_Customize_Filter_Setting class.
 945   */
 946  require_once ( ABSPATH . WPINC . '/customize/class-wp-customize-filter-setting.php' );
 947  
 948  /**
 949   * WP_Customize_Header_Image_Setting class.
 950   */
 951  require_once ( ABSPATH . WPINC . '/customize/class-wp-customize-header-image-setting.php' );
 952  
 953  /**
 954   * WP_Customize_Background_Image_Setting class.
 955   */
 956  require_once ( ABSPATH . WPINC . '/customize/class-wp-customize-background-image-setting.php' );
 957  
 958  /**
 959   * WP_Customize_Nav_Menu_Item_Setting class.
 960   */
 961  require_once ( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-item-setting.php' );
 962  
 963  /**
 964   * WP_Customize_Nav_Menu_Setting class.
 965   */
 966  require_once ( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-setting.php' );


Generated: Fri Jan 24 01:00:03 2020 Cross-referenced by PHPXref 0.7.1