Diff: STRATO-apps/wordpress_03/app/wp-includes/option.php

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