[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

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


Generated : Fri Aug 19 08:20:02 2022 Cross-referenced by PHPXref