[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

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


Generated: Wed Oct 23 08:20:01 2019 Cross-referenced by PHPXref 0.7