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