[ 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` 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_value 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_value = 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 ( isset( $deprecated_keys[ $option ] ) && ! wp_installing() ) {
  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_value );
 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_value` parameter was added.
 123       *
 124       * @param mixed  $pre_option    The value to return instead of the option value. This differs from
 125       *                              `$default_value`, 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_value 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_value );
 133  
 134      /**
 135       * Filters the value of all existing options before it is retrieved.
 136       *
 137       * Returning a truthy value from the filter will effectively short-circuit retrieval
 138       * and return the passed value instead.
 139       *
 140       * @since 6.1.0
 141       *
 142       * @param mixed  $pre_option    The value to return instead of the option value. This differs from
 143       *                              `$default_value`, which is used as the fallback value in the event
 144       *                              the option doesn't exist elsewhere in get_option().
 145       *                              Default false (to skip past the short-circuit).
 146       * @param string $option        Name of the option.
 147       * @param mixed  $default_value The fallback value to return if the option does not exist.
 148       *                              Default false.
 149       */
 150      $pre = apply_filters( 'pre_option', $pre, $option, $default_value );
 151  
 152      if ( false !== $pre ) {
 153          return $pre;
 154      }
 155  
 156      if ( defined( 'WP_SETUP_CONFIG' ) ) {
 157          return false;
 158      }
 159  
 160      // Distinguish between `false` as a default, and not passing one.
 161      $passed_default = func_num_args() > 1;
 162  
 163      if ( ! wp_installing() ) {
 164          $alloptions = wp_load_alloptions();
 165  
 166          if ( isset( $alloptions[ $option ] ) ) {
 167              $value = $alloptions[ $option ];
 168          } else {
 169              $value = wp_cache_get( $option, 'options' );
 170  
 171              if ( false === $value ) {
 172                  // Prevent non-existent options from triggering multiple queries.
 173                  $notoptions = wp_cache_get( 'notoptions', 'options' );
 174  
 175                  // Prevent non-existent `notoptions` key from triggering multiple key lookups.
 176                  if ( ! is_array( $notoptions ) ) {
 177                      $notoptions = array();
 178                      wp_cache_set( 'notoptions', $notoptions, 'options' );
 179                  } elseif ( isset( $notoptions[ $option ] ) ) {
 180                      /**
 181                       * Filters the default value for an option.
 182                       *
 183                       * The dynamic portion of the hook name, `$option`, refers to the option name.
 184                       *
 185                       * @since 3.4.0
 186                       * @since 4.4.0 The `$option` parameter was added.
 187                       * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value.
 188                       *
 189                       * @param mixed  $default_value  The default value to return if the option does not exist
 190                       *                               in the database.
 191                       * @param string $option         Option name.
 192                       * @param bool   $passed_default Was `get_option()` passed a default value?
 193                       */
 194                      return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
 195                  }
 196  
 197                  $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 198  
 199                  // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
 200                  if ( is_object( $row ) ) {
 201                      $value = $row->option_value;
 202                      wp_cache_add( $option, $value, 'options' );
 203                  } else { // Option does not exist, so we must cache its non-existence.
 204                      $notoptions[ $option ] = true;
 205                      wp_cache_set( 'notoptions', $notoptions, 'options' );
 206  
 207                      /** This filter is documented in wp-includes/option.php */
 208                      return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
 209                  }
 210              }
 211          }
 212      } else {
 213          $suppress = $wpdb->suppress_errors();
 214          $row      = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 215          $wpdb->suppress_errors( $suppress );
 216  
 217          if ( is_object( $row ) ) {
 218              $value = $row->option_value;
 219          } else {
 220              /** This filter is documented in wp-includes/option.php */
 221              return apply_filters( "default_option_{$option}", $default_value, $option, $passed_default );
 222          }
 223      }
 224  
 225      // If home is not set, use siteurl.
 226      if ( 'home' === $option && '' === $value ) {
 227          return get_option( 'siteurl' );
 228      }
 229  
 230      if ( in_array( $option, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) {
 231          $value = untrailingslashit( $value );
 232      }
 233  
 234      /**
 235       * Filters the value of an existing option.
 236       *
 237       * The dynamic portion of the hook name, `$option`, refers to the option name.
 238       *
 239       * @since 1.5.0 As 'option_' . $setting
 240       * @since 3.0.0
 241       * @since 4.4.0 The `$option` parameter was added.
 242       *
 243       * @param mixed  $value  Value of the option. If stored serialized, it will be
 244       *                       unserialized prior to being returned.
 245       * @param string $option Option name.
 246       */
 247      return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
 248  }
 249  
 250  /**
 251   * Primes specific options into the cache with a single database query.
 252   *
 253   * Only options that do not already exist in cache will be loaded.
 254   *
 255   * @since 6.4.0
 256   *
 257   * @global wpdb $wpdb WordPress database abstraction object.
 258   *
 259   * @param string[] $options An array of option names to be loaded.
 260   */
 261  function wp_prime_option_caches( $options ) {
 262      global $wpdb;
 263  
 264      $alloptions     = wp_load_alloptions();
 265      $cached_options = wp_cache_get_multiple( $options, 'options' );
 266      $notoptions     = wp_cache_get( 'notoptions', 'options' );
 267      if ( ! is_array( $notoptions ) ) {
 268          $notoptions = array();
 269      }
 270  
 271      // Filter options that are not in the cache.
 272      $options_to_prime = array();
 273      foreach ( $options as $option ) {
 274          if (
 275              ( ! isset( $cached_options[ $option ] ) || false === $cached_options[ $option ] )
 276              && ! isset( $alloptions[ $option ] )
 277              && ! isset( $notoptions[ $option ] )
 278          ) {
 279              $options_to_prime[] = $option;
 280          }
 281      }
 282  
 283      // Bail early if there are no options to be loaded.
 284      if ( empty( $options_to_prime ) ) {
 285          return;
 286      }
 287  
 288      $results = $wpdb->get_results(
 289          $wpdb->prepare(
 290              sprintf(
 291                  "SELECT option_name, option_value FROM $wpdb->options WHERE option_name IN (%s)",
 292                  implode( ',', array_fill( 0, count( $options_to_prime ), '%s' ) )
 293              ),
 294              $options_to_prime
 295          )
 296      );
 297  
 298      $options_found = array();
 299      foreach ( $results as $result ) {
 300          /*
 301           * The cache is primed with the raw value (i.e. not maybe_unserialized).
 302           *
 303           * `get_option()` will handle unserializing the value as needed.
 304           */
 305          $options_found[ $result->option_name ] = $result->option_value;
 306      }
 307      wp_cache_set_multiple( $options_found, 'options' );
 308  
 309      // If all options were found, no need to update `notoptions` cache.
 310      if ( count( $options_found ) === count( $options_to_prime ) ) {
 311          return;
 312      }
 313  
 314      $options_not_found = array_diff( $options_to_prime, array_keys( $options_found ) );
 315  
 316      // Add the options that were not found to the cache.
 317      $update_notoptions = false;
 318      foreach ( $options_not_found as $option_name ) {
 319          if ( ! isset( $notoptions[ $option_name ] ) ) {
 320              $notoptions[ $option_name ] = true;
 321              $update_notoptions          = true;
 322          }
 323      }
 324  
 325      // Only update the cache if it was modified.
 326      if ( $update_notoptions ) {
 327          wp_cache_set( 'notoptions', $notoptions, 'options' );
 328      }
 329  }
 330  
 331  /**
 332   * Primes the cache of all options registered with a specific option group.
 333   *
 334   * @since 6.4.0
 335   *
 336   * @global array $new_allowed_options
 337   *
 338   * @param string $option_group The option group to load options for.
 339   */
 340  function wp_prime_option_caches_by_group( $option_group ) {
 341      global $new_allowed_options;
 342  
 343      if ( isset( $new_allowed_options[ $option_group ] ) ) {
 344          wp_prime_option_caches( $new_allowed_options[ $option_group ] );
 345      }
 346  }
 347  
 348  /**
 349   * Retrieves multiple options.
 350   *
 351   * Options are loaded as necessary first in order to use a single database query at most.
 352   *
 353   * @since 6.4.0
 354   *
 355   * @param string[] $options An array of option names to retrieve.
 356   * @return array An array of key-value pairs for the requested options.
 357   */
 358  function get_options( $options ) {
 359      wp_prime_option_caches( $options );
 360  
 361      $result = array();
 362      foreach ( $options as $option ) {
 363          $result[ $option ] = get_option( $option );
 364      }
 365  
 366      return $result;
 367  }
 368  
 369  /**
 370   * Sets the autoload values for multiple options in the database.
 371   *
 372   * Autoloading too many options can lead to performance problems, especially if the options are not frequently used.
 373   * This function allows modifying the autoload value for multiple options without changing the actual option value.
 374   * This is for example recommended for plugin activation and deactivation hooks, to ensure any options exclusively used
 375   * by the plugin which are generally autoloaded can be set to not autoload when the plugin is inactive.
 376   *
 377   * @since 6.4.0
 378   * @since 6.7.0 The autoload values 'yes' and 'no' are deprecated.
 379   *
 380   * @global wpdb $wpdb WordPress database abstraction object.
 381   *
 382   * @param array $options Associative array of option names and their autoload values to set. The option names are
 383   *                       expected to not be SQL-escaped. The autoload values should be boolean values. For backward
 384   *                       compatibility 'yes' and 'no' are also accepted, though using these values is deprecated.
 385   * @return array Associative array of all provided $options as keys and boolean values for whether their autoload value
 386   *               was updated.
 387   */
 388  function wp_set_option_autoload_values( array $options ) {
 389      global $wpdb;
 390  
 391      if ( ! $options ) {
 392          return array();
 393      }
 394  
 395      $grouped_options = array(
 396          'on'  => array(),
 397          'off' => array(),
 398      );
 399      $results         = array();
 400      foreach ( $options as $option => $autoload ) {
 401          wp_protect_special_option( $option ); // Ensure only valid options can be passed.
 402  
 403          /*
 404           * Sanitize autoload value and categorize accordingly.
 405           * The values 'yes', 'no', 'on', and 'off' are supported for backward compatibility.
 406           */
 407          if ( 'off' === $autoload || 'no' === $autoload || false === $autoload ) {
 408              $grouped_options['off'][] = $option;
 409          } else {
 410              $grouped_options['on'][] = $option;
 411          }
 412          $results[ $option ] = false; // Initialize result value.
 413      }
 414  
 415      $where      = array();
 416      $where_args = array();
 417      foreach ( $grouped_options as $autoload => $options ) {
 418          if ( ! $options ) {
 419              continue;
 420          }
 421          $placeholders = implode( ',', array_fill( 0, count( $options ), '%s' ) );
 422          $where[]      = "autoload != '%s' AND option_name IN ($placeholders)";
 423          $where_args[] = $autoload;
 424          foreach ( $options as $option ) {
 425              $where_args[] = $option;
 426          }
 427      }
 428      $where = 'WHERE ' . implode( ' OR ', $where );
 429  
 430      /*
 431       * Determine the relevant options that do not already use the given autoload value.
 432       * If no options are returned, no need to update.
 433       */
 434      // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
 435      $options_to_update = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options $where", $where_args ) );
 436      if ( ! $options_to_update ) {
 437          return $results;
 438      }
 439  
 440      // Run UPDATE queries as needed (maximum 2) to update the relevant options' autoload values to 'yes' or 'no'.
 441      foreach ( $grouped_options as $autoload => $options ) {
 442          if ( ! $options ) {
 443              continue;
 444          }
 445          $options                      = array_intersect( $options, $options_to_update );
 446          $grouped_options[ $autoload ] = $options;
 447          if ( ! $grouped_options[ $autoload ] ) {
 448              continue;
 449          }
 450  
 451          // Run query to update autoload value for all the options where it is needed.
 452          $success = $wpdb->query(
 453              $wpdb->prepare(
 454                  "UPDATE $wpdb->options SET autoload = %s WHERE option_name IN (" . implode( ',', array_fill( 0, count( $grouped_options[ $autoload ] ), '%s' ) ) . ')',
 455                  array_merge(
 456                      array( $autoload ),
 457                      $grouped_options[ $autoload ]
 458                  )
 459              )
 460          );
 461          if ( ! $success ) {
 462              // Set option list to an empty array to indicate no options were updated.
 463              $grouped_options[ $autoload ] = array();
 464              continue;
 465          }
 466  
 467          // Assume that on success all options were updated, which should be the case given only new values are sent.
 468          foreach ( $grouped_options[ $autoload ] as $option ) {
 469              $results[ $option ] = true;
 470          }
 471      }
 472  
 473      /*
 474       * If any options were changed to 'on', delete their individual caches, and delete 'alloptions' cache so that it
 475       * is refreshed as needed.
 476       * If no options were changed to 'on' but any options were changed to 'no', delete them from the 'alloptions'
 477       * cache. This is not necessary when options were changed to 'on', since in that situation the entire cache is
 478       * deleted anyway.
 479       */
 480      if ( $grouped_options['on'] ) {
 481          wp_cache_delete_multiple( $grouped_options['on'], 'options' );
 482          wp_cache_delete( 'alloptions', 'options' );
 483      } elseif ( $grouped_options['off'] ) {
 484          $alloptions = wp_load_alloptions( true );
 485  
 486          foreach ( $grouped_options['off'] as $option ) {
 487              if ( isset( $alloptions[ $option ] ) ) {
 488                  unset( $alloptions[ $option ] );
 489              }
 490          }
 491  
 492          wp_cache_set( 'alloptions', $alloptions, 'options' );
 493      }
 494  
 495      return $results;
 496  }
 497  
 498  /**
 499   * Sets the autoload value for multiple options in the database.
 500   *
 501   * This is a wrapper for {@see wp_set_option_autoload_values()}, which can be used to set different autoload values for
 502   * each option at once.
 503   *
 504   * @since 6.4.0
 505   * @since 6.7.0 The autoload values 'yes' and 'no' are deprecated.
 506   *
 507   * @see wp_set_option_autoload_values()
 508   *
 509   * @param string[] $options  List of option names. Expected to not be SQL-escaped.
 510   * @param bool     $autoload Autoload value to control whether to load the options when WordPress starts up.
 511   *                           For backward compatibility 'yes' and 'no' are also accepted, though using these values is
 512   *                           deprecated.
 513   * @return array Associative array of all provided $options as keys and boolean values for whether their autoload value
 514   *               was updated.
 515   */
 516  function wp_set_options_autoload( array $options, $autoload ) {
 517      return wp_set_option_autoload_values(
 518          array_fill_keys( $options, $autoload )
 519      );
 520  }
 521  
 522  /**
 523   * Sets the autoload value for an option in the database.
 524   *
 525   * This is a wrapper for {@see wp_set_option_autoload_values()}, which can be used to set the autoload value for
 526   * multiple options at once.
 527   *
 528   * @since 6.4.0
 529   * @since 6.7.0 The autoload values 'yes' and 'no' are deprecated.
 530   *
 531   * @see wp_set_option_autoload_values()
 532   *
 533   * @param string $option   Name of the option. Expected to not be SQL-escaped.
 534   * @param bool   $autoload Autoload value to control whether to load the option when WordPress starts up.
 535   *                         For backward compatibility 'yes' and 'no' are also accepted, though using these values is
 536   *                         deprecated.
 537   * @return bool True if the autoload value was modified, false otherwise.
 538   */
 539  function wp_set_option_autoload( $option, $autoload ) {
 540      $result = wp_set_option_autoload_values( array( $option => $autoload ) );
 541      if ( isset( $result[ $option ] ) ) {
 542          return $result[ $option ];
 543      }
 544      return false;
 545  }
 546  
 547  /**
 548   * Protects WordPress special option from being modified.
 549   *
 550   * Will die if $option is in protected list. Protected options are 'alloptions'
 551   * and 'notoptions' options.
 552   *
 553   * @since 2.2.0
 554   *
 555   * @param string $option Option name.
 556   */
 557  function wp_protect_special_option( $option ) {
 558      if ( 'alloptions' === $option || 'notoptions' === $option ) {
 559          wp_die(
 560              sprintf(
 561                  /* translators: %s: Option name. */
 562                  __( '%s is a protected WP option and may not be modified' ),
 563                  esc_html( $option )
 564              )
 565          );
 566      }
 567  }
 568  
 569  /**
 570   * Prints option value after sanitizing for forms.
 571   *
 572   * @since 1.5.0
 573   *
 574   * @param string $option Option name.
 575   */
 576  function form_option( $option ) {
 577      echo esc_attr( get_option( $option ) );
 578  }
 579  
 580  /**
 581   * Loads and caches all autoloaded options, if available or all options.
 582   *
 583   * @since 2.2.0
 584   * @since 5.3.1 The `$force_cache` parameter was added.
 585   *
 586   * @global wpdb $wpdb WordPress database abstraction object.
 587   *
 588   * @param bool $force_cache Optional. Whether to force an update of the local cache
 589   *                          from the persistent cache. Default false.
 590   * @return array List of all options.
 591   */
 592  function wp_load_alloptions( $force_cache = false ) {
 593      global $wpdb;
 594  
 595      /**
 596       * Filters the array of alloptions before it is populated.
 597       *
 598       * Returning an array from the filter will effectively short circuit
 599       * wp_load_alloptions(), returning that value instead.
 600       *
 601       * @since 6.2.0
 602       *
 603       * @param array|null $alloptions  An array of alloptions. Default null.
 604       * @param bool       $force_cache Whether to force an update of the local cache from the persistent cache. Default false.
 605       */
 606      $alloptions = apply_filters( 'pre_wp_load_alloptions', null, $force_cache );
 607      if ( is_array( $alloptions ) ) {
 608          return $alloptions;
 609      }
 610  
 611      if ( ! wp_installing() || ! is_multisite() ) {
 612          $alloptions = wp_cache_get( 'alloptions', 'options', $force_cache );
 613      } else {
 614          $alloptions = false;
 615      }
 616  
 617      if ( ! $alloptions ) {
 618          $suppress      = $wpdb->suppress_errors();
 619          $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload IN ( '" . implode( "', '", esc_sql( wp_autoload_values_to_autoload() ) ) . "' )" );
 620  
 621          if ( ! $alloptions_db ) {
 622              $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 623          }
 624          $wpdb->suppress_errors( $suppress );
 625  
 626          $alloptions = array();
 627          foreach ( (array) $alloptions_db as $o ) {
 628              $alloptions[ $o->option_name ] = $o->option_value;
 629          }
 630  
 631          if ( ! wp_installing() || ! is_multisite() ) {
 632              /**
 633               * Filters all options before caching them.
 634               *
 635               * @since 4.9.0
 636               *
 637               * @param array $alloptions Array with all options.
 638               */
 639              $alloptions = apply_filters( 'pre_cache_alloptions', $alloptions );
 640  
 641              wp_cache_add( 'alloptions', $alloptions, 'options' );
 642          }
 643      }
 644  
 645      /**
 646       * Filters all options after retrieving them.
 647       *
 648       * @since 4.9.0
 649       *
 650       * @param array $alloptions Array with all options.
 651       */
 652      return apply_filters( 'alloptions', $alloptions );
 653  }
 654  
 655  /**
 656   * Primes specific network options for the current network into the cache with a single database query.
 657   *
 658   * Only network options that do not already exist in cache will be loaded.
 659   *
 660   * If site is not multisite, then call wp_prime_option_caches().
 661   *
 662   * @since 6.6.0
 663   *
 664   * @see wp_prime_network_option_caches()
 665   *
 666   * @param string[] $options An array of option names to be loaded.
 667   */
 668  function wp_prime_site_option_caches( array $options ) {
 669      wp_prime_network_option_caches( null, $options );
 670  }
 671  
 672  /**
 673   * Primes specific network options into the cache with a single database query.
 674   *
 675   * Only network options that do not already exist in cache will be loaded.
 676   *
 677   * If site is not multisite, then call wp_prime_option_caches().
 678   *
 679   * @since 6.6.0
 680   *
 681   * @global wpdb $wpdb WordPress database abstraction object.
 682   *
 683   * @param int      $network_id ID of the network. Can be null to default to the current network ID.
 684   * @param string[] $options    An array of option names to be loaded.
 685   */
 686  function wp_prime_network_option_caches( $network_id, array $options ) {
 687      global $wpdb;
 688  
 689      if ( wp_installing() ) {
 690          return;
 691      }
 692  
 693      if ( ! is_multisite() ) {
 694          wp_prime_option_caches( $options );
 695          return;
 696      }
 697  
 698      if ( $network_id && ! is_numeric( $network_id ) ) {
 699          return;
 700      }
 701  
 702      $network_id = (int) $network_id;
 703  
 704      // Fallback to the current network if a network ID is not specified.
 705      if ( ! $network_id ) {
 706          $network_id = get_current_network_id();
 707      }
 708  
 709      $cache_keys = array();
 710      foreach ( $options as $option ) {
 711          $cache_keys[ $option ] = "{$network_id}:{$option}";
 712      }
 713  
 714      $cache_group    = 'site-options';
 715      $cached_options = wp_cache_get_multiple( array_values( $cache_keys ), $cache_group );
 716  
 717      $notoptions_key = "$network_id:notoptions";
 718      $notoptions     = wp_cache_get( $notoptions_key, $cache_group );
 719  
 720      if ( ! is_array( $notoptions ) ) {
 721          $notoptions = array();
 722      }
 723  
 724      // Filter options that are not in the cache.
 725      $options_to_prime = array();
 726      foreach ( $cache_keys as $option => $cache_key ) {
 727          if (
 728              ( ! isset( $cached_options[ $cache_key ] ) || false === $cached_options[ $cache_key ] )
 729              && ! isset( $notoptions[ $option ] )
 730          ) {
 731              $options_to_prime[] = $option;
 732          }
 733      }
 734  
 735      // Bail early if there are no options to be loaded.
 736      if ( empty( $options_to_prime ) ) {
 737          return;
 738      }
 739  
 740      $query_args   = $options_to_prime;
 741      $query_args[] = $network_id;
 742      $results      = $wpdb->get_results(
 743          $wpdb->prepare(
 744              sprintf(
 745                  "SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN (%s) AND site_id = %s",
 746                  implode( ',', array_fill( 0, count( $options_to_prime ), '%s' ) ),
 747                  '%d'
 748              ),
 749              $query_args
 750          )
 751      );
 752  
 753      $data          = array();
 754      $options_found = array();
 755      foreach ( $results as $result ) {
 756          $key                = $result->meta_key;
 757          $cache_key          = $cache_keys[ $key ];
 758          $data[ $cache_key ] = maybe_unserialize( $result->meta_value );
 759          $options_found[]    = $key;
 760      }
 761      wp_cache_set_multiple( $data, $cache_group );
 762      // If all options were found, no need to update `notoptions` cache.
 763      if ( count( $options_found ) === count( $options_to_prime ) ) {
 764          return;
 765      }
 766  
 767      $options_not_found = array_diff( $options_to_prime, $options_found );
 768  
 769      // Add the options that were not found to the cache.
 770      $update_notoptions = false;
 771      foreach ( $options_not_found as $option_name ) {
 772          if ( ! isset( $notoptions[ $option_name ] ) ) {
 773              $notoptions[ $option_name ] = true;
 774              $update_notoptions          = true;
 775          }
 776      }
 777  
 778      // Only update the cache if it was modified.
 779      if ( $update_notoptions ) {
 780          wp_cache_set( $notoptions_key, $notoptions, $cache_group );
 781      }
 782  }
 783  
 784  /**
 785   * Loads and primes caches of certain often requested network options if is_multisite().
 786   *
 787   * @since 3.0.0
 788   * @since 6.3.0 Also prime caches for network options when persistent object cache is enabled.
 789   * @since 6.6.0 Uses wp_prime_network_option_caches().
 790   *
 791   * @param int $network_id Optional. Network ID of network for which to prime network options cache. Defaults to current network.
 792   */
 793  function wp_load_core_site_options( $network_id = null ) {
 794      if ( ! is_multisite() || wp_installing() ) {
 795          return;
 796      }
 797      $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', 'WPLANG' );
 798  
 799      wp_prime_network_option_caches( $network_id, $core_options );
 800  }
 801  
 802  /**
 803   * Updates the value of an option that was already added.
 804   *
 805   * You do not need to serialize values. If the value needs to be serialized,
 806   * then it will be serialized before it is inserted into the database.
 807   * Remember, resources cannot be serialized or added as an option.
 808   *
 809   * If the option does not exist, it will be created.
 810  
 811   * This function is designed to work with or without a logged-in user. In terms of security,
 812   * plugin developers should check the current user's capabilities before updating any options.
 813   *
 814   * @since 1.0.0
 815   * @since 4.2.0 The `$autoload` parameter was added.
 816   * @since 6.7.0 The autoload values 'yes' and 'no' are deprecated.
 817   *
 818   * @global wpdb $wpdb WordPress database abstraction object.
 819   *
 820   * @param string    $option   Name of the option to update. Expected to not be SQL-escaped.
 821   * @param mixed     $value    Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
 822   * @param bool|null $autoload Optional. Whether to load the option when WordPress starts up.
 823   *                            Accepts a boolean, or `null` to stick with the initial value or, if no initial value is
 824   *                            set, to leave the decision up to default heuristics in WordPress.
 825   *                            For existing options, `$autoload` can only be updated using `update_option()` if `$value`
 826   *                            is also changed.
 827   *                            For backward compatibility 'yes' and 'no' are also accepted, though using these values is
 828   *                            deprecated.
 829   *                            Autoloading too many options can lead to performance problems, especially if the
 830   *                            options are not frequently used. For options which are accessed across several places
 831   *                            in the frontend, it is recommended to autoload them, by using true.
 832   *                            For options which are accessed only on few specific URLs, it is recommended
 833   *                            to not autoload them, by using false.
 834   *                            For non-existent options, the default is null, which means WordPress will determine
 835   *                            the autoload value.
 836   * @return bool True if the value was updated, false otherwise.
 837   */
 838  function update_option( $option, $value, $autoload = null ) {
 839      global $wpdb;
 840  
 841      if ( is_scalar( $option ) ) {
 842          $option = trim( $option );
 843      }
 844  
 845      if ( empty( $option ) ) {
 846          return false;
 847      }
 848  
 849      /*
 850       * Until a proper _deprecated_option() function can be introduced,
 851       * redirect requests to deprecated keys to the new, correct ones.
 852       */
 853      $deprecated_keys = array(
 854          'blacklist_keys'    => 'disallowed_keys',
 855          'comment_whitelist' => 'comment_previously_approved',
 856      );
 857  
 858      if ( isset( $deprecated_keys[ $option ] ) && ! wp_installing() ) {
 859          _deprecated_argument(
 860              __FUNCTION__,
 861              '5.5.0',
 862              sprintf(
 863                  /* translators: 1: Deprecated option key, 2: New option key. */
 864                  __( 'The "%1$s" option key has been renamed to "%2$s".' ),
 865                  $option,
 866                  $deprecated_keys[ $option ]
 867              )
 868          );
 869          return update_option( $deprecated_keys[ $option ], $value, $autoload );
 870      }
 871  
 872      wp_protect_special_option( $option );
 873  
 874      if ( is_object( $value ) ) {
 875          $value = clone $value;
 876      }
 877  
 878      $value     = sanitize_option( $option, $value );
 879      $old_value = get_option( $option );
 880  
 881      /**
 882       * Filters a specific option before its value is (maybe) serialized and updated.
 883       *
 884       * The dynamic portion of the hook name, `$option`, refers to the option name.
 885       *
 886       * @since 2.6.0
 887       * @since 4.4.0 The `$option` parameter was added.
 888       *
 889       * @param mixed  $value     The new, unserialized option value.
 890       * @param mixed  $old_value The old option value.
 891       * @param string $option    Option name.
 892       */
 893      $value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
 894  
 895      /**
 896       * Filters an option before its value is (maybe) serialized and updated.
 897       *
 898       * @since 3.9.0
 899       *
 900       * @param mixed  $value     The new, unserialized option value.
 901       * @param string $option    Name of the option.
 902       * @param mixed  $old_value The old option value.
 903       */
 904      $value = apply_filters( 'pre_update_option', $value, $option, $old_value );
 905  
 906      /*
 907       * If the new and old values are the same, no need to update.
 908       *
 909       * Unserialized values will be adequate in most cases. If the unserialized
 910       * data differs, the (maybe) serialized data is checked to avoid
 911       * unnecessary database calls for otherwise identical object instances.
 912       *
 913       * See https://core.trac.wordpress.org/ticket/38903
 914       */
 915      if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
 916          return false;
 917      }
 918  
 919      /** This filter is documented in wp-includes/option.php */
 920      if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
 921          return add_option( $option, $value, '', $autoload );
 922      }
 923  
 924      $serialized_value = maybe_serialize( $value );
 925  
 926      /**
 927       * Fires immediately before an option value is updated.
 928       *
 929       * @since 2.9.0
 930       *
 931       * @param string $option    Name of the option to update.
 932       * @param mixed  $old_value The old option value.
 933       * @param mixed  $value     The new option value.
 934       */
 935      do_action( 'update_option', $option, $old_value, $value );
 936  
 937      $update_args = array(
 938          'option_value' => $serialized_value,
 939      );
 940  
 941      if ( null !== $autoload ) {
 942          $update_args['autoload'] = wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload );
 943      } else {
 944          // Retrieve the current autoload value to reevaluate it in case it was set automatically.
 945          $raw_autoload = $wpdb->get_var( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 946          $allow_values = array( 'auto-on', 'auto-off', 'auto' );
 947          if ( in_array( $raw_autoload, $allow_values, true ) ) {
 948              $autoload = wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload );
 949              if ( $autoload !== $raw_autoload ) {
 950                  $update_args['autoload'] = $autoload;
 951              }
 952          }
 953      }
 954  
 955      $result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
 956      if ( ! $result ) {
 957          return false;
 958      }
 959  
 960      $notoptions = wp_cache_get( 'notoptions', 'options' );
 961  
 962      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
 963          unset( $notoptions[ $option ] );
 964          wp_cache_set( 'notoptions', $notoptions, 'options' );
 965      }
 966  
 967      if ( ! wp_installing() ) {
 968          if ( ! isset( $update_args['autoload'] ) ) {
 969              // Update the cached value based on where it is currently cached.
 970              $alloptions = wp_load_alloptions( true );
 971  
 972              if ( isset( $alloptions[ $option ] ) ) {
 973                  $alloptions[ $option ] = $serialized_value;
 974                  wp_cache_set( 'alloptions', $alloptions, 'options' );
 975              } else {
 976                  wp_cache_set( $option, $serialized_value, 'options' );
 977              }
 978          } elseif ( in_array( $update_args['autoload'], wp_autoload_values_to_autoload(), true ) ) {
 979              // Delete the individual cache, then set in alloptions cache.
 980              wp_cache_delete( $option, 'options' );
 981  
 982              $alloptions = wp_load_alloptions( true );
 983  
 984              $alloptions[ $option ] = $serialized_value;
 985              wp_cache_set( 'alloptions', $alloptions, 'options' );
 986          } else {
 987              // Delete the alloptions cache, then set the individual cache.
 988              $alloptions = wp_load_alloptions( true );
 989  
 990              if ( isset( $alloptions[ $option ] ) ) {
 991                  unset( $alloptions[ $option ] );
 992                  wp_cache_set( 'alloptions', $alloptions, 'options' );
 993              }
 994  
 995              wp_cache_set( $option, $serialized_value, 'options' );
 996          }
 997      }
 998  
 999      /**
1000       * Fires after the value of a specific option has been successfully updated.
1001       *
1002       * The dynamic portion of the hook name, `$option`, refers to the option name.
1003       *
1004       * @since 2.0.1
1005       * @since 4.4.0 The `$option` parameter was added.
1006       *
1007       * @param mixed  $old_value The old option value.
1008       * @param mixed  $value     The new option value.
1009       * @param string $option    Option name.
1010       */
1011      do_action( "update_option_{$option}", $old_value, $value, $option );
1012  
1013      /**
1014       * Fires after the value of an option has been successfully updated.
1015       *
1016       * @since 2.9.0
1017       *
1018       * @param string $option    Name of the updated option.
1019       * @param mixed  $old_value The old option value.
1020       * @param mixed  $value     The new option value.
1021       */
1022      do_action( 'updated_option', $option, $old_value, $value );
1023  
1024      return true;
1025  }
1026  
1027  /**
1028   * Adds a new option.
1029   *
1030   * You do not need to serialize values. If the value needs to be serialized,
1031   * then it will be serialized before it is inserted into the database.
1032   * Remember, resources cannot be serialized or added as an option.
1033   *
1034   * You can create options without values and then update the values later.
1035   * Existing options will not be updated and checks are performed to ensure that you
1036   * aren't adding a protected WordPress option. Care should be taken to not name
1037   * options the same as the ones which are protected.
1038   *
1039   * @since 1.0.0
1040   * @since 6.6.0 The $autoload parameter's default value was changed to null.
1041   * @since 6.7.0 The autoload values 'yes' and 'no' are deprecated.
1042   *
1043   * @global wpdb $wpdb WordPress database abstraction object.
1044   *
1045   * @param string    $option     Name of the option to add. Expected to not be SQL-escaped.
1046   * @param mixed     $value      Optional. Option value. Must be serializable if non-scalar.
1047   *                              Expected to not be SQL-escaped.
1048   * @param string    $deprecated Optional. Description. Not used anymore.
1049   * @param bool|null $autoload   Optional. Whether to load the option when WordPress starts up.
1050   *                              Accepts a boolean, or `null` to leave the decision up to default heuristics in
1051   *                              WordPress. For backward compatibility 'yes' and 'no' are also accepted, though using
1052   *                              these values is deprecated.
1053   *                              Autoloading too many options can lead to performance problems, especially if the
1054   *                              options are not frequently used. For options which are accessed across several places
1055   *                              in the frontend, it is recommended to autoload them, by using true.
1056   *                              For options which are accessed only on few specific URLs, it is recommended
1057   *                              to not autoload them, by using false.
1058   *                              Default is null, which means WordPress will determine the autoload value.
1059   * @return bool True if the option was added, false otherwise.
1060   */
1061  function add_option( $option, $value = '', $deprecated = '', $autoload = null ) {
1062      global $wpdb;
1063  
1064      if ( ! empty( $deprecated ) ) {
1065          _deprecated_argument( __FUNCTION__, '2.3.0' );
1066      }
1067  
1068      if ( is_scalar( $option ) ) {
1069          $option = trim( $option );
1070      }
1071  
1072      if ( empty( $option ) ) {
1073          return false;
1074      }
1075  
1076      /*
1077       * Until a proper _deprecated_option() function can be introduced,
1078       * redirect requests to deprecated keys to the new, correct ones.
1079       */
1080      $deprecated_keys = array(
1081          'blacklist_keys'    => 'disallowed_keys',
1082          'comment_whitelist' => 'comment_previously_approved',
1083      );
1084  
1085      if ( isset( $deprecated_keys[ $option ] ) && ! wp_installing() ) {
1086          _deprecated_argument(
1087              __FUNCTION__,
1088              '5.5.0',
1089              sprintf(
1090                  /* translators: 1: Deprecated option key, 2: New option key. */
1091                  __( 'The "%1$s" option key has been renamed to "%2$s".' ),
1092                  $option,
1093                  $deprecated_keys[ $option ]
1094              )
1095          );
1096          return add_option( $deprecated_keys[ $option ], $value, $deprecated, $autoload );
1097      }
1098  
1099      wp_protect_special_option( $option );
1100  
1101      if ( is_object( $value ) ) {
1102          $value = clone $value;
1103      }
1104  
1105      $value = sanitize_option( $option, $value );
1106  
1107      /*
1108       * Make sure the option doesn't already exist.
1109       * We can check the 'notoptions' cache before we ask for a DB query.
1110       */
1111      $notoptions = wp_cache_get( 'notoptions', 'options' );
1112  
1113      if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
1114          /** This filter is documented in wp-includes/option.php */
1115          if ( apply_filters( "default_option_{$option}", false, $option, false ) !== get_option( $option ) ) {
1116              return false;
1117          }
1118      }
1119  
1120      $serialized_value = maybe_serialize( $value );
1121  
1122      $autoload = wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload );
1123  
1124      /**
1125       * Fires before an option is added.
1126       *
1127       * @since 2.9.0
1128       *
1129       * @param string $option Name of the option to add.
1130       * @param mixed  $value  Value of the option.
1131       */
1132      do_action( 'add_option', $option, $value );
1133  
1134      $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 ) );
1135      if ( ! $result ) {
1136          return false;
1137      }
1138  
1139      if ( ! wp_installing() ) {
1140          if ( in_array( $autoload, wp_autoload_values_to_autoload(), true ) ) {
1141              $alloptions            = wp_load_alloptions( true );
1142              $alloptions[ $option ] = $serialized_value;
1143              wp_cache_set( 'alloptions', $alloptions, 'options' );
1144          } else {
1145              wp_cache_set( $option, $serialized_value, 'options' );
1146          }
1147      }
1148  
1149      // This option exists now.
1150      $notoptions = wp_cache_get( 'notoptions', 'options' ); // Yes, again... we need it to be fresh.
1151  
1152      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1153          unset( $notoptions[ $option ] );
1154          wp_cache_set( 'notoptions', $notoptions, 'options' );
1155      }
1156  
1157      /**
1158       * Fires after a specific option has been added.
1159       *
1160       * The dynamic portion of the hook name, `$option`, refers to the option name.
1161       *
1162       * @since 2.5.0 As "add_option_{$name}"
1163       * @since 3.0.0
1164       *
1165       * @param string $option Name of the option to add.
1166       * @param mixed  $value  Value of the option.
1167       */
1168      do_action( "add_option_{$option}", $option, $value );
1169  
1170      /**
1171       * Fires after an option has been added.
1172       *
1173       * @since 2.9.0
1174       *
1175       * @param string $option Name of the added option.
1176       * @param mixed  $value  Value of the option.
1177       */
1178      do_action( 'added_option', $option, $value );
1179  
1180      return true;
1181  }
1182  
1183  /**
1184   * Removes an option by name. Prevents removal of protected WordPress options.
1185   *
1186   * @since 1.2.0
1187   *
1188   * @global wpdb $wpdb WordPress database abstraction object.
1189   *
1190   * @param string $option Name of the option to delete. Expected to not be SQL-escaped.
1191   * @return bool True if the option was deleted, false otherwise.
1192   */
1193  function delete_option( $option ) {
1194      global $wpdb;
1195  
1196      if ( is_scalar( $option ) ) {
1197          $option = trim( $option );
1198      }
1199  
1200      if ( empty( $option ) ) {
1201          return false;
1202      }
1203  
1204      wp_protect_special_option( $option );
1205  
1206      // Get the ID, if no ID then return.
1207      $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
1208      if ( is_null( $row ) ) {
1209          return false;
1210      }
1211  
1212      /**
1213       * Fires immediately before an option is deleted.
1214       *
1215       * @since 2.9.0
1216       *
1217       * @param string $option Name of the option to delete.
1218       */
1219      do_action( 'delete_option', $option );
1220  
1221      $result = $wpdb->delete( $wpdb->options, array( 'option_name' => $option ) );
1222  
1223      if ( ! wp_installing() ) {
1224          if ( in_array( $row->autoload, wp_autoload_values_to_autoload(), true ) ) {
1225              $alloptions = wp_load_alloptions( true );
1226  
1227              if ( is_array( $alloptions ) && isset( $alloptions[ $option ] ) ) {
1228                  unset( $alloptions[ $option ] );
1229                  wp_cache_set( 'alloptions', $alloptions, 'options' );
1230              }
1231          } else {
1232              wp_cache_delete( $option, 'options' );
1233          }
1234  
1235          $notoptions = wp_cache_get( 'notoptions', 'options' );
1236  
1237          if ( ! is_array( $notoptions ) ) {
1238              $notoptions = array();
1239          }
1240          $notoptions[ $option ] = true;
1241  
1242          wp_cache_set( 'notoptions', $notoptions, 'options' );
1243      }
1244  
1245      if ( $result ) {
1246  
1247          /**
1248           * Fires after a specific option has been deleted.
1249           *
1250           * The dynamic portion of the hook name, `$option`, refers to the option name.
1251           *
1252           * @since 3.0.0
1253           *
1254           * @param string $option Name of the deleted option.
1255           */
1256          do_action( "delete_option_{$option}", $option );
1257  
1258          /**
1259           * Fires after an option has been deleted.
1260           *
1261           * @since 2.9.0
1262           *
1263           * @param string $option Name of the deleted option.
1264           */
1265          do_action( 'deleted_option', $option );
1266  
1267          return true;
1268      }
1269  
1270      return false;
1271  }
1272  
1273  /**
1274   *  Determines the appropriate autoload value for an option based on input.
1275   *
1276   *  This function checks the provided autoload value and returns a standardized value
1277   *  ('on', 'off', 'auto-on', 'auto-off', or 'auto') based on specific conditions.
1278   *
1279   * If no explicit autoload value is provided, the function will check for certain heuristics around the given option.
1280   * It will return `auto-on` to indicate autoloading, `auto-off` to indicate not autoloading, or `auto` if no clear
1281   * decision could be made.
1282   *
1283   * @since 6.6.0
1284   * @access private
1285   *
1286   * @param string $option          The name of the option.
1287   * @param mixed $value            The value of the option to check its autoload value.
1288   * @param mixed $serialized_value The serialized value of the option to check its autoload value.
1289   * @param bool|null $autoload     The autoload value to check.
1290   *                                Accepts 'on'|true to enable or 'off'|false to disable, or
1291   *                                'auto-on', 'auto-off', or 'auto' for internal purposes.
1292   *                                Any other autoload value will be forced to either 'auto-on',
1293   *                                'auto-off', or 'auto'.
1294   *                                'yes' and 'no' are supported for backward compatibility.
1295   * @return string Returns the original $autoload value if explicit, or 'auto-on', 'auto-off',
1296   *                or 'auto' depending on default heuristics.
1297   */
1298  function wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload ) {
1299  
1300      // Check if autoload is a boolean.
1301      if ( is_bool( $autoload ) ) {
1302          return $autoload ? 'on' : 'off';
1303      }
1304  
1305      switch ( $autoload ) {
1306          case 'on':
1307          case 'yes':
1308              return 'on';
1309          case 'off':
1310          case 'no':
1311              return 'off';
1312      }
1313  
1314      /**
1315       * Allows to determine the default autoload value for an option where no explicit value is passed.
1316       *
1317       * @since 6.6.0
1318       *
1319       * @param bool|null $autoload The default autoload value to set. Returning true will be set as 'auto-on' in the
1320       *                            database, false will be set as 'auto-off', and null will be set as 'auto'.
1321       * @param string    $option   The passed option name.
1322       * @param mixed     $value    The passed option value to be saved.
1323       */
1324      $autoload = apply_filters( 'wp_default_autoload_value', null, $option, $value, $serialized_value );
1325      if ( is_bool( $autoload ) ) {
1326          return $autoload ? 'auto-on' : 'auto-off';
1327      }
1328  
1329      return 'auto';
1330  }
1331  
1332  /**
1333   * Filters the default autoload value to disable autoloading if the option value is too large.
1334   *
1335   * @since 6.6.0
1336   * @access private
1337   *
1338   * @param bool|null $autoload         The default autoload value to set.
1339   * @param string    $option           The passed option name.
1340   * @param mixed     $value            The passed option value to be saved.
1341   * @param mixed     $serialized_value The passed option value to be saved, in serialized form.
1342   * @return bool|null Potentially modified $default.
1343   */
1344  function wp_filter_default_autoload_value_via_option_size( $autoload, $option, $value, $serialized_value ) {
1345      /**
1346       * Filters the maximum size of option value in bytes.
1347       *
1348       * @since 6.6.0
1349       *
1350       * @param int    $max_option_size The option-size threshold, in bytes. Default 150000.
1351       * @param string $option          The name of the option.
1352       */
1353      $max_option_size = (int) apply_filters( 'wp_max_autoloaded_option_size', 150000, $option );
1354      $size            = ! empty( $serialized_value ) ? strlen( $serialized_value ) : 0;
1355  
1356      if ( $size > $max_option_size ) {
1357          return false;
1358      }
1359  
1360      return $autoload;
1361  }
1362  
1363  /**
1364   * Deletes a transient.
1365   *
1366   * @since 2.8.0
1367   *
1368   * @param string $transient Transient name. Expected to not be SQL-escaped.
1369   * @return bool True if the transient was deleted, false otherwise.
1370   */
1371  function delete_transient( $transient ) {
1372  
1373      /**
1374       * Fires immediately before a specific transient is deleted.
1375       *
1376       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1377       *
1378       * @since 3.0.0
1379       *
1380       * @param string $transient Transient name.
1381       */
1382      do_action( "delete_transient_{$transient}", $transient );
1383  
1384      if ( wp_using_ext_object_cache() || wp_installing() ) {
1385          $result = wp_cache_delete( $transient, 'transient' );
1386      } else {
1387          $option_timeout = '_transient_timeout_' . $transient;
1388          $option         = '_transient_' . $transient;
1389          $result         = delete_option( $option );
1390  
1391          if ( $result ) {
1392              delete_option( $option_timeout );
1393          }
1394      }
1395  
1396      if ( $result ) {
1397  
1398          /**
1399           * Fires after a transient is deleted.
1400           *
1401           * @since 3.0.0
1402           *
1403           * @param string $transient Deleted transient name.
1404           */
1405          do_action( 'deleted_transient', $transient );
1406      }
1407  
1408      return $result;
1409  }
1410  
1411  /**
1412   * Retrieves the value of a transient.
1413   *
1414   * If the transient does not exist, does not have a value, or has expired,
1415   * then the return value will be false.
1416   *
1417   * @since 2.8.0
1418   *
1419   * @param string $transient Transient name. Expected to not be SQL-escaped.
1420   * @return mixed Value of transient.
1421   */
1422  function get_transient( $transient ) {
1423  
1424      /**
1425       * Filters the value of an existing transient before it is retrieved.
1426       *
1427       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1428       *
1429       * Returning a value other than false from the filter will short-circuit retrieval
1430       * and return that value instead.
1431       *
1432       * @since 2.8.0
1433       * @since 4.4.0 The `$transient` parameter was added
1434       *
1435       * @param mixed  $pre_transient The default value to return if the transient does not exist.
1436       *                              Any value other than false will short-circuit the retrieval
1437       *                              of the transient, and return that value.
1438       * @param string $transient     Transient name.
1439       */
1440      $pre = apply_filters( "pre_transient_{$transient}", false, $transient );
1441  
1442      if ( false !== $pre ) {
1443          return $pre;
1444      }
1445  
1446      if ( wp_using_ext_object_cache() || wp_installing() ) {
1447          $value = wp_cache_get( $transient, 'transient' );
1448      } else {
1449          $transient_option = '_transient_' . $transient;
1450          if ( ! wp_installing() ) {
1451              // If option is not in alloptions, it is not autoloaded and thus has a timeout.
1452              $alloptions = wp_load_alloptions();
1453  
1454              if ( ! isset( $alloptions[ $transient_option ] ) ) {
1455                  $transient_timeout = '_transient_timeout_' . $transient;
1456                  wp_prime_option_caches( array( $transient_option, $transient_timeout ) );
1457                  $timeout = get_option( $transient_timeout );
1458                  if ( false !== $timeout && $timeout < time() ) {
1459                      delete_option( $transient_option );
1460                      delete_option( $transient_timeout );
1461                      $value = false;
1462                  }
1463              }
1464          }
1465  
1466          if ( ! isset( $value ) ) {
1467              $value = get_option( $transient_option );
1468          }
1469      }
1470  
1471      /**
1472       * Filters an existing transient's value.
1473       *
1474       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1475       *
1476       * @since 2.8.0
1477       * @since 4.4.0 The `$transient` parameter was added
1478       *
1479       * @param mixed  $value     Value of transient.
1480       * @param string $transient Transient name.
1481       */
1482      return apply_filters( "transient_{$transient}", $value, $transient );
1483  }
1484  
1485  /**
1486   * Sets/updates the value of a transient.
1487   *
1488   * You do not need to serialize values. If the value needs to be serialized,
1489   * then it will be serialized before it is set.
1490   *
1491   * @since 2.8.0
1492   *
1493   * @param string $transient  Transient name. Expected to not be SQL-escaped.
1494   *                           Must be 172 characters or fewer in length.
1495   * @param mixed  $value      Transient value. Must be serializable if non-scalar.
1496   *                           Expected to not be SQL-escaped.
1497   * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
1498   * @return bool True if the value was set, false otherwise.
1499   */
1500  function set_transient( $transient, $value, $expiration = 0 ) {
1501  
1502      $expiration = (int) $expiration;
1503  
1504      /**
1505       * Filters a specific transient before its value is set.
1506       *
1507       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1508       *
1509       * @since 3.0.0
1510       * @since 4.2.0 The `$expiration` parameter was added.
1511       * @since 4.4.0 The `$transient` parameter was added.
1512       *
1513       * @param mixed  $value      New value of transient.
1514       * @param int    $expiration Time until expiration in seconds.
1515       * @param string $transient  Transient name.
1516       */
1517      $value = apply_filters( "pre_set_transient_{$transient}", $value, $expiration, $transient );
1518  
1519      /**
1520       * Filters the expiration for a transient before its value is set.
1521       *
1522       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1523       *
1524       * @since 4.4.0
1525       *
1526       * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
1527       * @param mixed  $value      New value of transient.
1528       * @param string $transient  Transient name.
1529       */
1530      $expiration = apply_filters( "expiration_of_transient_{$transient}", $expiration, $value, $transient );
1531  
1532      if ( wp_using_ext_object_cache() || wp_installing() ) {
1533          $result = wp_cache_set( $transient, $value, 'transient', $expiration );
1534      } else {
1535          $transient_timeout = '_transient_timeout_' . $transient;
1536          $transient_option  = '_transient_' . $transient;
1537          wp_prime_option_caches( array( $transient_option, $transient_timeout ) );
1538  
1539          if ( false === get_option( $transient_option ) ) {
1540              $autoload = true;
1541              if ( $expiration ) {
1542                  $autoload = false;
1543                  add_option( $transient_timeout, time() + $expiration, '', false );
1544              }
1545              $result = add_option( $transient_option, $value, '', $autoload );
1546          } else {
1547              /*
1548               * If expiration is requested, but the transient has no timeout option,
1549               * delete, then re-create transient rather than update.
1550               */
1551              $update = true;
1552  
1553              if ( $expiration ) {
1554                  if ( false === get_option( $transient_timeout ) ) {
1555                      delete_option( $transient_option );
1556                      add_option( $transient_timeout, time() + $expiration, '', false );
1557                      $result = add_option( $transient_option, $value, '', false );
1558                      $update = false;
1559                  } else {
1560                      update_option( $transient_timeout, time() + $expiration );
1561                  }
1562              }
1563  
1564              if ( $update ) {
1565                  $result = update_option( $transient_option, $value );
1566              }
1567          }
1568      }
1569  
1570      if ( $result ) {
1571  
1572          /**
1573           * Fires after the value for a specific transient has been set.
1574           *
1575           * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1576           *
1577           * @since 3.0.0
1578           * @since 3.6.0 The `$value` and `$expiration` parameters were added.
1579           * @since 4.4.0 The `$transient` parameter was added.
1580           *
1581           * @param mixed  $value      Transient value.
1582           * @param int    $expiration Time until expiration in seconds.
1583           * @param string $transient  The name of the transient.
1584           */
1585          do_action( "set_transient_{$transient}", $value, $expiration, $transient );
1586  
1587          /**
1588           * Fires after the value for a transient has been set.
1589           *
1590           * @since 3.0.0
1591           * @since 3.6.0 The `$value` and `$expiration` parameters were added.
1592           *
1593           * @param string $transient  The name of the transient.
1594           * @param mixed  $value      Transient value.
1595           * @param int    $expiration Time until expiration in seconds.
1596           */
1597          do_action( 'setted_transient', $transient, $value, $expiration );
1598      }
1599  
1600      return $result;
1601  }
1602  
1603  /**
1604   * Deletes all expired transients.
1605   *
1606   * Note that this function won't do anything if an external object cache is in use.
1607   *
1608   * The multi-table delete syntax is used to delete the transient record
1609   * from table a, and the corresponding transient_timeout record from table b.
1610   *
1611   * @global wpdb $wpdb WordPress database abstraction object.
1612   *
1613   * @since 4.9.0
1614   *
1615   * @param bool $force_db Optional. Force cleanup to run against the database even when an external object cache is used.
1616   */
1617  function delete_expired_transients( $force_db = false ) {
1618      global $wpdb;
1619  
1620      if ( ! $force_db && wp_using_ext_object_cache() ) {
1621          return;
1622      }
1623  
1624      $wpdb->query(
1625          $wpdb->prepare(
1626              "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
1627              WHERE a.option_name LIKE %s
1628              AND a.option_name NOT LIKE %s
1629              AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
1630              AND b.option_value < %d",
1631              $wpdb->esc_like( '_transient_' ) . '%',
1632              $wpdb->esc_like( '_transient_timeout_' ) . '%',
1633              time()
1634          )
1635      );
1636  
1637      if ( ! is_multisite() ) {
1638          // Single site stores site transients in the options table.
1639          $wpdb->query(
1640              $wpdb->prepare(
1641                  "DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
1642                  WHERE a.option_name LIKE %s
1643                  AND a.option_name NOT LIKE %s
1644                  AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
1645                  AND b.option_value < %d",
1646                  $wpdb->esc_like( '_site_transient_' ) . '%',
1647                  $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
1648                  time()
1649              )
1650          );
1651      } elseif ( is_multisite() && is_main_site() && is_main_network() ) {
1652          // Multisite stores site transients in the sitemeta table.
1653          $wpdb->query(
1654              $wpdb->prepare(
1655                  "DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
1656                  WHERE a.meta_key LIKE %s
1657                  AND a.meta_key NOT LIKE %s
1658                  AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
1659                  AND b.meta_value < %d",
1660                  $wpdb->esc_like( '_site_transient_' ) . '%',
1661                  $wpdb->esc_like( '_site_transient_timeout_' ) . '%',
1662                  time()
1663              )
1664          );
1665      }
1666  }
1667  
1668  /**
1669   * Saves and restores user interface settings stored in a cookie.
1670   *
1671   * Checks if the current user-settings cookie is updated and stores it. When no
1672   * cookie exists (different browser used), adds the last saved cookie restoring
1673   * the settings.
1674   *
1675   * @since 2.7.0
1676   */
1677  function wp_user_settings() {
1678  
1679      if ( ! is_admin() || wp_doing_ajax() ) {
1680          return;
1681      }
1682  
1683      $user_id = get_current_user_id();
1684      if ( ! $user_id ) {
1685          return;
1686      }
1687  
1688      if ( ! is_user_member_of_blog() ) {
1689          return;
1690      }
1691  
1692      $settings = (string) get_user_option( 'user-settings', $user_id );
1693  
1694      if ( isset( $_COOKIE[ 'wp-settings-' . $user_id ] ) ) {
1695          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE[ 'wp-settings-' . $user_id ] );
1696  
1697          // No change or both empty.
1698          if ( $cookie === $settings ) {
1699              return;
1700          }
1701  
1702          $last_saved = (int) get_user_option( 'user-settings-time', $user_id );
1703          $current    = 0;
1704  
1705          if ( isset( $_COOKIE[ 'wp-settings-time-' . $user_id ] ) ) {
1706              $current = (int) preg_replace( '/[^0-9]/', '', $_COOKIE[ 'wp-settings-time-' . $user_id ] );
1707          }
1708  
1709          // The cookie is newer than the saved value. Update the user_option and leave the cookie as-is.
1710          if ( $current > $last_saved ) {
1711              update_user_option( $user_id, 'user-settings', $cookie, false );
1712              update_user_option( $user_id, 'user-settings-time', time() - 5, false );
1713              return;
1714          }
1715      }
1716  
1717      // The cookie is not set in the current browser or the saved value is newer.
1718      $secure = ( 'https' === parse_url( admin_url(), PHP_URL_SCHEME ) );
1719      setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, '', $secure );
1720      setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, '', $secure );
1721      $_COOKIE[ 'wp-settings-' . $user_id ] = $settings;
1722  }
1723  
1724  /**
1725   * Retrieves user interface setting value based on setting name.
1726   *
1727   * @since 2.7.0
1728   *
1729   * @param string       $name          The name of the setting.
1730   * @param string|false $default_value Optional. Default value to return when $name is not set. Default false.
1731   * @return mixed The last saved user setting or the default value/false if it doesn't exist.
1732   */
1733  function get_user_setting( $name, $default_value = false ) {
1734      $all_user_settings = get_all_user_settings();
1735  
1736      return isset( $all_user_settings[ $name ] ) ? $all_user_settings[ $name ] : $default_value;
1737  }
1738  
1739  /**
1740   * Adds or updates user interface setting.
1741   *
1742   * Both `$name` and `$value` can contain only ASCII letters, numbers, hyphens, and underscores.
1743   *
1744   * This function has to be used before any output has started as it calls `setcookie()`.
1745   *
1746   * @since 2.8.0
1747   *
1748   * @param string $name  The name of the setting.
1749   * @param string $value The value for the setting.
1750   * @return bool|null True if set successfully, false otherwise.
1751   *                   Null if the current user is not a member of the site.
1752   */
1753  function set_user_setting( $name, $value ) {
1754      if ( headers_sent() ) {
1755          return false;
1756      }
1757  
1758      $all_user_settings          = get_all_user_settings();
1759      $all_user_settings[ $name ] = $value;
1760  
1761      return wp_set_all_user_settings( $all_user_settings );
1762  }
1763  
1764  /**
1765   * Deletes user interface settings.
1766   *
1767   * Deleting settings would reset them to the defaults.
1768   *
1769   * This function has to be used before any output has started as it calls `setcookie()`.
1770   *
1771   * @since 2.7.0
1772   *
1773   * @param string $names The name or array of names of the setting to be deleted.
1774   * @return bool|null True if deleted successfully, false otherwise.
1775   *                   Null if the current user is not a member of the site.
1776   */
1777  function delete_user_setting( $names ) {
1778      if ( headers_sent() ) {
1779          return false;
1780      }
1781  
1782      $all_user_settings = get_all_user_settings();
1783      $names             = (array) $names;
1784      $deleted           = false;
1785  
1786      foreach ( $names as $name ) {
1787          if ( isset( $all_user_settings[ $name ] ) ) {
1788              unset( $all_user_settings[ $name ] );
1789              $deleted = true;
1790          }
1791      }
1792  
1793      if ( $deleted ) {
1794          return wp_set_all_user_settings( $all_user_settings );
1795      }
1796  
1797      return false;
1798  }
1799  
1800  /**
1801   * Retrieves all user interface settings.
1802   *
1803   * @since 2.7.0
1804   *
1805   * @global array $_updated_user_settings
1806   *
1807   * @return array The last saved user settings or empty array.
1808   */
1809  function get_all_user_settings() {
1810      global $_updated_user_settings;
1811  
1812      $user_id = get_current_user_id();
1813      if ( ! $user_id ) {
1814          return array();
1815      }
1816  
1817      if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) {
1818          return $_updated_user_settings;
1819      }
1820  
1821      $user_settings = array();
1822  
1823      if ( isset( $_COOKIE[ 'wp-settings-' . $user_id ] ) ) {
1824          $cookie = preg_replace( '/[^A-Za-z0-9=&_-]/', '', $_COOKIE[ 'wp-settings-' . $user_id ] );
1825  
1826          if ( strpos( $cookie, '=' ) ) { // '=' cannot be 1st char.
1827              parse_str( $cookie, $user_settings );
1828          }
1829      } else {
1830          $option = get_user_option( 'user-settings', $user_id );
1831  
1832          if ( $option && is_string( $option ) ) {
1833              parse_str( $option, $user_settings );
1834          }
1835      }
1836  
1837      $_updated_user_settings = $user_settings;
1838      return $user_settings;
1839  }
1840  
1841  /**
1842   * Private. Sets all user interface settings.
1843   *
1844   * @since 2.8.0
1845   * @access private
1846   *
1847   * @global array $_updated_user_settings
1848   *
1849   * @param array $user_settings User settings.
1850   * @return bool|null True if set successfully, false if the current user could not be found.
1851   *                   Null if the current user is not a member of the site.
1852   */
1853  function wp_set_all_user_settings( $user_settings ) {
1854      global $_updated_user_settings;
1855  
1856      $user_id = get_current_user_id();
1857      if ( ! $user_id ) {
1858          return false;
1859      }
1860  
1861      if ( ! is_user_member_of_blog() ) {
1862          return;
1863      }
1864  
1865      $settings = '';
1866      foreach ( $user_settings as $name => $value ) {
1867          $_name  = preg_replace( '/[^A-Za-z0-9_-]+/', '', $name );
1868          $_value = preg_replace( '/[^A-Za-z0-9_-]+/', '', $value );
1869  
1870          if ( ! empty( $_name ) ) {
1871              $settings .= $_name . '=' . $_value . '&';
1872          }
1873      }
1874  
1875      $settings = rtrim( $settings, '&' );
1876      parse_str( $settings, $_updated_user_settings );
1877  
1878      update_user_option( $user_id, 'user-settings', $settings, false );
1879      update_user_option( $user_id, 'user-settings-time', time(), false );
1880  
1881      return true;
1882  }
1883  
1884  /**
1885   * Deletes the user settings of the current user.
1886   *
1887   * @since 2.7.0
1888   */
1889  function delete_all_user_settings() {
1890      $user_id = get_current_user_id();
1891      if ( ! $user_id ) {
1892          return;
1893      }
1894  
1895      update_user_option( $user_id, 'user-settings', '', false );
1896      setcookie( 'wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
1897  }
1898  
1899  /**
1900   * Retrieve an option value for the current network based on name of option.
1901   *
1902   * @since 2.8.0
1903   * @since 4.4.0 The `$use_cache` parameter was deprecated.
1904   * @since 4.4.0 Modified into wrapper for get_network_option()
1905   *
1906   * @see get_network_option()
1907   *
1908   * @param string $option        Name of the option to retrieve. Expected to not be SQL-escaped.
1909   * @param mixed  $default_value Optional. Value to return if the option doesn't exist. Default false.
1910   * @param bool   $deprecated    Whether to use cache. Multisite only. Always set to true.
1911   * @return mixed Value set for the option.
1912   */
1913  function get_site_option( $option, $default_value = false, $deprecated = true ) {
1914      return get_network_option( null, $option, $default_value );
1915  }
1916  
1917  /**
1918   * Adds a new option for the current network.
1919   *
1920   * Existing options will not be updated. Note that prior to 3.3 this wasn't the case.
1921   *
1922   * @since 2.8.0
1923   * @since 4.4.0 Modified into wrapper for add_network_option()
1924   *
1925   * @see add_network_option()
1926   *
1927   * @param string $option Name of the option to add. Expected to not be SQL-escaped.
1928   * @param mixed  $value  Option value, can be anything. Expected to not be SQL-escaped.
1929   * @return bool True if the option was added, false otherwise.
1930   */
1931  function add_site_option( $option, $value ) {
1932      return add_network_option( null, $option, $value );
1933  }
1934  
1935  /**
1936   * Removes an option by name for the current network.
1937   *
1938   * @since 2.8.0
1939   * @since 4.4.0 Modified into wrapper for delete_network_option()
1940   *
1941   * @see delete_network_option()
1942   *
1943   * @param string $option Name of the option to delete. Expected to not be SQL-escaped.
1944   * @return bool True if the option was deleted, false otherwise.
1945   */
1946  function delete_site_option( $option ) {
1947      return delete_network_option( null, $option );
1948  }
1949  
1950  /**
1951   * Updates the value of an option that was already added for the current network.
1952   *
1953   * @since 2.8.0
1954   * @since 4.4.0 Modified into wrapper for update_network_option()
1955   *
1956   * @see update_network_option()
1957   *
1958   * @param string $option Name of the option. Expected to not be SQL-escaped.
1959   * @param mixed  $value  Option value. Expected to not be SQL-escaped.
1960   * @return bool True if the value was updated, false otherwise.
1961   */
1962  function update_site_option( $option, $value ) {
1963      return update_network_option( null, $option, $value );
1964  }
1965  
1966  /**
1967   * Retrieves a network's option value based on the option name.
1968   *
1969   * @since 4.4.0
1970   *
1971   * @see get_option()
1972   *
1973   * @global wpdb $wpdb WordPress database abstraction object.
1974   *
1975   * @param int    $network_id    ID of the network. Can be null to default to the current network ID.
1976   * @param string $option        Name of the option to retrieve. Expected to not be SQL-escaped.
1977   * @param mixed  $default_value Optional. Value to return if the option doesn't exist. Default false.
1978   * @return mixed Value set for the option.
1979   */
1980  function get_network_option( $network_id, $option, $default_value = false ) {
1981      global $wpdb;
1982  
1983      if ( $network_id && ! is_numeric( $network_id ) ) {
1984          return false;
1985      }
1986  
1987      $network_id = (int) $network_id;
1988  
1989      // Fallback to the current network if a network ID is not specified.
1990      if ( ! $network_id ) {
1991          $network_id = get_current_network_id();
1992      }
1993  
1994      /**
1995       * Filters the value of an existing network option before it is retrieved.
1996       *
1997       * The dynamic portion of the hook name, `$option`, refers to the option name.
1998       *
1999       * Returning a value other than false from the filter will short-circuit retrieval
2000       * and return that value instead.
2001       *
2002       * @since 2.9.0 As 'pre_site_option_' . $key
2003       * @since 3.0.0
2004       * @since 4.4.0 The `$option` parameter was added.
2005       * @since 4.7.0 The `$network_id` parameter was added.
2006       * @since 4.9.0 The `$default_value` parameter was added.
2007       *
2008       * @param mixed  $pre_site_option The value to return instead of the option value. This differs from
2009       *                                `$default_value`, which is used as the fallback value in the event
2010       *                                the option doesn't exist elsewhere in get_network_option().
2011       *                                Default false (to skip past the short-circuit).
2012       * @param string $option          Option name.
2013       * @param int    $network_id      ID of the network.
2014       * @param mixed  $default_value   The fallback value to return if the option does not exist.
2015       *                                Default false.
2016       */
2017      $pre = apply_filters( "pre_site_option_{$option}", false, $option, $network_id, $default_value );
2018  
2019      if ( false !== $pre ) {
2020          return $pre;
2021      }
2022  
2023      // Prevent non-existent options from triggering multiple queries.
2024      $notoptions_key = "$network_id:notoptions";
2025      $notoptions     = wp_cache_get( $notoptions_key, 'site-options' );
2026  
2027      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
2028  
2029          /**
2030           * Filters the value of a specific default network option.
2031           *
2032           * The dynamic portion of the hook name, `$option`, refers to the option name.
2033           *
2034           * @since 3.4.0
2035           * @since 4.4.0 The `$option` parameter was added.
2036           * @since 4.7.0 The `$network_id` parameter was added.
2037           *
2038           * @param mixed  $default_value The value to return if the site option does not exist
2039           *                              in the database.
2040           * @param string $option        Option name.
2041           * @param int    $network_id    ID of the network.
2042           */
2043          return apply_filters( "default_site_option_{$option}", $default_value, $option, $network_id );
2044      }
2045  
2046      if ( ! is_multisite() ) {
2047          /** This filter is documented in wp-includes/option.php */
2048          $default_value = apply_filters( 'default_site_option_' . $option, $default_value, $option, $network_id );
2049          $value         = get_option( $option, $default_value );
2050      } else {
2051          $cache_key = "$network_id:$option";
2052          $value     = wp_cache_get( $cache_key, 'site-options' );
2053  
2054          if ( ! isset( $value ) || false === $value ) {
2055              $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
2056  
2057              // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
2058              if ( is_object( $row ) ) {
2059                  $value = $row->meta_value;
2060                  $value = maybe_unserialize( $value );
2061                  wp_cache_set( $cache_key, $value, 'site-options' );
2062              } else {
2063                  if ( ! is_array( $notoptions ) ) {
2064                      $notoptions = array();
2065                  }
2066  
2067                  $notoptions[ $option ] = true;
2068                  wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
2069  
2070                  /** This filter is documented in wp-includes/option.php */
2071                  $value = apply_filters( 'default_site_option_' . $option, $default_value, $option, $network_id );
2072              }
2073          }
2074      }
2075  
2076      if ( ! is_array( $notoptions ) ) {
2077          $notoptions = array();
2078          wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
2079      }
2080  
2081      /**
2082       * Filters the value of an existing network option.
2083       *
2084       * The dynamic portion of the hook name, `$option`, refers to the option name.
2085       *
2086       * @since 2.9.0 As 'site_option_' . $key
2087       * @since 3.0.0
2088       * @since 4.4.0 The `$option` parameter was added.
2089       * @since 4.7.0 The `$network_id` parameter was added.
2090       *
2091       * @param mixed  $value      Value of network option.
2092       * @param string $option     Option name.
2093       * @param int    $network_id ID of the network.
2094       */
2095      return apply_filters( "site_option_{$option}", $value, $option, $network_id );
2096  }
2097  
2098  /**
2099   * Adds a new network option.
2100   *
2101   * Existing options will not be updated.
2102   *
2103   * @since 4.4.0
2104   *
2105   * @see add_option()
2106   *
2107   * @global wpdb $wpdb WordPress database abstraction object.
2108   *
2109   * @param int    $network_id ID of the network. Can be null to default to the current network ID.
2110   * @param string $option     Name of the option to add. Expected to not be SQL-escaped.
2111   * @param mixed  $value      Option value, can be anything. Expected to not be SQL-escaped.
2112   * @return bool True if the option was added, false otherwise.
2113   */
2114  function add_network_option( $network_id, $option, $value ) {
2115      global $wpdb;
2116  
2117      if ( $network_id && ! is_numeric( $network_id ) ) {
2118          return false;
2119      }
2120  
2121      $network_id = (int) $network_id;
2122  
2123      // Fallback to the current network if a network ID is not specified.
2124      if ( ! $network_id ) {
2125          $network_id = get_current_network_id();
2126      }
2127  
2128      wp_protect_special_option( $option );
2129  
2130      /**
2131       * Filters the value of a specific network option before it is added.
2132       *
2133       * The dynamic portion of the hook name, `$option`, refers to the option name.
2134       *
2135       * @since 2.9.0 As 'pre_add_site_option_' . $key
2136       * @since 3.0.0
2137       * @since 4.4.0 The `$option` parameter was added.
2138       * @since 4.7.0 The `$network_id` parameter was added.
2139       *
2140       * @param mixed  $value      Value of network option.
2141       * @param string $option     Option name.
2142       * @param int    $network_id ID of the network.
2143       */
2144      $value = apply_filters( "pre_add_site_option_{$option}", $value, $option, $network_id );
2145  
2146      $notoptions_key = "$network_id:notoptions";
2147  
2148      if ( ! is_multisite() ) {
2149          $result = add_option( $option, $value, '', false );
2150      } else {
2151          $cache_key = "$network_id:$option";
2152  
2153          /*
2154           * Make sure the option doesn't already exist.
2155           * We can check the 'notoptions' cache before we ask for a DB query.
2156           */
2157          $notoptions = wp_cache_get( $notoptions_key, 'site-options' );
2158  
2159          if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
2160              if ( false !== get_network_option( $network_id, $option, false ) ) {
2161                  return false;
2162              }
2163          }
2164  
2165          $value = sanitize_option( $option, $value );
2166  
2167          $serialized_value = maybe_serialize( $value );
2168          $result           = $wpdb->insert(
2169              $wpdb->sitemeta,
2170              array(
2171                  'site_id'    => $network_id,
2172                  'meta_key'   => $option,
2173                  'meta_value' => $serialized_value,
2174              )
2175          );
2176  
2177          if ( ! $result ) {
2178              return false;
2179          }
2180  
2181          wp_cache_set( $cache_key, $value, 'site-options' );
2182  
2183          // This option exists now.
2184          $notoptions = wp_cache_get( $notoptions_key, 'site-options' ); // Yes, again... we need it to be fresh.
2185  
2186          if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
2187              unset( $notoptions[ $option ] );
2188              wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
2189          }
2190      }
2191  
2192      if ( $result ) {
2193  
2194          /**
2195           * Fires after a specific network option has been successfully added.
2196           *
2197           * The dynamic portion of the hook name, `$option`, refers to the option name.
2198           *
2199           * @since 2.9.0 As "add_site_option_{$key}"
2200           * @since 3.0.0
2201           * @since 4.7.0 The `$network_id` parameter was added.
2202           *
2203           * @param string $option     Name of the network option.
2204           * @param mixed  $value      Value of the network option.
2205           * @param int    $network_id ID of the network.
2206           */
2207          do_action( "add_site_option_{$option}", $option, $value, $network_id );
2208  
2209          /**
2210           * Fires after a network option has been successfully added.
2211           *
2212           * @since 3.0.0
2213           * @since 4.7.0 The `$network_id` parameter was added.
2214           *
2215           * @param string $option     Name of the network option.
2216           * @param mixed  $value      Value of the network option.
2217           * @param int    $network_id ID of the network.
2218           */
2219          do_action( 'add_site_option', $option, $value, $network_id );
2220  
2221          return true;
2222      }
2223  
2224      return false;
2225  }
2226  
2227  /**
2228   * Removes a network option by name.
2229   *
2230   * @since 4.4.0
2231   *
2232   * @see delete_option()
2233   *
2234   * @global wpdb $wpdb WordPress database abstraction object.
2235   *
2236   * @param int    $network_id ID of the network. Can be null to default to the current network ID.
2237   * @param string $option     Name of the option to delete. Expected to not be SQL-escaped.
2238   * @return bool True if the option was deleted, false otherwise.
2239   */
2240  function delete_network_option( $network_id, $option ) {
2241      global $wpdb;
2242  
2243      if ( $network_id && ! is_numeric( $network_id ) ) {
2244          return false;
2245      }
2246  
2247      $network_id = (int) $network_id;
2248  
2249      // Fallback to the current network if a network ID is not specified.
2250      if ( ! $network_id ) {
2251          $network_id = get_current_network_id();
2252      }
2253  
2254      /**
2255       * Fires immediately before a specific network option is deleted.
2256       *
2257       * The dynamic portion of the hook name, `$option`, refers to the option name.
2258       *
2259       * @since 3.0.0
2260       * @since 4.4.0 The `$option` parameter was added.
2261       * @since 4.7.0 The `$network_id` parameter was added.
2262       *
2263       * @param string $option     Option name.
2264       * @param int    $network_id ID of the network.
2265       */
2266      do_action( "pre_delete_site_option_{$option}", $option, $network_id );
2267  
2268      if ( ! is_multisite() ) {
2269          $result = delete_option( $option );
2270      } else {
2271          $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
2272          if ( is_null( $row ) || ! $row->meta_id ) {
2273              return false;
2274          }
2275          $cache_key = "$network_id:$option";
2276          wp_cache_delete( $cache_key, 'site-options' );
2277  
2278          $result = $wpdb->delete(
2279              $wpdb->sitemeta,
2280              array(
2281                  'meta_key' => $option,
2282                  'site_id'  => $network_id,
2283              )
2284          );
2285  
2286          if ( $result ) {
2287              $notoptions_key = "$network_id:notoptions";
2288              $notoptions     = wp_cache_get( $notoptions_key, 'site-options' );
2289  
2290              if ( ! is_array( $notoptions ) ) {
2291                  $notoptions = array();
2292              }
2293              $notoptions[ $option ] = true;
2294              wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
2295          }
2296      }
2297  
2298      if ( $result ) {
2299  
2300          /**
2301           * Fires after a specific network option has been deleted.
2302           *
2303           * The dynamic portion of the hook name, `$option`, refers to the option name.
2304           *
2305           * @since 2.9.0 As "delete_site_option_{$key}"
2306           * @since 3.0.0
2307           * @since 4.7.0 The `$network_id` parameter was added.
2308           *
2309           * @param string $option     Name of the network option.
2310           * @param int    $network_id ID of the network.
2311           */
2312          do_action( "delete_site_option_{$option}", $option, $network_id );
2313  
2314          /**
2315           * Fires after a network option has been deleted.
2316           *
2317           * @since 3.0.0
2318           * @since 4.7.0 The `$network_id` parameter was added.
2319           *
2320           * @param string $option     Name of the network option.
2321           * @param int    $network_id ID of the network.
2322           */
2323          do_action( 'delete_site_option', $option, $network_id );
2324  
2325          return true;
2326      }
2327  
2328      return false;
2329  }
2330  
2331  /**
2332   * Updates the value of a network option that was already added.
2333   *
2334   * @since 4.4.0
2335   *
2336   * @see update_option()
2337   *
2338   * @global wpdb $wpdb WordPress database abstraction object.
2339   *
2340   * @param int    $network_id ID of the network. Can be null to default to the current network ID.
2341   * @param string $option     Name of the option. Expected to not be SQL-escaped.
2342   * @param mixed  $value      Option value. Expected to not be SQL-escaped.
2343   * @return bool True if the value was updated, false otherwise.
2344   */
2345  function update_network_option( $network_id, $option, $value ) {
2346      global $wpdb;
2347  
2348      if ( $network_id && ! is_numeric( $network_id ) ) {
2349          return false;
2350      }
2351  
2352      $network_id = (int) $network_id;
2353  
2354      // Fallback to the current network if a network ID is not specified.
2355      if ( ! $network_id ) {
2356          $network_id = get_current_network_id();
2357      }
2358  
2359      wp_protect_special_option( $option );
2360  
2361      $old_value = get_network_option( $network_id, $option );
2362  
2363      /**
2364       * Filters a specific network option before its value is updated.
2365       *
2366       * The dynamic portion of the hook name, `$option`, refers to the option name.
2367       *
2368       * @since 2.9.0 As 'pre_update_site_option_' . $key
2369       * @since 3.0.0
2370       * @since 4.4.0 The `$option` parameter was added.
2371       * @since 4.7.0 The `$network_id` parameter was added.
2372       *
2373       * @param mixed  $value      New value of the network option.
2374       * @param mixed  $old_value  Old value of the network option.
2375       * @param string $option     Option name.
2376       * @param int    $network_id ID of the network.
2377       */
2378      $value = apply_filters( "pre_update_site_option_{$option}", $value, $old_value, $option, $network_id );
2379  
2380      /*
2381       * If the new and old values are the same, no need to update.
2382       *
2383       * Unserialized values will be adequate in most cases. If the unserialized
2384       * data differs, the (maybe) serialized data is checked to avoid
2385       * unnecessary database calls for otherwise identical object instances.
2386       *
2387       * See https://core.trac.wordpress.org/ticket/44956
2388       */
2389      if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
2390          return false;
2391      }
2392  
2393      if ( false === $old_value ) {
2394          return add_network_option( $network_id, $option, $value );
2395      }
2396  
2397      $notoptions_key = "$network_id:notoptions";
2398      $notoptions     = wp_cache_get( $notoptions_key, 'site-options' );
2399  
2400      if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
2401          unset( $notoptions[ $option ] );
2402          wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
2403      }
2404  
2405      if ( ! is_multisite() ) {
2406          $result = update_option( $option, $value, false );
2407      } else {
2408          $value = sanitize_option( $option, $value );
2409  
2410          $serialized_value = maybe_serialize( $value );
2411          $result           = $wpdb->update(
2412              $wpdb->sitemeta,
2413              array( 'meta_value' => $serialized_value ),
2414              array(
2415                  'site_id'  => $network_id,
2416                  'meta_key' => $option,
2417              )
2418          );
2419  
2420          if ( $result ) {
2421              $cache_key = "$network_id:$option";
2422              wp_cache_set( $cache_key, $value, 'site-options' );
2423          }
2424      }
2425  
2426      if ( $result ) {
2427  
2428          /**
2429           * Fires after the value of a specific network option has been successfully updated.
2430           *
2431           * The dynamic portion of the hook name, `$option`, refers to the option name.
2432           *
2433           * @since 2.9.0 As "update_site_option_{$key}"
2434           * @since 3.0.0
2435           * @since 4.7.0 The `$network_id` parameter was added.
2436           *
2437           * @param string $option     Name of the network option.
2438           * @param mixed  $value      Current value of the network option.
2439           * @param mixed  $old_value  Old value of the network option.
2440           * @param int    $network_id ID of the network.
2441           */
2442          do_action( "update_site_option_{$option}", $option, $value, $old_value, $network_id );
2443  
2444          /**
2445           * Fires after the value of a network option has been successfully updated.
2446           *
2447           * @since 3.0.0
2448           * @since 4.7.0 The `$network_id` parameter was added.
2449           *
2450           * @param string $option     Name of the network option.
2451           * @param mixed  $value      Current value of the network option.
2452           * @param mixed  $old_value  Old value of the network option.
2453           * @param int    $network_id ID of the network.
2454           */
2455          do_action( 'update_site_option', $option, $value, $old_value, $network_id );
2456  
2457          return true;
2458      }
2459  
2460      return false;
2461  }
2462  
2463  /**
2464   * Deletes a site transient.
2465   *
2466   * @since 2.9.0
2467   *
2468   * @param string $transient Transient name. Expected to not be SQL-escaped.
2469   * @return bool True if the transient was deleted, false otherwise.
2470   */
2471  function delete_site_transient( $transient ) {
2472  
2473      /**
2474       * Fires immediately before a specific site transient is deleted.
2475       *
2476       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2477       *
2478       * @since 3.0.0
2479       *
2480       * @param string $transient Transient name.
2481       */
2482      do_action( "delete_site_transient_{$transient}", $transient );
2483  
2484      if ( wp_using_ext_object_cache() || wp_installing() ) {
2485          $result = wp_cache_delete( $transient, 'site-transient' );
2486      } else {
2487          $option_timeout = '_site_transient_timeout_' . $transient;
2488          $option         = '_site_transient_' . $transient;
2489          $result         = delete_site_option( $option );
2490  
2491          if ( $result ) {
2492              delete_site_option( $option_timeout );
2493          }
2494      }
2495  
2496      if ( $result ) {
2497  
2498          /**
2499           * Fires after a transient is deleted.
2500           *
2501           * @since 3.0.0
2502           *
2503           * @param string $transient Deleted transient name.
2504           */
2505          do_action( 'deleted_site_transient', $transient );
2506      }
2507  
2508      return $result;
2509  }
2510  
2511  /**
2512   * Retrieves the value of a site transient.
2513   *
2514   * If the transient does not exist, does not have a value, or has expired,
2515   * then the return value will be false.
2516   *
2517   * @since 2.9.0
2518   *
2519   * @see get_transient()
2520   *
2521   * @param string $transient Transient name. Expected to not be SQL-escaped.
2522   * @return mixed Value of transient.
2523   */
2524  function get_site_transient( $transient ) {
2525  
2526      /**
2527       * Filters the value of an existing site transient before it is retrieved.
2528       *
2529       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2530       *
2531       * Returning a value other than boolean false will short-circuit retrieval and
2532       * return that value instead.
2533       *
2534       * @since 2.9.0
2535       * @since 4.4.0 The `$transient` parameter was added.
2536       *
2537       * @param mixed  $pre_site_transient The default value to return if the site transient does not exist.
2538       *                                   Any value other than false will short-circuit the retrieval
2539       *                                   of the transient, and return that value.
2540       * @param string $transient          Transient name.
2541       */
2542      $pre = apply_filters( "pre_site_transient_{$transient}", false, $transient );
2543  
2544      if ( false !== $pre ) {
2545          return $pre;
2546      }
2547  
2548      if ( wp_using_ext_object_cache() || wp_installing() ) {
2549          $value = wp_cache_get( $transient, 'site-transient' );
2550      } else {
2551          // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
2552          $no_timeout       = array( 'update_core', 'update_plugins', 'update_themes' );
2553          $transient_option = '_site_transient_' . $transient;
2554          if ( ! in_array( $transient, $no_timeout, true ) ) {
2555              $transient_timeout = '_site_transient_timeout_' . $transient;
2556              wp_prime_site_option_caches( array( $transient_option, $transient_timeout ) );
2557  
2558              $timeout = get_site_option( $transient_timeout );
2559              if ( false !== $timeout && $timeout < time() ) {
2560                  delete_site_option( $transient_option );
2561                  delete_site_option( $transient_timeout );
2562                  $value = false;
2563              }
2564          }
2565  
2566          if ( ! isset( $value ) ) {
2567              $value = get_site_option( $transient_option );
2568          }
2569      }
2570  
2571      /**
2572       * Filters the value of an existing site transient.
2573       *
2574       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2575       *
2576       * @since 2.9.0
2577       * @since 4.4.0 The `$transient` parameter was added.
2578       *
2579       * @param mixed  $value     Value of site transient.
2580       * @param string $transient Transient name.
2581       */
2582      return apply_filters( "site_transient_{$transient}", $value, $transient );
2583  }
2584  
2585  /**
2586   * Sets/updates the value of a site transient.
2587   *
2588   * You do not need to serialize values. If the value needs to be serialized,
2589   * then it will be serialized before it is set.
2590   *
2591   * @since 2.9.0
2592   *
2593   * @see set_transient()
2594   *
2595   * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
2596   *                           167 characters or fewer in length.
2597   * @param mixed  $value      Transient value. Expected to not be SQL-escaped.
2598   * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
2599   * @return bool True if the value was set, false otherwise.
2600   */
2601  function set_site_transient( $transient, $value, $expiration = 0 ) {
2602  
2603      /**
2604       * Filters the value of a specific site transient before it is set.
2605       *
2606       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2607       *
2608       * @since 3.0.0
2609       * @since 4.4.0 The `$transient` parameter was added.
2610       *
2611       * @param mixed  $value     New value of site transient.
2612       * @param string $transient Transient name.
2613       */
2614      $value = apply_filters( "pre_set_site_transient_{$transient}", $value, $transient );
2615  
2616      $expiration = (int) $expiration;
2617  
2618      /**
2619       * Filters the expiration for a site transient before its value is set.
2620       *
2621       * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2622       *
2623       * @since 4.4.0
2624       *
2625       * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
2626       * @param mixed  $value      New value of site transient.
2627       * @param string $transient  Transient name.
2628       */
2629      $expiration = apply_filters( "expiration_of_site_transient_{$transient}", $expiration, $value, $transient );
2630  
2631      if ( wp_using_ext_object_cache() || wp_installing() ) {
2632          $result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
2633      } else {
2634          $transient_timeout = '_site_transient_timeout_' . $transient;
2635          $option            = '_site_transient_' . $transient;
2636          wp_prime_site_option_caches( array( $option, $transient_timeout ) );
2637  
2638          if ( false === get_site_option( $option ) ) {
2639              if ( $expiration ) {
2640                  add_site_option( $transient_timeout, time() + $expiration );
2641              }
2642              $result = add_site_option( $option, $value );
2643          } else {
2644              if ( $expiration ) {
2645                  update_site_option( $transient_timeout, time() + $expiration );
2646              }
2647              $result = update_site_option( $option, $value );
2648          }
2649      }
2650  
2651      if ( $result ) {
2652  
2653          /**
2654           * Fires after the value for a specific site transient has been set.
2655           *
2656           * The dynamic portion of the hook name, `$transient`, refers to the transient name.
2657           *
2658           * @since 3.0.0
2659           * @since 4.4.0 The `$transient` parameter was added
2660           *
2661           * @param mixed  $value      Site transient value.
2662           * @param int    $expiration Time until expiration in seconds.
2663           * @param string $transient  Transient name.
2664           */
2665          do_action( "set_site_transient_{$transient}", $value, $expiration, $transient );
2666  
2667          /**
2668           * Fires after the value for a site transient has been set.
2669           *
2670           * @since 3.0.0
2671           *
2672           * @param string $transient  The name of the site transient.
2673           * @param mixed  $value      Site transient value.
2674           * @param int    $expiration Time until expiration in seconds.
2675           */
2676          do_action( 'setted_site_transient', $transient, $value, $expiration );
2677      }
2678  
2679      return $result;
2680  }
2681  
2682  /**
2683   * Registers default settings available in WordPress.
2684   *
2685   * The settings registered here are primarily useful for the REST API, so this
2686   * does not encompass all settings available in WordPress.
2687   *
2688   * @since 4.7.0
2689   * @since 6.0.1 The `show_on_front`, `page_on_front`, and `page_for_posts` options were added.
2690   */
2691  function register_initial_settings() {
2692      register_setting(
2693          'general',
2694          'blogname',
2695          array(
2696              'show_in_rest' => array(
2697                  'name' => 'title',
2698              ),
2699              'type'         => 'string',
2700              'label'        => __( 'Title' ),
2701              'description'  => __( 'Site title.' ),
2702          )
2703      );
2704  
2705      register_setting(
2706          'general',
2707          'blogdescription',
2708          array(
2709              'show_in_rest' => array(
2710                  'name' => 'description',
2711              ),
2712              'type'         => 'string',
2713              'label'        => __( 'Tagline' ),
2714              'description'  => __( 'Site tagline.' ),
2715          )
2716      );
2717  
2718      if ( ! is_multisite() ) {
2719          register_setting(
2720              'general',
2721              'siteurl',
2722              array(
2723                  'show_in_rest' => array(
2724                      'name'   => 'url',
2725                      'schema' => array(
2726                          'format' => 'uri',
2727                      ),
2728                  ),
2729                  'type'         => 'string',
2730                  'description'  => __( 'Site URL.' ),
2731              )
2732          );
2733      }
2734  
2735      if ( ! is_multisite() ) {
2736          register_setting(
2737              'general',
2738              'admin_email',
2739              array(
2740                  'show_in_rest' => array(
2741                      'name'   => 'email',
2742                      'schema' => array(
2743                          'format' => 'email',
2744                      ),
2745                  ),
2746                  'type'         => 'string',
2747                  'description'  => __( 'This address is used for admin purposes, like new user notification.' ),
2748              )
2749          );
2750      }
2751  
2752      register_setting(
2753          'general',
2754          'timezone_string',
2755          array(
2756              'show_in_rest' => array(
2757                  'name' => 'timezone',
2758              ),
2759              'type'         => 'string',
2760              'description'  => __( 'A city in the same timezone as you.' ),
2761          )
2762      );
2763  
2764      register_setting(
2765          'general',
2766          'date_format',
2767          array(
2768              'show_in_rest' => true,
2769              'type'         => 'string',
2770              'description'  => __( 'A date format for all date strings.' ),
2771          )
2772      );
2773  
2774      register_setting(
2775          'general',
2776          'time_format',
2777          array(
2778              'show_in_rest' => true,
2779              'type'         => 'string',
2780              'description'  => __( 'A time format for all time strings.' ),
2781          )
2782      );
2783  
2784      register_setting(
2785          'general',
2786          'start_of_week',
2787          array(
2788              'show_in_rest' => true,
2789              'type'         => 'integer',
2790              'description'  => __( 'A day number of the week that the week should start on.' ),
2791          )
2792      );
2793  
2794      register_setting(
2795          'general',
2796          'WPLANG',
2797          array(
2798              'show_in_rest' => array(
2799                  'name' => 'language',
2800              ),
2801              'type'         => 'string',
2802              'description'  => __( 'WordPress locale code.' ),
2803              'default'      => 'en_US',
2804          )
2805      );
2806  
2807      register_setting(
2808          'writing',
2809          'use_smilies',
2810          array(
2811              'show_in_rest' => true,
2812              'type'         => 'boolean',
2813              'description'  => __( 'Convert emoticons like :-) and :-P to graphics on display.' ),
2814              'default'      => true,
2815          )
2816      );
2817  
2818      register_setting(
2819          'writing',
2820          'default_category',
2821          array(
2822              'show_in_rest' => true,
2823              'type'         => 'integer',
2824              'description'  => __( 'Default post category.' ),
2825          )
2826      );
2827  
2828      register_setting(
2829          'writing',
2830          'default_post_format',
2831          array(
2832              'show_in_rest' => true,
2833              'type'         => 'string',
2834              'description'  => __( 'Default post format.' ),
2835          )
2836      );
2837  
2838      register_setting(
2839          'reading',
2840          'posts_per_page',
2841          array(
2842              'show_in_rest' => true,
2843              'type'         => 'integer',
2844              'label'        => __( 'Maximum posts per page' ),
2845              'description'  => __( 'Blog pages show at most.' ),
2846              'default'      => 10,
2847          )
2848      );
2849  
2850      register_setting(
2851          'reading',
2852          'show_on_front',
2853          array(
2854              'show_in_rest' => true,
2855              'type'         => 'string',
2856              'label'        => __( 'Show on front' ),
2857              'description'  => __( 'What to show on the front page' ),
2858          )
2859      );
2860  
2861      register_setting(
2862          'reading',
2863          'page_on_front',
2864          array(
2865              'show_in_rest' => true,
2866              'type'         => 'integer',
2867              'label'        => __( 'Page on front' ),
2868              'description'  => __( 'The ID of the page that should be displayed on the front page' ),
2869          )
2870      );
2871  
2872      register_setting(
2873          'reading',
2874          'page_for_posts',
2875          array(
2876              'show_in_rest' => true,
2877              'type'         => 'integer',
2878              'description'  => __( 'The ID of the page that should display the latest posts' ),
2879          )
2880      );
2881  
2882      register_setting(
2883          'discussion',
2884          'default_ping_status',
2885          array(
2886              'show_in_rest' => array(
2887                  'schema' => array(
2888                      'enum' => array( 'open', 'closed' ),
2889                  ),
2890              ),
2891              'type'         => 'string',
2892              'description'  => __( 'Allow link notifications from other blogs (pingbacks and trackbacks) on new articles.' ),
2893          )
2894      );
2895  
2896      register_setting(
2897          'discussion',
2898          'default_comment_status',
2899          array(
2900              'show_in_rest' => array(
2901                  'schema' => array(
2902                      'enum' => array( 'open', 'closed' ),
2903                  ),
2904              ),
2905              'type'         => 'string',
2906              'label'        => __( 'Allow comments on new posts' ),
2907              'description'  => __( 'Allow people to submit comments on new posts.' ),
2908          )
2909      );
2910  }
2911  
2912  /**
2913   * Registers a setting and its data.
2914   *
2915   * @since 2.7.0
2916   * @since 3.0.0 The `misc` option group was deprecated.
2917   * @since 3.5.0 The `privacy` option group was deprecated.
2918   * @since 4.7.0 `$args` can be passed to set flags on the setting, similar to `register_meta()`.
2919   * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`.
2920   *              Please consider writing more inclusive code.
2921   * @since 6.6.0 Added the `label` argument.
2922   *
2923   * @global array $new_allowed_options
2924   * @global array $wp_registered_settings
2925   *
2926   * @param string $option_group A settings group name. Should correspond to an allowed option key name.
2927   *                             Default allowed option key names include 'general', 'discussion', 'media',
2928   *                             'reading', 'writing', and 'options'.
2929   * @param string $option_name The name of an option to sanitize and save.
2930   * @param array  $args {
2931   *     Data used to describe the setting when registered.
2932   *
2933   *     @type string     $type              The type of data associated with this setting.
2934   *                                         Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
2935   *     @type string     $label             A label of the data attached to this setting.
2936   *     @type string     $description       A description of the data attached to this setting.
2937   *     @type callable   $sanitize_callback A callback function that sanitizes the option's value.
2938   *     @type bool|array $show_in_rest      Whether data associated with this setting should be included in the REST API.
2939   *                                         When registering complex settings, this argument may optionally be an
2940   *                                         array with a 'schema' key.
2941   *     @type mixed      $default           Default value when calling `get_option()`.
2942   * }
2943   */
2944  function register_setting( $option_group, $option_name, $args = array() ) {
2945      global $new_allowed_options, $wp_registered_settings;
2946  
2947      /*
2948       * In 5.5.0, the `$new_whitelist_options` global variable was renamed to `$new_allowed_options`.
2949       * Please consider writing more inclusive code.
2950       */
2951      $GLOBALS['new_whitelist_options'] = &$new_allowed_options;
2952  
2953      $defaults = array(
2954          'type'              => 'string',
2955          'group'             => $option_group,
2956          'label'             => '',
2957          'description'       => '',
2958          'sanitize_callback' => null,
2959          'show_in_rest'      => false,
2960      );
2961  
2962      // Back-compat: old sanitize callback is added.
2963      if ( is_callable( $args ) ) {
2964          $args = array(
2965              'sanitize_callback' => $args,
2966          );
2967      }
2968  
2969      /**
2970       * Filters the registration arguments when registering a setting.
2971       *
2972       * @since 4.7.0
2973       *
2974       * @param array  $args         Array of setting registration arguments.
2975       * @param array  $defaults     Array of default arguments.
2976       * @param string $option_group Setting group.
2977       * @param string $option_name  Setting name.
2978       */
2979      $args = apply_filters( 'register_setting_args', $args, $defaults, $option_group, $option_name );
2980  
2981      $args = wp_parse_args( $args, $defaults );
2982  
2983      // Require an item schema when registering settings with an array type.
2984      if ( false !== $args['show_in_rest'] && 'array' === $args['type'] && ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) ) {
2985          _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' );
2986      }
2987  
2988      if ( ! is_array( $wp_registered_settings ) ) {
2989          $wp_registered_settings = array();
2990      }
2991  
2992      if ( 'misc' === $option_group ) {
2993          _deprecated_argument(
2994              __FUNCTION__,
2995              '3.0.0',
2996              sprintf(
2997                  /* translators: %s: misc */
2998                  __( 'The "%s" options group has been removed. Use another settings group.' ),
2999                  'misc'
3000              )
3001          );
3002          $option_group = 'general';
3003      }
3004  
3005      if ( 'privacy' === $option_group ) {
3006          _deprecated_argument(
3007              __FUNCTION__,
3008              '3.5.0',
3009              sprintf(
3010                  /* translators: %s: privacy */
3011                  __( 'The "%s" options group has been removed. Use another settings group.' ),
3012                  'privacy'
3013              )
3014          );
3015          $option_group = 'reading';
3016      }
3017  
3018      $new_allowed_options[ $option_group ][] = $option_name;
3019  
3020      if ( ! empty( $args['sanitize_callback'] ) ) {
3021          add_filter( "sanitize_option_{$option_name}", $args['sanitize_callback'] );
3022      }
3023      if ( array_key_exists( 'default', $args ) ) {
3024          add_filter( "default_option_{$option_name}", 'filter_default_option', 10, 3 );
3025      }
3026  
3027      /**
3028       * Fires immediately before the setting is registered but after its filters are in place.
3029       *
3030       * @since 5.5.0
3031       *
3032       * @param string $option_group Setting group.
3033       * @param string $option_name  Setting name.
3034       * @param array  $args         Array of setting registration arguments.
3035       */
3036      do_action( 'register_setting', $option_group, $option_name, $args );
3037  
3038      $wp_registered_settings[ $option_name ] = $args;
3039  }
3040  
3041  /**
3042   * Unregisters a setting.
3043   *
3044   * @since 2.7.0
3045   * @since 4.7.0 `$sanitize_callback` was deprecated. The callback from `register_setting()` is now used instead.
3046   * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`.
3047   *              Please consider writing more inclusive code.
3048   *
3049   * @global array $new_allowed_options
3050   * @global array $wp_registered_settings
3051   *
3052   * @param string   $option_group The settings group name used during registration.
3053   * @param string   $option_name  The name of the option to unregister.
3054   * @param callable $deprecated   Optional. Deprecated.
3055   */
3056  function unregister_setting( $option_group, $option_name, $deprecated = '' ) {
3057      global $new_allowed_options, $wp_registered_settings;
3058  
3059      /*
3060       * In 5.5.0, the `$new_whitelist_options` global variable was renamed to `$new_allowed_options`.
3061       * Please consider writing more inclusive code.
3062       */
3063      $GLOBALS['new_whitelist_options'] = &$new_allowed_options;
3064  
3065      if ( 'misc' === $option_group ) {
3066          _deprecated_argument(
3067              __FUNCTION__,
3068              '3.0.0',
3069              sprintf(
3070                  /* translators: %s: misc */
3071                  __( 'The "%s" options group has been removed. Use another settings group.' ),
3072                  'misc'
3073              )
3074          );
3075          $option_group = 'general';
3076      }
3077  
3078      if ( 'privacy' === $option_group ) {
3079          _deprecated_argument(
3080              __FUNCTION__,
3081              '3.5.0',
3082              sprintf(
3083                  /* translators: %s: privacy */
3084                  __( 'The "%s" options group has been removed. Use another settings group.' ),
3085                  'privacy'
3086              )
3087          );
3088          $option_group = 'reading';
3089      }
3090  
3091      $pos = false;
3092      if ( isset( $new_allowed_options[ $option_group ] ) ) {
3093          $pos = array_search( $option_name, (array) $new_allowed_options[ $option_group ], true );
3094      }
3095  
3096      if ( false !== $pos ) {
3097          unset( $new_allowed_options[ $option_group ][ $pos ] );
3098      }
3099  
3100      if ( '' !== $deprecated ) {
3101          _deprecated_argument(
3102              __FUNCTION__,
3103              '4.7.0',
3104              sprintf(
3105                  /* translators: 1: $sanitize_callback, 2: register_setting() */
3106                  __( '%1$s is deprecated. The callback from %2$s is used instead.' ),
3107                  '<code>$sanitize_callback</code>',
3108                  '<code>register_setting()</code>'
3109              )
3110          );
3111          remove_filter( "sanitize_option_{$option_name}", $deprecated );
3112      }
3113  
3114      if ( isset( $wp_registered_settings[ $option_name ] ) ) {
3115          // Remove the sanitize callback if one was set during registration.
3116          if ( ! empty( $wp_registered_settings[ $option_name ]['sanitize_callback'] ) ) {
3117              remove_filter( "sanitize_option_{$option_name}", $wp_registered_settings[ $option_name ]['sanitize_callback'] );
3118          }
3119  
3120          // Remove the default filter if a default was provided during registration.
3121          if ( array_key_exists( 'default', $wp_registered_settings[ $option_name ] ) ) {
3122              remove_filter( "default_option_{$option_name}", 'filter_default_option', 10 );
3123          }
3124  
3125          /**
3126           * Fires immediately before the setting is unregistered and after its filters have been removed.
3127           *
3128           * @since 5.5.0
3129           *
3130           * @param string $option_group Setting group.
3131           * @param string $option_name  Setting name.
3132           */
3133          do_action( 'unregister_setting', $option_group, $option_name );
3134  
3135          unset( $wp_registered_settings[ $option_name ] );
3136      }
3137  }
3138  
3139  /**
3140   * Retrieves an array of registered settings.
3141   *
3142   * @since 4.7.0
3143   *
3144   * @global array $wp_registered_settings
3145   *
3146   * @return array List of registered settings, keyed by option name.
3147   */
3148  function get_registered_settings() {
3149      global $wp_registered_settings;
3150  
3151      if ( ! is_array( $wp_registered_settings ) ) {
3152          return array();
3153      }
3154  
3155      return $wp_registered_settings;
3156  }
3157  
3158  /**
3159   * Filters the default value for the option.
3160   *
3161   * For settings which register a default setting in `register_setting()`, this
3162   * function is added as a filter to `default_option_{$option}`.
3163   *
3164   * @since 4.7.0
3165   *
3166   * @param mixed  $default_value  Existing default value to return.
3167   * @param string $option         Option name.
3168   * @param bool   $passed_default Was `get_option()` passed a default value?
3169   * @return mixed Filtered default value.
3170   */
3171  function filter_default_option( $default_value, $option, $passed_default ) {
3172      if ( $passed_default ) {
3173          return $default_value;
3174      }
3175  
3176      $registered = get_registered_settings();
3177      if ( empty( $registered[ $option ] ) ) {
3178          return $default_value;
3179      }
3180  
3181      return $registered[ $option ]['default'];
3182  }
3183  
3184  /**
3185   * Returns the values that trigger autoloading from the options table.
3186   *
3187   * @since 6.6.0
3188   *
3189   * @return string[] The values that trigger autoloading.
3190   */
3191  function wp_autoload_values_to_autoload() {
3192      $autoload_values = array( 'yes', 'on', 'auto-on', 'auto' );
3193  
3194      /**
3195       * Filters the autoload values that should be considered for autoloading from the options table.
3196       *
3197       * The filter can only be used to remove autoload values from the default list.
3198       *
3199       * @since 6.6.0
3200       *
3201       * @param string[] $autoload_values Autoload values used to autoload option.
3202       *                               Default list contains 'yes', 'on', 'auto-on', and 'auto'.
3203       */
3204      $filtered_values = apply_filters( 'wp_autoload_values_to_autoload', $autoload_values );
3205  
3206      return array_intersect( $filtered_values, $autoload_values );
3207  }


Generated : Tue Dec 24 08:20:01 2024 Cross-referenced by PHPXref