[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

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


Generated: Tue Aug 20 08:20:01 2019 Cross-referenced by PHPXref 0.7