[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> option.php (source)

   1  <?php
   2  /**
   3   * Option API
   4   *
   5   * @package WordPress
   6   * @subpackage Option
   7   */
   8  
   9  /**
  10   * Retrieves an option value based on an option name.
  11   *
  12   * If the option does not exist or does not have a value, then the return value
  13   * will be false. This is useful to check whether you need to install an option
  14   * and is commonly used during installation of plugin options and to test
  15   * whether upgrading is required.
  16   *
  17   * If the option was serialized then it will be unserialized when it is returned.
  18   *
  19   * Any scalar values will be returned as strings. You may coerce the return type of
  20   * a given option by registering an {@see 'option_$option'} filter callback.
  21   *
  22   * @since 1.5.0
  23   *
  24   * @global wpdb $wpdb WordPress database abstraction object.
  25   *
  26   * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
  27   * @param mixed  $default Optional. Default value to return if the option does not exist.
  28   * @return mixed Value set for the option.
  29   */
  30  function get_option( $option, $default = false ) {
  31      global $wpdb;
  32  
  33      $option = trim( $option );
  34      if ( empty( $option ) ) {
  35          return false;
  36      }
  37  
  38      /**
  39       * Filters the value of an existing option before it is retrieved.
  40       *
  41       * The dynamic portion of the hook name, `$option`, refers to the option name.
  42       *
  43       * Passing a truthy value to the filter will short-circuit retrieving
  44       * the option value, returning the passed value instead.
  45       *
  46       * @since 1.5.0
  47       * @since 4.4.0 The `$option` parameter was added.
  48       * @since 4.9.0 The `$default` parameter was added.
  49       *
  50       * @param bool|mixed $pre_option The value to return instead of the option value. This differs from
  51       *                               `$default`, which is used as the fallback value in the event the option
  52       *                               doesn't exist elsewhere in get_option(). Default false (to skip past the
  53       *                               short-circuit).
  54       * @param string     $option     Option name.
  55       * @param mixed      $default    The fallback value to return if the option does not exist.
  56       *                               Default is false.
  57       */
  58      $pre = apply_filters( "pre_option_{$option}", false, $option, $default );
  59  
  60      if ( false !== $pre ) {
  61          return $pre;
  62      }
  63  
  64      if ( defined( 'WP_SETUP_CONFIG' ) ) {
  65          return false;
  66      }
  67  
  68      // Distinguish between `false` as a default, and not passing one.
  69      $passed_default = func_num_args() > 1;
  70  
  71      if ( ! wp_installing() ) {
  72          // Prevent non-existent options from triggering multiple queries.
  73          $notoptions = wp_cache_get( 'notoptions', 'options' );
  74          if ( isset( $notoptions[ $option ] ) ) {
  75              /**
  76               * Filters the default value for an option.
  77               *
  78               * The dynamic portion of the hook name, `$option`, refers to the option name.
  79               *
  80               * @since 3.4.0
  81               * @since 4.4.0 The `$option` parameter was added.
  82               * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value.
  83               *
  84               * @param mixed  $default The default value to return if the option does not exist
  85               *                        in the database.
  86               * @param string $option  Option name.
  87               * @param bool   $passed_default Was `get_option()` passed a default value?
  88               */
  89              return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
  90          }
  91  
  92          $alloptions = wp_load_alloptions();
  93  
  94          if ( isset( $alloptions[ $option ] ) ) {
  95              $value = $alloptions[ $option ];
  96          } else {
  97              $value = wp_cache_get( $option, 'options' );
  98  
  99              if ( false === $value ) {
 100                  $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 101  
 102                  // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
 103                  if ( is_object( $row ) ) {
 104                      $value = $row->option_value;
 105                      wp_cache_add( $option, $value, 'options' );
 106                  } else { // Option does not exist, so we must cache its non-existence.
 107                      if ( ! is_array( $notoptions ) ) {
 108                          $notoptions = array();
 109                      }
 110                      $notoptions[ $option ] = true;
 111                      wp_cache_set( 'notoptions', $notoptions, 'options' );
 112  
 113                      /** This filter is documented in wp-includes/option.php */
 114                      return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
 115                  }
 116              }
 117          }
 118      } else {
 119          $suppress = $wpdb->suppress_errors();
 120          $row      = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 121          $wpdb->suppress_errors( $suppress );
 122          if ( is_object( $row ) ) {
 123              $value = $row->option_value;
 124          } else {
 125              /** This filter is documented in wp-includes/option.php */
 126              return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
 127          }
 128      }
 129  
 130      // If home is not set, use siteurl.
 131      if ( 'home' === $option && '' === $value ) {
 132          return get_option( 'siteurl' );
 133      }
 134  
 135      if ( in_array( $option, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) {
 136          $value = untrailingslashit( $value );
 137      }
 138  
 139      /**
 140       * Filters the value of an existing option.
 141       *
 142       * The dynamic portion of the hook name, `$option`, refers to the option name.
 143       *
 144       * @since 1.5.0 As 'option_' . $setting
 145       * @since 3.0.0
 146       * @since 4.4.0 The `$option` parameter was added.
 147       *
 148       * @param mixed  $value  Value of the option. If stored serialized, it will be
 149       *                       unserialized prior to being returned.
 150       * @param string $option Option name.
 151       */
 152      return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
 153  }
 154  
 155  /**
 156   * Protects WordPress special option from being modified.
 157   *
 158   * Will die if $option is in protected list. Protected options are 'alloptions'
 159   * and 'notoptions' options.
 160   *
 161   * @since 2.2.0
 162   *
 163   * @param string $option Option name.
 164   */
 165  function wp_protect_special_option( $option ) {
 166      if ( 'alloptions' === $option || 'notoptions' === $option ) {
 167          wp_die(
 168              sprintf(
 169                  /* translators: %s: Option name. */
 170                  __( '%s is a protected WP option and may not be modified' ),
 171                  esc_html( $option )
 172              )
 173          );
 174      }
 175  }
 176  
 177  /**
 178   * Prints option value after sanitizing for forms.
 179   *
 180   * @since 1.5.0
 181   *
 182   * @param string $option Option name.
 183   */
 184  function form_option( $option ) {
 185      echo esc_attr( get_option( $option ) );
 186  }
 187  
 188  /**
 189   * Loads and caches all autoloaded options, if available or all options.
 190   *
 191   * @since 2.2.0
 192   * @since 5.3.1 The `$force_cache` parameter was added.
 193   *
 194   * @global wpdb $wpdb WordPress database abstraction object.
 195   *
 196   * @param bool $force_cache Optional. Whether to force an update of the local cache
 197   *                          from the persistent cache. Default false.
 198   * @return array List of all options.
 199   */
 200  function wp_load_alloptions( $force_cache = false ) {
 201      global $wpdb;
 202  
 203      if ( ! wp_installing() || ! is_multisite() ) {
 204          $alloptions = wp_cache_get( 'alloptions', 'options', $force_cache );
 205      } else {
 206          $alloptions = false;
 207      }
 208  
 209      if ( ! $alloptions ) {
 210          $suppress      = $wpdb->suppress_errors();
 211          $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" );
 212          if ( ! $alloptions_db ) {
 213              $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 214          }
 215          $wpdb->suppress_errors( $suppress );
 216  
 217          $alloptions = array();
 218          foreach ( (array) $alloptions_db as $o ) {
 219              $alloptions[ $o->option_name ] = $o->option_value;
 220          }
 221  
 222          if ( ! wp_installing() || ! is_multisite() ) {
 223              /**
 224               * Filters all options before caching them.
 225               *
 226               * @since 4.9.0
 227               *
 228               * @param array $alloptions Array with all options.
 229               */
 230              $alloptions = apply_filters( 'pre_cache_alloptions', $alloptions );
 231              wp_cache_add( 'alloptions', $alloptions, 'options' );
 232          }
 233      }
 234  
 235      /**
 236       * Filters all options after retrieving them.
 237       *
 238       * @since 4.9.0
 239       *
 240       * @param array $alloptions Array with all options.
 241       */
 242      return apply_filters( 'alloptions', $alloptions );
 243  }
 244  
 245  /**
 246   * Loads and caches certain often requested site options if is_multisite() and a persistent cache is not being used.
 247   *
 248   * @since 3.0.0
 249   *
 250   * @global wpdb $wpdb WordPress database abstraction object.
 251   *
 252   * @param int $network_id Optional site ID for which to query the options. Defaults to the current site.
 253   */
 254  function wp_load_core_site_options( $network_id = null ) {
 255      global $wpdb;
 256  
 257      if ( ! is_multisite() || wp_using_ext_object_cache() || wp_installing() ) {
 258          return;
 259      }
 260  
 261      if ( empty( $network_id ) ) {
 262          $network_id = get_current_network_id();
 263      }
 264  
 265      $core_options = array( 'site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'can_compress_scripts', 'global_terms_enabled', 'ms_files_rewriting' );
 266  
 267      $core_options_in = "'" . implode( "', '", $core_options ) . "'";
 268      $options         = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $network_id ) );
 269  
 270      foreach ( $options as $option ) {
 271          $key                = $option->meta_key;
 272          $cache_key          = "{$network_id}:$key";
 273          $option->meta_value = maybe_unserialize( $option->meta_value );
 274  
 275          wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
 276      }
 277  }
 278  
 279  /**
 280   * Updates the value of an option that was already added.
 281   *
 282   * You do not need to serialize values. If the value needs to be serialized,
 283   * then it will be serialized before it is inserted into the database.
 284   * Remember, resources cannot be serialized or added as an option.
 285   *
 286   * If the option does not exist, it will be created.
 287  
 288   * This function is designed to work with or without a logged-in user. In terms of security,
 289   * plugin developers should check the current user's capabilities before updating any options.
 290   *
 291   * @since 1.0.0
 292   * @since 4.2.0 The `$autoload` parameter was added.
 293   *
 294   * @global wpdb $wpdb WordPress database abstraction object.
 295   *
 296   * @param string      $option   Option name. Expected to not be SQL-escaped.
 297   * @param mixed       $value    Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
 298   * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
 299   *                              `$autoload` can only be updated using `update_option()` if `$value` is also changed.
 300   *                              Accepts 'yes'|true to enable or 'no'|false to disable. For non-existent options,
 301   *                              the default value is 'yes'. Default null.
 302   * @return bool False if value was not updated and true if value was updated.
 303   */
 304  function update_option( $option, $value, $autoload = null ) {
 305      global $wpdb;
 306  
 307      $option = trim( $option );
 308      if ( empty( $option ) ) {
 309          return false;
 310      }
 311  
 312      wp_protect_special_option( $option );
 313  
 314      if ( is_object( $value ) ) {
 315          $value = clone $value;
 316      }
 317  
 318      $value     = sanitize_option( $option, $value );
 319      $old_value = get_option( $option );
 320  
 321      /**
 322       * Filters a specific option before its value is (maybe) serialized and updated.
 323       *
 324       * The dynamic portion of the hook name, `$option`, refers to the option name.
 325       *
 326       * @since 2.6.0
 327       * @since 4.4.0 The `$option` parameter was added.
 328       *
 329       * @param mixed  $value     The new, unserialized option value.
 330       * @param mixed  $old_value The old option value.
 331       * @param string $option    Option name.
 332       */
 333      $value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
 334  
 335      /**
 336       * Filters an option before its value is (maybe) serialized and updated.
 337       *
 338       * @since 3.9.0
 339       *
 340       * @param mixed  $value     The new, unserialized option value.
 341       * @param string $option    Name of the option.
 342       * @param mixed  $old_value The old option value.
 343       */
 344      $value = apply_filters( 'pre_update_option', $value, $option, $old_value );
 345  
 346      /*
 347       * If the new and old values are the same, no need to update.
 348       *
 349       * Unserialized values will be adequate in most cases. If the unserialized
 350       * data differs, the (maybe) serialized data is checked to avoid
 351       * unnecessary database calls for otherwise identical object instances.
 352       *
 353       * See https://core.trac.wordpress.org/ticket/38903
 354       */
 355      if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
 356          return false;
 357      }
 358  
 359      /** This filter is documented in wp-includes/option.php */
 360      if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
 361          // Default setting for new options is 'yes'.
 362          if ( null === $autoload ) {
 363              $autoload = 'yes';
 364          }
 365  
 366          return add_option( $option, $value, '', $autoload );
 367      }
 368  
 369      $serialized_value = maybe_serialize( $value );
 370  
 371      /**
 372       * Fires immediately before an option value is updated.
 373       *
 374       * @since 2.9.0
 375       *
 376       * @param string $option    Name of the option to update.
 377       * @param mixed  $old_value The old option value.
 378       * @param mixed  $value     The new option value.
 379       */
 380      do_action( 'update_option', $option, $old_value, $value );
 381  
 382      $update_args = array(
 383          'option_value' => $serialized_value,
 384      );
 385  
 386      if ( null !== $autoload ) {
 387          $update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
 388      }
 389  
 390      $result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
 391      if ( ! $result ) {
 392          return false;
 393      }
 394  
 395      $notoptions = wp_cache_get( 'notoptions', 'options' );
 396      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
 397          unset( $notoptions[ $option ] );
 398          wp_cache_set( 'notoptions', $notoptions, 'options' );
 399      }
 400  
 401      if ( ! wp_installing() ) {
 402          $alloptions = wp_load_alloptions( true );
 403          if ( isset( $alloptions[ $option ] ) ) {
 404              $alloptions[ $option ] = $serialized_value;
 405              wp_cache_set( 'alloptions', $alloptions, 'options' );
 406          } else {
 407              wp_cache_set( $option, $serialized_value, 'options' );
 408          }
 409      }
 410  
 411      /**
 412       * Fires after the value of a specific option has been successfully updated.
 413       *
 414       * The dynamic portion of the hook name, `$option`, refers to the option name.
 415       *
 416       * @since 2.0.1
 417       * @since 4.4.0 The `$option` parameter was added.
 418       *
 419       * @param mixed  $old_value The old option value.
 420       * @param mixed  $value     The new option value.
 421       * @param string $option    Option name.
 422       */
 423      do_action( "update_option_{$option}", $old_value, $value, $option );
 424  
 425      /**
 426       * Fires after the value of an option has been successfully updated.
 427       *
 428       * @since 2.9.0
 429       *
 430       * @param string $option    Name of the updated option.
 431       * @param mixed  $old_value The old option value.
 432       * @param mixed  $value     The new option value.
 433       */
 434      do_action( 'updated_option', $option, $old_value, $value );
 435      return true;
 436  }
 437  
 438  /**
 439   * Adds a new option.
 440   *
 441   * You do not need to serialize values. If the value needs to be serialized,
 442   * then it will be serialized before it is inserted into the database.
 443   * Remember, resources cannot be serialized or added as an option.
 444   *
 445   * You can create options without values and then update the values later.
 446   * Existing options will not be updated and checks are performed to ensure that you
 447   * aren't adding a protected WordPress option. Care should be taken to not name
 448   * options the same as the ones which are protected.
 449   *
 450   * @since 1.0.0
 451   *
 452   * @global wpdb $wpdb WordPress database abstraction object.
 453   *
 454   * @param string         $option      Name of option to add. Expected to not be SQL-escaped.
 455   * @param mixed          $value       Optional. Option value. Must be serializable if non-scalar.
 456   *                                    Expected to not be SQL-escaped.
 457   * @param string         $deprecated  Optional. Description. Not used anymore.
 458   * @param string|bool    $autoload    Optional. Whether to load the option when WordPress starts up.
 459   *                                    Default is enabled. Accepts 'no' to disable for legacy reasons.
 460   * @return bool False if option was not added and true if option was added.
 461   */
 462  function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
 463      global $wpdb;
 464  
 465      if ( ! empty( $deprecated ) ) {
 466          _deprecated_argument( __FUNCTION__, '2.3.0' );
 467      }
 468  
 469      $option = trim( $option );
 470      if ( empty( $option ) ) {
 471          return false;
 472      }
 473  
 474      wp_protect_special_option( $option );
 475  
 476      if ( is_object( $value ) ) {
 477          $value = clone $value;
 478      }
 479  
 480      $value = sanitize_option( $option, $value );
 481  
 482      // Make sure the option doesn't already exist.
 483      // We can check the 'notoptions' cache before we ask for a DB query.
 484      $notoptions = wp_cache_get( 'notoptions', 'options' );
 485      if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
 486          /** This filter is documented in wp-includes/option.php */
 487          if ( apply_filters( "default_option_{$option}", false, $option, false ) !== get_option( $option ) ) {
 488              return false;
 489          }
 490      }
 491  
 492      $serialized_value = maybe_serialize( $value );
 493      $autoload         = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
 494  
 495      /**
 496       * Fires before an option is added.
 497       *
 498       * @since 2.9.0
 499       *
 500       * @param string $option Name of the option to add.
 501       * @param mixed  $value  Value of the option.
 502       */
 503      do_action( 'add_option', $option, $value );
 504  
 505      $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) );
 506      if ( ! $result ) {
 507          return false;
 508      }
 509  
 510      if ( ! wp_installing() ) {
 511          if ( 'yes' === $autoload ) {
 512              $alloptions            = wp_load_alloptions( true );
 513              $alloptions[ $option ] = $serialized_value;
 514              wp_cache_set( 'alloptions', $alloptions, 'options' );
 515          } else {
 516              wp_cache_set( $option, $serialized_value, 'options' );
 517          }
 518      }
 519  
 520      // This option exists now.
 521      $notoptions = wp_cache_get( 'notoptions', 'options' ); // Yes, again... we need it to be fresh.
 522      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
 523          unset( $notoptions[ $option ] );
 524          wp_cache_set( 'notoptions', $notoptions, 'options' );
 525      }
 526  
 527      /**
 528       * Fires after a specific option has been added.
 529       *
 530       * The dynamic portion of the hook name, `$option`, refers to the option name.
 531       *
 532       * @since 2.5.0 As "add_option_{$name}"
 533       * @since 3.0.0
 534       *
 535       * @param string $option Name of the option to add.
 536       * @param mixed  $value  Value of the option.
 537       */
 538      do_action( "add_option_{$option}", $option, $value );
 539  
 540      /**
 541       * Fires after an option has been added.
 542       *
 543       * @since 2.9.0
 544       *
 545       * @param string $option Name of the added option.
 546       * @param mixed  $value  Value of the option.
 547       */
 548      do_action( 'added_option', $option, $value );
 549      return true;
 550  }
 551  
 552  /**
 553   * Removes option by name. Prevents removal of protected WordPress options.
 554   *
 555   * @since 1.2.0
 556   *
 557   * @global wpdb $wpdb WordPress database abstraction object.
 558   *
 559   * @param string $option Name of option to remove. Expected to not be SQL-escaped.
 560   * @return bool True, if option is successfully deleted. False on failure.
 561   */
 562  function delete_option( $option ) {
 563      global $wpdb;
 564  
 565      $option = trim( $option );
 566      if ( empty( $option ) ) {
 567          return false;
 568      }
 569  
 570      wp_protect_special_option( $option );
 571  
 572      // Get the ID, if no ID then return.
 573      $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
 574      if ( is_null( $row ) ) {
 575          return false;
 576      }
 577  
 578      /**
 579       * Fires immediately before an option is deleted.
 580       *
 581       * @since 2.9.0
 582       *
 583       * @param string $option Name of the option to delete.
 584       */
 585      do_action( 'delete_option', $option );
 586  
 587      $result = $wpdb->delete( $wpdb->options, array( 'option_name' => $option ) );
 588      if ( ! wp_installing() ) {
 589          if ( 'yes' === $row->autoload ) {
 590              $alloptions = wp_load_alloptions( true );
 591              if ( is_array( $alloptions ) && isset( $alloptions[ $option ] ) ) {
 592                  unset( $alloptions[ $option ] );
 593                  wp_cache_set( 'alloptions', $alloptions, 'options' );
 594              }
 595          } else {
 596              wp_cache_delete( $option, 'options' );
 597          }
 598      }
 599      if ( $result ) {
 600  
 601          /**
 602           * Fires after a specific option has been deleted.
 603           *
 604           * The dynamic portion of the hook name, `$option`, refers to the option name.
 605           *
 606           * @since 3.0.0
 607           *
 608           * @param string $option Name of the deleted option.
 609           */
 610          do_action( "delete_option_{$option}", $option );
 611  
 612          /**
 613           * Fires after an option has been deleted.
 614           *
 615           * @since 2.9.0
 616           *
 617           * @param string $option Name of the deleted option.
 618           */
 619          do_action( 'deleted_option', $option );
 620          return true;
 621      }
 622      return false;
 623  }
 624  
 625  /**
 626   * Deletes a transient.
 627   *
 628   * @since 2.8.0
 629   *
 630   * @param string $transient Transient name. Expected to not be SQL-escaped.
 631   * @return bool true if successful, false otherwise
 632   */
 633  function delete_transient( $transient ) {
 634  
 635      /**
 636       * Fires immediately before a specific transient is deleted.
 637       *
 638       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 639       *
 640       * @since 3.0.0
 641       *
 642       * @param string $transient Transient name.
 643       */
 644      do_action( "delete_transient_{$transient}", $transient );
 645  
 646      if ( wp_using_ext_object_cache() ) {
 647          $result = wp_cache_delete( $transient, 'transient' );
 648      } else {
 649          $option_timeout = '_transient_timeout_' . $transient;
 650          $option         = '_transient_' . $transient;
 651          $result         = delete_option( $option );
 652          if ( $result ) {
 653              delete_option( $option_timeout );
 654          }
 655      }
 656  
 657      if ( $result ) {
 658  
 659          /**
 660           * Fires after a transient is deleted.
 661           *
 662           * @since 3.0.0
 663           *
 664           * @param string $transient Deleted transient name.
 665           */
 666          do_action( 'deleted_transient', $transient );
 667      }
 668  
 669      return $result;
 670  }
 671  
 672  /**
 673   * Retrieves the value of a transient.
 674   *
 675   * If the transient does not exist, does not have a value, or has expired,
 676   * then the return value will be false.
 677   *
 678   * @since 2.8.0
 679   *
 680   * @param string $transient Transient name. Expected to not be SQL-escaped.
 681   * @return mixed Value of transient.
 682   */
 683  function get_transient( $transient ) {
 684  
 685      /**
 686       * Filters the value of an existing transient.
 687       *
 688       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 689       *
 690       * Passing a truthy value to the filter will effectively short-circuit retrieval
 691       * of the transient, returning the passed value instead.
 692       *
 693       * @since 2.8.0
 694       * @since 4.4.0 The `$transient` parameter was added
 695       *
 696       * @param mixed  $pre_transient The default value to return if the transient does not exist.
 697       *                              Any value other than false will short-circuit the retrieval
 698       *                              of the transient, and return the returned value.
 699       * @param string $transient     Transient name.
 700       */
 701      $pre = apply_filters( "pre_transient_{$transient}", false, $transient );
 702      if ( false !== $pre ) {
 703          return $pre;
 704      }
 705  
 706      if ( wp_using_ext_object_cache() ) {
 707          $value = wp_cache_get( $transient, 'transient' );
 708      } else {
 709          $transient_option = '_transient_' . $transient;
 710          if ( ! wp_installing() ) {
 711              // If option is not in alloptions, it is not autoloaded and thus has a timeout.
 712              $alloptions = wp_load_alloptions();
 713              if ( ! isset( $alloptions[ $transient_option ] ) ) {
 714                  $transient_timeout = '_transient_timeout_' . $transient;
 715                  $timeout           = get_option( $transient_timeout );
 716                  if ( false !== $timeout && $timeout < time() ) {
 717                      delete_option( $transient_option );
 718                      delete_option( $transient_timeout );
 719                      $value = false;
 720                  }
 721              }
 722          }
 723  
 724          if ( ! isset( $value ) ) {
 725              $value = get_option( $transient_option );
 726          }
 727      }
 728  
 729      /**
 730       * Filters an existing transient's value.
 731       *
 732       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 733       *
 734       * @since 2.8.0
 735       * @since 4.4.0 The `$transient` parameter was added
 736       *
 737       * @param mixed  $value     Value of transient.
 738       * @param string $transient Transient name.
 739       */
 740      return apply_filters( "transient_{$transient}", $value, $transient );
 741  }
 742  
 743  /**
 744   * Sets/updates the value of a transient.
 745   *
 746   * You do not need to serialize values. If the value needs to be serialized,
 747   * then it will be serialized before it is set.
 748   *
 749   * @since 2.8.0
 750   *
 751   * @param string $transient  Transient name. Expected to not be SQL-escaped.
 752   *                           Must be 172 characters or fewer in length.
 753   * @param mixed  $value      Transient value. Must be serializable if non-scalar.
 754   *                           Expected to not be SQL-escaped.
 755   * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
 756   * @return bool False if value was not set and true if value was set.
 757   */
 758  function set_transient( $transient, $value, $expiration = 0 ) {
 759  
 760      $expiration = (int) $expiration;
 761  
 762      /**
 763       * Filters a specific transient before its value is set.
 764       *
 765       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 766       *
 767       * @since 3.0.0
 768       * @since 4.2.0 The `$expiration` parameter was added.
 769       * @since 4.4.0 The `$transient` parameter was added.
 770       *
 771       * @param mixed  $value      New value of transient.
 772       * @param int    $expiration Time until expiration in seconds.
 773       * @param string $transient  Transient name.
 774       */
 775      $value = apply_filters( "pre_set_transient_{$transient}", $value, $expiration, $transient );
 776  
 777      /**
 778       * Filters the expiration for a transient before its value is set.
 779       *
 780       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 781       *
 782       * @since 4.4.0
 783       *
 784       * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
 785       * @param mixed  $value      New value of transient.
 786       * @param string $transient  Transient name.
 787       */
 788      $expiration = apply_filters( "expiration_of_transient_{$transient}", $expiration, $value, $transient );
 789  
 790      if ( wp_using_ext_object_cache() ) {
 791          $result = wp_cache_set( $transient, $value, 'transient', $expiration );
 792      } else {
 793          $transient_timeout = '_transient_timeout_' . $transient;
 794          $transient_option  = '_transient_' . $transient;
 795          if ( false === get_option( $transient_option ) ) {
 796              $autoload = 'yes';
 797              if ( $expiration ) {
 798                  $autoload = 'no';
 799                  add_option( $transient_timeout, time() + $expiration, '', 'no' );
 800              }
 801              $result = add_option( $transient_option, $value, '', $autoload );
 802          } else {
 803              // If expiration is requested, but the transient has no timeout option,
 804              // delete, then re-create transient rather than update.
 805              $update = true;
 806              if ( $expiration ) {
 807                  if ( false === get_option( $transient_timeout ) ) {
 808                      delete_option( $transient_option );
 809                      add_option( $transient_timeout, time() + $expiration, '', 'no' );
 810                      $result = add_option( $transient_option, $value, '', 'no' );
 811                      $update = false;
 812                  } else {
 813                      update_option( $transient_timeout, time() + $expiration );
 814                  }
 815              }
 816              if ( $update ) {
 817                  $result = update_option( $transient_option, $value );
 818              }
 819          }
 820      }
 821  
 822      if ( $result ) {
 823  
 824          /**
 825           * Fires after the value for a specific transient has been set.
 826           *
 827           * The dynamic portion of the hook name, `$transient`, refers to the transient name.
 828           *
 829           * @since 3.0.0
 830           * @since 3.6.0 The `$value` and `$expiration` parameters were added.
 831           * @since 4.4.0 The `$transient` parameter was added.
 832           *
 833           * @param mixed  $value      Transient value.
 834           * @param int    $expiration Time until expiration in seconds.
 835           * @param string $transient  The name of the transient.
 836           */
 837          do_action( "set_transient_{$transient}", $value, $expiration, $transient );
 838  
 839          /**
 840           * Fires after the value for a transient has been set.
 841           *
 842           * @since 3.0.0
 843           * @since 3.6.0 The `$value` and `$expiration` parameters were added.
 844           *
 845           * @param string $transient  The name of the transient.
 846           * @param mixed  $value      Transient value.
 847           * @param int    $expiration Time until expiration in seconds.
 848           */
 849          do_action( 'setted_transient', $transient, $value, $expiration );
 850      }
 851      return $result;
 852  }
 853  
 854  /**
 855   * Deletes all expired transients.
 856   *
 857   * The multi-table delete syntax is used to delete the transient record
 858   * from table a, and the corresponding transient_timeout record from table b.
 859   *
 860   * @since 4.9.0
 861   *
 862   * @param bool $force_db Optional. Force cleanup to run against the database even when an external object cache is used.
 863   */
 864  function delete_expired_transients( $force_db = false ) {
 865      global $wpdb;
 866  
 867      if ( ! $force_db && wp_using_ext_object_cache() ) {
 868          return;
 869      }
 870  
 871      $wpdb->query(
 872          $wpdb->prepare(
 873              "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
 874              WHERE a.option_name LIKE %s
 875              AND a.option_name NOT LIKE %s
 876              AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
 877              AND b.option_value < %d",
 878              $wpdb->esc_like( '_transient_' ) . '%',
 879              $wpdb->esc_like( '_transient_timeout_' ) . '%',
 880              time()
 881          )
 882      );
 883  
 884      if ( ! is_multisite() ) {
 885          // Single site stores site transients in the options table.
 886          $wpdb->query(
 887              $wpdb->prepare(
 888                  "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
 889                  WHERE a.option_name LIKE %s
 890                  AND a.option_name NOT LIKE %s
 891                  AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
 892                  AND b.option_value < %d",
 893                  $wpdb->esc_like( '_site_transient_' ) . '%',
 894                  $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
 895                  time()
 896              )
 897          );
 898      } elseif ( is_multisite() && is_main_site() && is_main_network() ) {
 899          // Multisite stores site transients in the sitemeta table.
 900          $wpdb->query(
 901              $wpdb->prepare(
 902                  "DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
 903                  WHERE a.meta_key LIKE %s
 904                  AND a.meta_key NOT LIKE %s
 905                  AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
 906                  AND b.meta_value < %d",
 907                  $wpdb->esc_like( '_site_transient_' ) . '%',
 908                  $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
 909                  time()
 910              )
 911          );
 912      }
 913  }
 914  
 915  /**
 916   * Saves and restores user interface settings stored in a cookie.
 917   *
 918   * Checks if the current user-settings cookie is updated and stores it. When no
 919   * cookie exists (different browser used), adds the last saved cookie restoring
 920   * the settings.
 921   *
 922   * @since 2.7.0
 923   */
 924  function wp_user_settings() {
 925  
 926      if ( ! is_admin() || wp_doing_ajax() ) {
 927          return;
 928      }
 929  
 930      $user_id = get_current_user_id();
 931      if ( ! $user_id ) {
 932          return;
 933      }
 934  
 935      if ( ! is_user_member_of_blog() ) {
 936          return;
 937      }
 938  
 939      $settings = (string) get_user_option( 'user-settings', $user_id );
 940  
 941      if ( isset( $_COOKIE[ 'wp-settings-' . $user_id ] ) ) {
 942          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE[ 'wp-settings-' . $user_id ] );
 943  
 944          // No change or both empty.
 945          if ( $cookie == $settings ) {
 946              return;
 947          }
 948  
 949          $last_saved = (int) get_user_option( 'user-settings-time', $user_id );
 950          $current    = isset( $_COOKIE[ 'wp-settings-time-' . $user_id ] ) ? preg_replace( '/[^0-9]/', '', $_COOKIE[ 'wp-settings-time-' . $user_id ] ) : 0;
 951  
 952          // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is.
 953          if ( $current > $last_saved ) {
 954              update_user_option( $user_id, 'user-settings', $cookie, false );
 955              update_user_option( $user_id, 'user-settings-time', time() - 5, false );
 956              return;
 957          }
 958      }
 959  
 960      // The cookie is not set in the current browser or the saved value is newer.
 961      $secure = ( 'https' === parse_url( admin_url(), PHP_URL_SCHEME ) );
 962      setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
 963      setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
 964      $_COOKIE[ 'wp-settings-' . $user_id ] = $settings;
 965  }
 966  
 967  /**
 968   * Retrieves user interface setting value based on setting name.
 969   *
 970   * @since 2.7.0
 971   *
 972   * @param string $name    The name of the setting.
 973   * @param string $default Optional default value to return when $name is not set.
 974   * @return mixed the last saved user setting or the default value/false if it doesn't exist.
 975   */
 976  function get_user_setting( $name, $default = false ) {
 977      $all_user_settings = get_all_user_settings();
 978  
 979      return isset( $all_user_settings[ $name ] ) ? $all_user_settings[ $name ] : $default;
 980  }
 981  
 982  /**
 983   * Adds or updates user interface setting.
 984   *
 985   * Both $name and $value can contain only ASCII letters, numbers, hyphens, and underscores.
 986   *
 987   * This function has to be used before any output has started as it calls setcookie().
 988   *
 989   * @since 2.8.0
 990   *
 991   * @param string $name  The name of the setting.
 992   * @param string $value The value for the setting.
 993   * @return bool|null True if set successfully, false if not. Null if the current user can't be established.
 994   */
 995  function set_user_setting( $name, $value ) {
 996      if ( headers_sent() ) {
 997          return false;
 998      }
 999  
1000      $all_user_settings          = get_all_user_settings();
1001      $all_user_settings[ $name ] = $value;
1002  
1003      return wp_set_all_user_settings( $all_user_settings );
1004  }
1005  
1006  /**
1007   * Deletes user interface settings.
1008   *
1009   * Deleting settings would reset them to the defaults.
1010   *
1011   * This function has to be used before any output has started as it calls setcookie().
1012   *
1013   * @since 2.7.0
1014   *
1015   * @param string $names The name or array of names of the setting to be deleted.
1016   * @return bool|null True if deleted successfully, false if not. Null if the current user can't be established.
1017   */
1018  function delete_user_setting( $names ) {
1019      if ( headers_sent() ) {
1020          return false;
1021      }
1022  
1023      $all_user_settings = get_all_user_settings();
1024      $names             = (array) $names;
1025      $deleted           = false;
1026  
1027      foreach ( $names as $name ) {
1028          if ( isset( $all_user_settings[ $name ] ) ) {
1029              unset( $all_user_settings[ $name ] );
1030              $deleted = true;
1031          }
1032      }
1033  
1034      if ( $deleted ) {
1035          return wp_set_all_user_settings( $all_user_settings );
1036      }
1037  
1038      return false;
1039  }
1040  
1041  /**
1042   * Retrieves all user interface settings.
1043   *
1044   * @since 2.7.0
1045   *
1046   * @global array $_updated_user_settings
1047   *
1048   * @return array the last saved user settings or empty array.
1049   */
1050  function get_all_user_settings() {
1051      global $_updated_user_settings;
1052  
1053      $user_id = get_current_user_id();
1054      if ( ! $user_id ) {
1055          return array();
1056      }
1057  
1058      if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) {
1059          return $_updated_user_settings;
1060      }
1061  
1062      $user_settings = array();
1063  
1064      if ( isset( $_COOKIE[ 'wp-settings-' . $user_id ] ) ) {
1065          $cookie = preg_replace( '/[^A-Za-z0-9=&_-]/', '', $_COOKIE[ 'wp-settings-' . $user_id ] );
1066  
1067          if ( strpos( $cookie, '=' ) ) { // '=' cannot be 1st char.
1068              parse_str( $cookie, $user_settings );
1069          }
1070      } else {
1071          $option = get_user_option( 'user-settings', $user_id );
1072  
1073          if ( $option && is_string( $option ) ) {
1074              parse_str( $option, $user_settings );
1075          }
1076      }
1077  
1078      $_updated_user_settings = $user_settings;
1079      return $user_settings;
1080  }
1081  
1082  /**
1083   * Private. Sets all user interface settings.
1084   *
1085   * @since 2.8.0
1086   * @access private
1087   *
1088   * @global array $_updated_user_settings
1089   *
1090   * @param array $user_settings User settings.
1091   * @return bool|null False if the current user can't be found, null if the current
1092   *                   user is not a super admin or a member of the site, otherwise true.
1093   */
1094  function wp_set_all_user_settings( $user_settings ) {
1095      global $_updated_user_settings;
1096  
1097      $user_id = get_current_user_id();
1098      if ( ! $user_id ) {
1099          return false;
1100      }
1101  
1102      if ( ! is_user_member_of_blog() ) {
1103          return;
1104      }
1105  
1106      $settings = '';
1107      foreach ( $user_settings as $name => $value ) {
1108          $_name  = preg_replace( '/[^A-Za-z0-9_-]+/', '', $name );
1109          $_value = preg_replace( '/[^A-Za-z0-9_-]+/', '', $value );
1110  
1111          if ( ! empty( $_name ) ) {
1112              $settings .= $_name . '=' . $_value . '&';
1113          }
1114      }
1115  
1116      $settings = rtrim( $settings, '&' );
1117      parse_str( $settings, $_updated_user_settings );
1118  
1119      update_user_option( $user_id, 'user-settings', $settings, false );
1120      update_user_option( $user_id, 'user-settings-time', time(), false );
1121  
1122      return true;
1123  }
1124  
1125  /**
1126   * Deletes the user settings of the current user.
1127   *
1128   * @since 2.7.0
1129   */
1130  function delete_all_user_settings() {
1131      $user_id = get_current_user_id();
1132      if ( ! $user_id ) {
1133          return;
1134      }
1135  
1136      update_user_option( $user_id, 'user-settings', '', false );
1137      setcookie( 'wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
1138  }
1139  
1140  /**
1141   * Retrieve an option value for the current network based on name of option.
1142   *
1143   * @since 2.8.0
1144   * @since 4.4.0 The `$use_cache` parameter was deprecated.
1145   * @since 4.4.0 Modified into wrapper for get_network_option()
1146   *
1147   * @see get_network_option()
1148   *
1149   * @param string $option     Name of option to retrieve. Expected to not be SQL-escaped.
1150   * @param mixed  $default    Optional value to return if option doesn't exist. Default false.
1151   * @param bool   $deprecated Whether to use cache. Multisite only. Always set to true.
1152   * @return mixed Value set for the option.
1153   */
1154  function get_site_option( $option, $default = false, $deprecated = true ) {
1155      return get_network_option( null, $option, $default );
1156  }
1157  
1158  /**
1159   * Adds a new option for the current network.
1160   *
1161   * Existing options will not be updated. Note that prior to 3.3 this wasn't the case.
1162   *
1163   * @since 2.8.0
1164   * @since 4.4.0 Modified into wrapper for add_network_option()
1165   *
1166   * @see add_network_option()
1167   *
1168   * @param string $option Name of option to add. Expected to not be SQL-escaped.
1169   * @param mixed  $value  Option value, can be anything. Expected to not be SQL-escaped.
1170   * @return bool False if the option was not added. True if the option was added.
1171   */
1172  function add_site_option( $option, $value ) {
1173      return add_network_option( null, $option, $value );
1174  }
1175  
1176  /**
1177   * Removes a option by name for the current network.
1178   *
1179   * @since 2.8.0
1180   * @since 4.4.0 Modified into wrapper for delete_network_option()
1181   *
1182   * @see delete_network_option()
1183   *
1184   * @param string $option Name of option to remove. Expected to not be SQL-escaped.
1185   * @return bool True, if succeed. False, if failure.
1186   */
1187  function delete_site_option( $option ) {
1188      return delete_network_option( null, $option );
1189  }
1190  
1191  /**
1192   * Updates the value of an option that was already added for the current network.
1193   *
1194   * @since 2.8.0
1195   * @since 4.4.0 Modified into wrapper for update_network_option()
1196   *
1197   * @see update_network_option()
1198   *
1199   * @param string $option Name of option. Expected to not be SQL-escaped.
1200   * @param mixed  $value  Option value. Expected to not be SQL-escaped.
1201   * @return bool False if value was not updated. True if value was updated.
1202   */
1203  function update_site_option( $option, $value ) {
1204      return update_network_option( null, $option, $value );
1205  }
1206  
1207  /**
1208   * Retrieves a network's option value based on the option name.
1209   *
1210   * @since 4.4.0
1211   *
1212   * @see get_option()
1213   *
1214   * @global wpdb $wpdb WordPress database abstraction object.
1215   *
1216   * @param int      $network_id ID of the network. Can be null to default to the current network ID.
1217   * @param string   $option     Name of option to retrieve. Expected to not be SQL-escaped.
1218   * @param mixed    $default    Optional. Value to return if the option doesn't exist. Default false.
1219   * @return mixed Value set for the option.
1220   */
1221  function get_network_option( $network_id, $option, $default = false ) {
1222      global $wpdb;
1223  
1224      if ( $network_id && ! is_numeric( $network_id ) ) {
1225          return false;
1226      }
1227  
1228      $network_id = (int) $network_id;
1229  
1230      // Fallback to the current network if a network ID is not specified.
1231      if ( ! $network_id ) {
1232          $network_id = get_current_network_id();
1233      }
1234  
1235      /**
1236       * Filters an existing network option before it is retrieved.
1237       *
1238       * The dynamic portion of the hook name, `$option`, refers to the option name.
1239       *
1240       * Passing a truthy value to the filter will effectively short-circuit retrieval,
1241       * returning the passed value instead.
1242       *
1243       * @since 2.9.0 As 'pre_site_option_' . $key
1244       * @since 3.0.0
1245       * @since 4.4.0 The `$option` parameter was added.
1246       * @since 4.7.0 The `$network_id` parameter was added.
1247       * @since 4.9.0 The `$default` parameter was added.
1248       *
1249       * @param mixed  $pre_option The value to return instead of the option value. This differs from
1250       *                           `$default`, which is used as the fallback value in the event the
1251       *                           option doesn't exist elsewhere in get_network_option(). Default
1252       *                           is false (to skip past the short-circuit).
1253       * @param string $option     Option name.
1254       * @param int    $network_id ID of the network.
1255       * @param mixed  $default    The fallback value to return if the option does not exist.
1256       *                           Default is false.
1257       */
1258      $pre = apply_filters( "pre_site_option_{$option}", false, $option, $network_id, $default );
1259  
1260      if ( false !== $pre ) {
1261          return $pre;
1262      }
1263  
1264      // Prevent non-existent options from triggering multiple queries.
1265      $notoptions_key = "$network_id:notoptions";
1266      $notoptions     = wp_cache_get( $notoptions_key, 'site-options' );
1267  
1268      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1269  
1270          /**
1271           * Filters a specific default network option.
1272           *
1273           * The dynamic portion of the hook name, `$option`, refers to the option name.
1274           *
1275           * @since 3.4.0
1276           * @since 4.4.0 The `$option` parameter was added.
1277           * @since 4.7.0 The `$network_id` parameter was added.
1278           *
1279           * @param mixed  $default    The value to return if the site option does not exist
1280           *                           in the database.
1281           * @param string $option     Option name.
1282           * @param int    $network_id ID of the network.
1283           */
1284          return apply_filters( "default_site_option_{$option}", $default, $option, $network_id );
1285      }
1286  
1287      if ( ! is_multisite() ) {
1288          /** This filter is documented in wp-includes/option.php */
1289          $default = apply_filters( 'default_site_option_' . $option, $default, $option, $network_id );
1290          $value   = get_option( $option, $default );
1291      } else {
1292          $cache_key = "$network_id:$option";
1293          $value     = wp_cache_get( $cache_key, 'site-options' );
1294  
1295          if ( ! isset( $value ) || false === $value ) {
1296              $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
1297  
1298              // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
1299              if ( is_object( $row ) ) {
1300                  $value = $row->meta_value;
1301                  $value = maybe_unserialize( $value );
1302                  wp_cache_set( $cache_key, $value, 'site-options' );
1303              } else {
1304                  if ( ! is_array( $notoptions ) ) {
1305                      $notoptions = array();
1306                  }
1307                  $notoptions[ $option ] = true;
1308                  wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1309  
1310                  /** This filter is documented in wp-includes/option.php */
1311                  $value = apply_filters( 'default_site_option_' . $option, $default, $option, $network_id );
1312              }
1313          }
1314      }
1315  
1316      if ( ! is_array( $notoptions ) ) {
1317          $notoptions = array();
1318          wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1319      }
1320  
1321      /**
1322       * Filters the value of an existing network option.
1323       *
1324       * The dynamic portion of the hook name, `$option`, refers to the option name.
1325       *
1326       * @since 2.9.0 As 'site_option_' . $key
1327       * @since 3.0.0
1328       * @since 4.4.0 The `$option` parameter was added.
1329       * @since 4.7.0 The `$network_id` parameter was added.
1330       *
1331       * @param mixed  $value      Value of network option.
1332       * @param string $option     Option name.
1333       * @param int    $network_id ID of the network.
1334       */
1335      return apply_filters( "site_option_{$option}", $value, $option, $network_id );
1336  }
1337  
1338  /**
1339   * Adds a new network option.
1340   *
1341   * Existing options will not be updated.
1342   *
1343   * @since 4.4.0
1344   *
1345   * @see add_option()
1346   *
1347   * @global wpdb $wpdb WordPress database abstraction object.
1348   *
1349   * @param int    $network_id ID of the network. Can be null to default to the current network ID.
1350   * @param string $option     Name of option to add. Expected to not be SQL-escaped.
1351   * @param mixed  $value      Option value, can be anything. Expected to not be SQL-escaped.
1352   * @return bool False if option was not added and true if option was added.
1353   */
1354  function add_network_option( $network_id, $option, $value ) {
1355      global $wpdb;
1356  
1357      if ( $network_id && ! is_numeric( $network_id ) ) {
1358          return false;
1359      }
1360  
1361      $network_id = (int) $network_id;
1362  
1363      // Fallback to the current network if a network ID is not specified.
1364      if ( ! $network_id ) {
1365          $network_id = get_current_network_id();
1366      }
1367  
1368      wp_protect_special_option( $option );
1369  
1370      /**
1371       * Filters the value of a specific network option before it is added.
1372       *
1373       * The dynamic portion of the hook name, `$option`, refers to the option name.
1374       *
1375       * @since 2.9.0 As 'pre_add_site_option_' . $key
1376       * @since 3.0.0
1377       * @since 4.4.0 The `$option` parameter was added.
1378       * @since 4.7.0 The `$network_id` parameter was added.
1379       *
1380       * @param mixed  $value      Value of network option.
1381       * @param string $option     Option name.
1382       * @param int    $network_id ID of the network.
1383       */
1384      $value = apply_filters( "pre_add_site_option_{$option}", $value, $option, $network_id );
1385  
1386      $notoptions_key = "$network_id:notoptions";
1387  
1388      if ( ! is_multisite() ) {
1389          $result = add_option( $option, $value, '', 'no' );
1390      } else {
1391          $cache_key = "$network_id:$option";
1392  
1393          // Make sure the option doesn't already exist.
1394          // We can check the 'notoptions' cache before we ask for a DB query.
1395          $notoptions = wp_cache_get( $notoptions_key, 'site-options' );
1396          if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
1397              if ( false !== get_network_option( $network_id, $option, false ) ) {
1398                  return false;
1399              }
1400          }
1401  
1402          $value = sanitize_option( $option, $value );
1403  
1404          $serialized_value = maybe_serialize( $value );
1405          $result           = $wpdb->insert(
1406              $wpdb->sitemeta,
1407              array(
1408                  'site_id'    => $network_id,
1409                  'meta_key'   => $option,
1410                  'meta_value' => $serialized_value,
1411              )
1412          );
1413  
1414          if ( ! $result ) {
1415              return false;
1416          }
1417  
1418          wp_cache_set( $cache_key, $value, 'site-options' );
1419  
1420          // This option exists now.
1421          $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); // Yes, again... we need it to be fresh.
1422          if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1423              unset( $notoptions[ $option ] );
1424              wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1425          }
1426      }
1427  
1428      if ( $result ) {
1429  
1430          /**
1431           * Fires after a specific network option has been successfully added.
1432           *
1433           * The dynamic portion of the hook name, `$option`, refers to the option name.
1434           *
1435           * @since 2.9.0 As "add_site_option_{$key}"
1436           * @since 3.0.0
1437           * @since 4.7.0 The `$network_id` parameter was added.
1438           *
1439           * @param string $option     Name of the network option.
1440           * @param mixed  $value      Value of the network option.
1441           * @param int    $network_id ID of the network.
1442           */
1443          do_action( "add_site_option_{$option}", $option, $value, $network_id );
1444  
1445          /**
1446           * Fires after a network option has been successfully added.
1447           *
1448           * @since 3.0.0
1449           * @since 4.7.0 The `$network_id` parameter was added.
1450           *
1451           * @param string $option     Name of the network option.
1452           * @param mixed  $value      Value of the network option.
1453           * @param int    $network_id ID of the network.
1454           */
1455          do_action( 'add_site_option', $option, $value, $network_id );
1456  
1457          return true;
1458      }
1459  
1460      return false;
1461  }
1462  
1463  /**
1464   * Removes a network option by name.
1465   *
1466   * @since 4.4.0
1467   *
1468   * @see delete_option()
1469   *
1470   * @global wpdb $wpdb WordPress database abstraction object.
1471   *
1472   * @param int    $network_id ID of the network. Can be null to default to the current network ID.
1473   * @param string $option     Name of option to remove. Expected to not be SQL-escaped.
1474   * @return bool True, if succeed. False, if failure.
1475   */
1476  function delete_network_option( $network_id, $option ) {
1477      global $wpdb;
1478  
1479      if ( $network_id && ! is_numeric( $network_id ) ) {
1480          return false;
1481      }
1482  
1483      $network_id = (int) $network_id;
1484  
1485      // Fallback to the current network if a network ID is not specified.
1486      if ( ! $network_id ) {
1487          $network_id = get_current_network_id();
1488      }
1489  
1490      /**
1491       * Fires immediately before a specific network option is deleted.
1492       *
1493       * The dynamic portion of the hook name, `$option`, refers to the option name.
1494       *
1495       * @since 3.0.0
1496       * @since 4.4.0 The `$option` parameter was added.
1497       * @since 4.7.0 The `$network_id` parameter was added.
1498       *
1499       * @param string $option     Option name.
1500       * @param int    $network_id ID of the network.
1501       */
1502      do_action( "pre_delete_site_option_{$option}", $option, $network_id );
1503  
1504      if ( ! is_multisite() ) {
1505          $result = delete_option( $option );
1506      } else {
1507          $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
1508          if ( is_null( $row ) || ! $row->meta_id ) {
1509              return false;
1510          }
1511          $cache_key = "$network_id:$option";
1512          wp_cache_delete( $cache_key, 'site-options' );
1513  
1514          $result = $wpdb->delete(
1515              $wpdb->sitemeta,
1516              array(
1517                  'meta_key' => $option,
1518                  'site_id'  => $network_id,
1519              )
1520          );
1521      }
1522  
1523      if ( $result ) {
1524  
1525          /**
1526           * Fires after a specific network option has been deleted.
1527           *
1528           * The dynamic portion of the hook name, `$option`, refers to the option name.
1529           *
1530           * @since 2.9.0 As "delete_site_option_{$key}"
1531           * @since 3.0.0
1532           * @since 4.7.0 The `$network_id` parameter was added.
1533           *
1534           * @param string $option     Name of the network option.
1535           * @param int    $network_id ID of the network.
1536           */
1537          do_action( "delete_site_option_{$option}", $option, $network_id );
1538  
1539          /**
1540           * Fires after a network option has been deleted.
1541           *
1542           * @since 3.0.0
1543           * @since 4.7.0 The `$network_id` parameter was added.
1544           *
1545           * @param string $option     Name of the network option.
1546           * @param int    $network_id ID of the network.
1547           */
1548          do_action( 'delete_site_option', $option, $network_id );
1549  
1550          return true;
1551      }
1552  
1553      return false;
1554  }
1555  
1556  /**
1557   * Updates the value of a network option that was already added.
1558   *
1559   * @since 4.4.0
1560   *
1561   * @see update_option()
1562   *
1563   * @global wpdb $wpdb WordPress database abstraction object.
1564   *
1565   * @param int      $network_id ID of the network. Can be null to default to the current network ID.
1566   * @param string   $option     Name of option. Expected to not be SQL-escaped.
1567   * @param mixed    $value      Option value. Expected to not be SQL-escaped.
1568   * @return bool False if value was not updated and true if value was updated.
1569   */
1570  function update_network_option( $network_id, $option, $value ) {
1571      global $wpdb;
1572  
1573      if ( $network_id && ! is_numeric( $network_id ) ) {
1574          return false;
1575      }
1576  
1577      $network_id = (int) $network_id;
1578  
1579      // Fallback to the current network if a network ID is not specified.
1580      if ( ! $network_id ) {
1581          $network_id = get_current_network_id();
1582      }
1583  
1584      wp_protect_special_option( $option );
1585  
1586      $old_value = get_network_option( $network_id, $option, false );
1587  
1588      /**
1589       * Filters a specific network option before its value is updated.
1590       *
1591       * The dynamic portion of the hook name, `$option`, refers to the option name.
1592       *
1593       * @since 2.9.0 As 'pre_update_site_option_' . $key
1594       * @since 3.0.0
1595       * @since 4.4.0 The `$option` parameter was added.
1596       * @since 4.7.0 The `$network_id` parameter was added.
1597       *
1598       * @param mixed  $value      New value of the network option.
1599       * @param mixed  $old_value  Old value of the network option.
1600       * @param string $option     Option name.
1601       * @param int    $network_id ID of the network.
1602       */
1603      $value = apply_filters( "pre_update_site_option_{$option}", $value, $old_value, $option, $network_id );
1604  
1605      /*
1606       * If the new and old values are the same, no need to update.
1607       *
1608       * Unserialized values will be adequate in most cases. If the unserialized
1609       * data differs, the (maybe) serialized data is checked to avoid
1610       * unnecessary database calls for otherwise identical object instances.
1611       *
1612       * See https://core.trac.wordpress.org/ticket/44956
1613       */
1614      if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
1615          return false;
1616      }
1617  
1618      if ( false === $old_value ) {
1619          return add_network_option( $network_id, $option, $value );
1620      }
1621  
1622      $notoptions_key = "$network_id:notoptions";
1623      $notoptions     = wp_cache_get( $notoptions_key, 'site-options' );
1624      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1625          unset( $notoptions[ $option ] );
1626          wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1627      }
1628  
1629      if ( ! is_multisite() ) {
1630          $result = update_option( $option, $value, 'no' );
1631      } else {
1632          $value = sanitize_option( $option, $value );
1633  
1634          $serialized_value = maybe_serialize( $value );
1635          $result           = $wpdb->update(
1636              $wpdb->sitemeta,
1637              array( 'meta_value' => $serialized_value ),
1638              array(
1639                  'site_id'  => $network_id,
1640                  'meta_key' => $option,
1641              )
1642          );
1643  
1644          if ( $result ) {
1645              $cache_key = "$network_id:$option";
1646              wp_cache_set( $cache_key, $value, 'site-options' );
1647          }
1648      }
1649  
1650      if ( $result ) {
1651  
1652          /**
1653           * Fires after the value of a specific network option has been successfully updated.
1654           *
1655           * The dynamic portion of the hook name, `$option`, refers to the option name.
1656           *
1657           * @since 2.9.0 As "update_site_option_{$key}"
1658           * @since 3.0.0
1659           * @since 4.7.0 The `$network_id` parameter was added.
1660           *
1661           * @param string $option     Name of the network option.
1662           * @param mixed  $value      Current value of the network option.
1663           * @param mixed  $old_value  Old value of the network option.
1664           * @param int    $network_id ID of the network.
1665           */
1666          do_action( "update_site_option_{$option}", $option, $value, $old_value, $network_id );
1667  
1668          /**
1669           * Fires after the value of a network option has been successfully updated.
1670           *
1671           * @since 3.0.0
1672           * @since 4.7.0 The `$network_id` parameter was added.
1673           *
1674           * @param string $option     Name of the network option.
1675           * @param mixed  $value      Current value of the network option.
1676           * @param mixed  $old_value  Old value of the network option.
1677           * @param int    $network_id ID of the network.
1678           */
1679          do_action( 'update_site_option', $option, $value, $old_value, $network_id );
1680  
1681          return true;
1682      }
1683  
1684      return false;
1685  }
1686  
1687  /**
1688   * Deletes a site transient.
1689   *
1690   * @since 2.9.0
1691   *
1692   * @param string $transient Transient name. Expected to not be SQL-escaped.
1693   * @return bool True if successful, false otherwise
1694   */
1695  function delete_site_transient( $transient ) {
1696  
1697      /**
1698       * Fires immediately before a specific site transient is deleted.
1699       *
1700       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1701       *
1702       * @since 3.0.0
1703       *
1704       * @param string $transient Transient name.
1705       */
1706      do_action( "delete_site_transient_{$transient}", $transient );
1707  
1708      if ( wp_using_ext_object_cache() ) {
1709          $result = wp_cache_delete( $transient, 'site-transient' );
1710      } else {
1711          $option_timeout = '_site_transient_timeout_' . $transient;
1712          $option         = '_site_transient_' . $transient;
1713          $result         = delete_site_option( $option );
1714          if ( $result ) {
1715              delete_site_option( $option_timeout );
1716          }
1717      }
1718      if ( $result ) {
1719  
1720          /**
1721           * Fires after a transient is deleted.
1722           *
1723           * @since 3.0.0
1724           *
1725           * @param string $transient Deleted transient name.
1726           */
1727          do_action( 'deleted_site_transient', $transient );
1728      }
1729  
1730      return $result;
1731  }
1732  
1733  /**
1734   * Retrieves the value of a site transient.
1735   *
1736   * If the transient does not exist, does not have a value, or has expired,
1737   * then the return value will be false.
1738   *
1739   * @since 2.9.0
1740   *
1741   * @see get_transient()
1742   *
1743   * @param string $transient Transient name. Expected to not be SQL-escaped.
1744   * @return mixed Value of transient.
1745   */
1746  function get_site_transient( $transient ) {
1747  
1748      /**
1749       * Filters the value of an existing site transient.
1750       *
1751       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1752       *
1753       * Passing a truthy value to the filter will effectively short-circuit retrieval,
1754       * returning the passed value instead.
1755       *
1756       * @since 2.9.0
1757       * @since 4.4.0 The `$transient` parameter was added.
1758       *
1759       * @param mixed  $pre_site_transient The default value to return if the site transient does not exist.
1760       *                                   Any value other than false will short-circuit the retrieval
1761       *                                   of the transient, and return the returned value.
1762       * @param string $transient          Transient name.
1763       */
1764      $pre = apply_filters( "pre_site_transient_{$transient}", false, $transient );
1765  
1766      if ( false !== $pre ) {
1767          return $pre;
1768      }
1769  
1770      if ( wp_using_ext_object_cache() ) {
1771          $value = wp_cache_get( $transient, 'site-transient' );
1772      } else {
1773          // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
1774          $no_timeout       = array( 'update_core', 'update_plugins', 'update_themes' );
1775          $transient_option = '_site_transient_' . $transient;
1776          if ( ! in_array( $transient, $no_timeout, true ) ) {
1777              $transient_timeout = '_site_transient_timeout_' . $transient;
1778              $timeout           = get_site_option( $transient_timeout );
1779              if ( false !== $timeout && $timeout < time() ) {
1780                  delete_site_option( $transient_option );
1781                  delete_site_option( $transient_timeout );
1782                  $value = false;
1783              }
1784          }
1785  
1786          if ( ! isset( $value ) ) {
1787              $value = get_site_option( $transient_option );
1788          }
1789      }
1790  
1791      /**
1792       * Filters the value of an existing site transient.
1793       *
1794       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1795       *
1796       * @since 2.9.0
1797       * @since 4.4.0 The `$transient` parameter was added.
1798       *
1799       * @param mixed  $value     Value of site transient.
1800       * @param string $transient Transient name.
1801       */
1802      return apply_filters( "site_transient_{$transient}", $value, $transient );
1803  }
1804  
1805  /**
1806   * Sets/updates the value of a site transient.
1807   *
1808   * You do not need to serialize values. If the value needs to be serialized,
1809   * then it will be serialized before it is set.
1810   *
1811   * @since 2.9.0
1812   *
1813   * @see set_transient()
1814   *
1815   * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
1816   *                           167 characters or fewer in length.
1817   * @param mixed  $value      Transient value. Expected to not be SQL-escaped.
1818   * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
1819   * @return bool False if value was not set and true if value was set.
1820   */
1821  function set_site_transient( $transient, $value, $expiration = 0 ) {
1822  
1823      /**
1824       * Filters the value of a specific site transient before it is set.
1825       *
1826       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1827       *
1828       * @since 3.0.0
1829       * @since 4.4.0 The `$transient` parameter was added.
1830       *
1831       * @param mixed  $value     New value of site transient.
1832       * @param string $transient Transient name.
1833       */
1834      $value = apply_filters( "pre_set_site_transient_{$transient}", $value, $transient );
1835  
1836      $expiration = (int) $expiration;
1837  
1838      /**
1839       * Filters the expiration for a site transient before its value is set.
1840       *
1841       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1842       *
1843       * @since 4.4.0
1844       *
1845       * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
1846       * @param mixed  $value      New value of site transient.
1847       * @param string $transient  Transient name.
1848       */
1849      $expiration = apply_filters( "expiration_of_site_transient_{$transient}", $expiration, $value, $transient );
1850  
1851      if ( wp_using_ext_object_cache() ) {
1852          $result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
1853      } else {
1854          $transient_timeout = '_site_transient_timeout_' . $transient;
1855          $option            = '_site_transient_' . $transient;
1856          if ( false === get_site_option( $option ) ) {
1857              if ( $expiration ) {
1858                  add_site_option( $transient_timeout, time() + $expiration );
1859              }
1860              $result = add_site_option( $option, $value );
1861          } else {
1862              if ( $expiration ) {
1863                  update_site_option( $transient_timeout, time() + $expiration );
1864              }
1865              $result = update_site_option( $option, $value );
1866          }
1867      }
1868      if ( $result ) {
1869  
1870          /**
1871           * Fires after the value for a specific site transient has been set.
1872           *
1873           * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1874           *
1875           * @since 3.0.0
1876           * @since 4.4.0 The `$transient` parameter was added
1877           *
1878           * @param mixed  $value      Site transient value.
1879           * @param int    $expiration Time until expiration in seconds.
1880           * @param string $transient  Transient name.
1881           */
1882          do_action( "set_site_transient_{$transient}", $value, $expiration, $transient );
1883  
1884          /**
1885           * Fires after the value for a site transient has been set.
1886           *
1887           * @since 3.0.0
1888           *
1889           * @param string $transient  The name of the site transient.
1890           * @param mixed  $value      Site transient value.
1891           * @param int    $expiration Time until expiration in seconds.
1892           */
1893          do_action( 'setted_site_transient', $transient, $value, $expiration );
1894      }
1895      return $result;
1896  }
1897  
1898  /**
1899   * Registers default settings available in WordPress.
1900   *
1901   * The settings registered here are primarily useful for the REST API, so this
1902   * does not encompass all settings available in WordPress.
1903   *
1904   * @since 4.7.0
1905   */
1906  function register_initial_settings() {
1907      register_setting(
1908          'general',
1909          'blogname',
1910          array(
1911              'show_in_rest' => array(
1912                  'name' => 'title',
1913              ),
1914              'type'         => 'string',
1915              'description'  => __( 'Site title.' ),
1916          )
1917      );
1918  
1919      register_setting(
1920          'general',
1921          'blogdescription',
1922          array(
1923              'show_in_rest' => array(
1924                  'name' => 'description',
1925              ),
1926              'type'         => 'string',
1927              'description'  => __( 'Site tagline.' ),
1928          )
1929      );
1930  
1931      if ( ! is_multisite() ) {
1932          register_setting(
1933              'general',
1934              'siteurl',
1935              array(
1936                  'show_in_rest' => array(
1937                      'name'   => 'url',
1938                      'schema' => array(
1939                          'format' => 'uri',
1940                      ),
1941                  ),
1942                  'type'         => 'string',
1943                  'description'  => __( 'Site URL.' ),
1944              )
1945          );
1946      }
1947  
1948      if ( ! is_multisite() ) {
1949          register_setting(
1950              'general',
1951              'admin_email',
1952              array(
1953                  'show_in_rest' => array(
1954                      'name'   => 'email',
1955                      'schema' => array(
1956                          'format' => 'email',
1957                      ),
1958                  ),
1959                  'type'         => 'string',
1960                  'description'  => __( 'This address is used for admin purposes, like new user notification.' ),
1961              )
1962          );
1963      }
1964  
1965      register_setting(
1966          'general',
1967          'timezone_string',
1968          array(
1969              'show_in_rest' => array(
1970                  'name' => 'timezone',
1971              ),
1972              'type'         => 'string',
1973              'description'  => __( 'A city in the same timezone as you.' ),
1974          )
1975      );
1976  
1977      register_setting(
1978          'general',
1979          'date_format',
1980          array(
1981              'show_in_rest' => true,
1982              'type'         => 'string',
1983              'description'  => __( 'A date format for all date strings.' ),
1984          )
1985      );
1986  
1987      register_setting(
1988          'general',
1989          'time_format',
1990          array(
1991              'show_in_rest' => true,
1992              'type'         => 'string',
1993              'description'  => __( 'A time format for all time strings.' ),
1994          )
1995      );
1996  
1997      register_setting(
1998          'general',
1999          'start_of_week',
2000          array(
2001              'show_in_rest' => true,
2002              'type'         => 'integer',
2003              'description'  => __( 'A day number of the week that the week should start on.' ),
2004          )
2005      );
2006  
2007      register_setting(
2008          'general',
2009          'WPLANG',
2010          array(
2011              'show_in_rest' => array(
2012                  'name' => 'language',
2013              ),
2014              'type'         => 'string',
2015              'description'  => __( 'WordPress locale code.' ),
2016              'default'      => 'en_US',
2017          )
2018      );
2019  
2020      register_setting(
2021          'writing',
2022          'use_smilies',
2023          array(
2024              'show_in_rest' => true,
2025              'type'         => 'boolean',
2026              'description'  => __( 'Convert emoticons like :-) and :-P to graphics on display.' ),
2027              'default'      => true,
2028          )
2029      );
2030  
2031      register_setting(
2032          'writing',
2033          'default_category',
2034          array(
2035              'show_in_rest' => true,
2036              'type'         => 'integer',
2037              'description'  => __( 'Default post category.' ),
2038          )
2039      );
2040  
2041      register_setting(
2042          'writing',
2043          'default_post_format',
2044          array(
2045              'show_in_rest' => true,
2046              'type'         => 'string',
2047              'description'  => __( 'Default post format.' ),
2048          )
2049      );
2050  
2051      register_setting(
2052          'reading',
2053          'posts_per_page',
2054          array(
2055              'show_in_rest' => true,
2056              'type'         => 'integer',
2057              'description'  => __( 'Blog pages show at most.' ),
2058              'default'      => 10,
2059          )
2060      );
2061  
2062      register_setting(
2063          'discussion',
2064          'default_ping_status',
2065          array(
2066              'show_in_rest' => array(
2067                  'schema' => array(
2068                      'enum' => array( 'open', 'closed' ),
2069                  ),
2070              ),
2071              'type'         => 'string',
2072              'description'  => __( 'Allow link notifications from other blogs (pingbacks and trackbacks) on new articles.' ),
2073          )
2074      );
2075  
2076      register_setting(
2077          'discussion',
2078          'default_comment_status',
2079          array(
2080              'show_in_rest' => array(
2081                  'schema' => array(
2082                      'enum' => array( 'open', 'closed' ),
2083                  ),
2084              ),
2085              'type'         => 'string',
2086              'description'  => __( 'Allow people to submit comments on new posts.' ),
2087          )
2088      );
2089  }
2090  
2091  /**
2092   * Registers a setting and its data.
2093   *
2094   * @since 2.7.0
2095   * @since 4.7.0 `$args` can be passed to set flags on the setting, similar to `register_meta()`.
2096   *
2097   * @global array $new_whitelist_options
2098   * @global array $wp_registered_settings
2099   *
2100   * @param string $option_group A settings group name. Should correspond to a whitelisted option key name.
2101   *                             Default whitelisted option key names include 'general', 'discussion', 'media',
2102   *                             'reading', 'writing', 'misc', 'options', and 'privacy'.
2103   * @param string $option_name The name of an option to sanitize and save.
2104   * @param array  $args {
2105   *     Data used to describe the setting when registered.
2106   *
2107   *     @type string     $type              The type of data associated with this setting.
2108   *                                         Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
2109   *     @type string     $description       A description of the data attached to this setting.
2110   *     @type callable   $sanitize_callback A callback function that sanitizes the option's value.
2111   *     @type bool|array $show_in_rest      Whether data associated with this setting should be included in the REST API.
2112   *                                         When registering complex settings, this argument may optionally be an
2113   *                                         array with a 'schema' key.
2114   *     @type mixed      $default           Default value when calling `get_option()`.
2115   * }
2116   */
2117  function register_setting( $option_group, $option_name, $args = array() ) {
2118      global $new_whitelist_options, $wp_registered_settings;
2119  
2120      $defaults = array(
2121          'type'              => 'string',
2122          'group'             => $option_group,
2123          'description'       => '',
2124          'sanitize_callback' => null,
2125          'show_in_rest'      => false,
2126      );
2127  
2128      // Back-compat: old sanitize callback is added.
2129      if ( is_callable( $args ) ) {
2130          $args = array(
2131              'sanitize_callback' => $args,
2132          );
2133      }
2134  
2135      /**
2136       * Filters the registration arguments when registering a setting.
2137       *
2138       * @since 4.7.0
2139       *
2140       * @param array  $args         Array of setting registration arguments.
2141       * @param array  $defaults     Array of default arguments.
2142       * @param string $option_group Setting group.
2143       * @param string $option_name  Setting name.
2144       */
2145      $args = apply_filters( 'register_setting_args', $args, $defaults, $option_group, $option_name );
2146      $args = wp_parse_args( $args, $defaults );
2147  
2148      // Require an item schema when registering settings with an array type.
2149      if ( false !== $args['show_in_rest'] && 'array' === $args['type'] && ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) ) {
2150          _doing_it_wrong( __FUNCTION__, __( 'When registering an "array" setting to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.4.0' );
2151      }
2152  
2153      if ( ! is_array( $wp_registered_settings ) ) {
2154          $wp_registered_settings = array();
2155      }
2156  
2157      if ( 'misc' === $option_group ) {
2158          _deprecated_argument(
2159              __FUNCTION__,
2160              '3.0.0',
2161              sprintf(
2162                  /* translators: %s: misc */
2163                  __( 'The "%s" options group has been removed. Use another settings group.' ),
2164                  'misc'
2165              )
2166          );
2167          $option_group = 'general';
2168      }
2169  
2170      if ( 'privacy' === $option_group ) {
2171          _deprecated_argument(
2172              __FUNCTION__,
2173              '3.5.0',
2174              sprintf(
2175                  /* translators: %s: privacy */
2176                  __( 'The "%s" options group has been removed. Use another settings group.' ),
2177                  'privacy'
2178              )
2179          );
2180          $option_group = 'reading';
2181      }
2182  
2183      $new_whitelist_options[ $option_group ][] = $option_name;
2184      if ( ! empty( $args['sanitize_callback'] ) ) {
2185          add_filter( "sanitize_option_{$option_name}", $args['sanitize_callback'] );
2186      }
2187      if ( array_key_exists( 'default', $args ) ) {
2188          add_filter( "default_option_{$option_name}", 'filter_default_option', 10, 3 );
2189      }
2190  
2191      $wp_registered_settings[ $option_name ] = $args;
2192  }
2193  
2194  /**
2195   * Unregisters a setting.
2196   *
2197   * @since 2.7.0
2198   * @since 4.7.0 `$sanitize_callback` was deprecated. The callback from `register_setting()` is now used instead.
2199   *
2200   * @global array $new_whitelist_options
2201   * @global array $wp_registered_settings
2202   *
2203   * @param string   $option_group      The settings group name used during registration.
2204   * @param string   $option_name       The name of the option to unregister.
2205   * @param callable $deprecated        Deprecated.
2206   */
2207  function unregister_setting( $option_group, $option_name, $deprecated = '' ) {
2208      global $new_whitelist_options, $wp_registered_settings;
2209  
2210      if ( 'misc' === $option_group ) {
2211          _deprecated_argument(
2212              __FUNCTION__,
2213              '3.0.0',
2214              sprintf(
2215                  /* translators: %s: misc */
2216                  __( 'The "%s" options group has been removed. Use another settings group.' ),
2217                  'misc'
2218              )
2219          );
2220          $option_group = 'general';
2221      }
2222  
2223      if ( 'privacy' === $option_group ) {
2224          _deprecated_argument(
2225              __FUNCTION__,
2226              '3.5.0',
2227              sprintf(
2228                  /* translators: %s: privacy */
2229                  __( 'The "%s" options group has been removed. Use another settings group.' ),
2230                  'privacy'
2231              )
2232          );
2233          $option_group = 'reading';
2234      }
2235  
2236      $pos = array_search( $option_name, (array) $new_whitelist_options[ $option_group ], true );
2237      if ( false !== $pos ) {
2238          unset( $new_whitelist_options[ $option_group ][ $pos ] );
2239      }
2240      if ( '' !== $deprecated ) {
2241          _deprecated_argument(
2242              __FUNCTION__,
2243              '4.7.0',
2244              sprintf(
2245                  /* translators: 1: $sanitize_callback, 2: register_setting() */
2246                  __( '%1$s is deprecated. The callback from %2$s is used instead.' ),
2247                  '<code>$sanitize_callback</code>',
2248                  '<code>register_setting()</code>'
2249              )
2250          );
2251          remove_filter( "sanitize_option_{$option_name}", $deprecated );
2252      }
2253  
2254      if ( isset( $wp_registered_settings[ $option_name ] ) ) {
2255          // Remove the sanitize callback if one was set during registration.
2256          if ( ! empty( $wp_registered_settings[ $option_name ]['sanitize_callback'] ) ) {
2257              remove_filter( "sanitize_option_{$option_name}", $wp_registered_settings[ $option_name ]['sanitize_callback'] );
2258          }
2259  
2260          // Remove the default filter if a default was provided during registration.
2261          if ( array_key_exists( 'default', $wp_registered_settings[ $option_name ] ) ) {
2262              remove_filter( "default_option_{$option_name}", 'filter_default_option', 10 );
2263          }
2264  
2265          unset( $wp_registered_settings[ $option_name ] );
2266      }
2267  }
2268  
2269  /**
2270   * Retrieves an array of registered settings.
2271   *
2272   * @since 4.7.0
2273   *
2274   * @global array $wp_registered_settings
2275   *
2276   * @return array List of registered settings, keyed by option name.
2277   */
2278  function get_registered_settings() {
2279      global $wp_registered_settings;
2280  
2281      if ( ! is_array( $wp_registered_settings ) ) {
2282          return array();
2283      }
2284  
2285      return $wp_registered_settings;
2286  }
2287  
2288  /**
2289   * Filters the default value for the option.
2290   *
2291   * For settings which register a default setting in `register_setting()`, this
2292   * function is added as a filter to `default_option_{$option}`.
2293   *
2294   * @since 4.7.0
2295   *
2296   * @param mixed $default Existing default value to return.
2297   * @param string $option Option name.
2298   * @param bool $passed_default Was `get_option()` passed a default value?
2299   * @return mixed Filtered default value.
2300   */
2301  function filter_default_option( $default, $option, $passed_default ) {
2302      if ( $passed_default ) {
2303          return $default;
2304      }
2305  
2306      $registered = get_registered_settings();
2307      if ( empty( $registered[ $option ] ) ) {
2308          return $default;
2309      }
2310  
2311      return $registered[ $option ]['default'];
2312  }


Generated: Sat May 30 01:00:03 2020 Cross-referenced by PHPXref 0.7.1