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