Issues (2010)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

wp-includes/option.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 or does not have a value, then the return value
13
 * will be false. This is useful to check whether you need to install an option
14
 * and is commonly used during installation of plugin options and to test
15
 * whether upgrading is required.
16
 *
17
 * If the option was serialized then it will be unserialized when it is returned.
18
 *
19
 * Any scalar values will be returned as strings. You may coerce the return type of
20
 * a given option by registering an {@see 'option_$option'} filter callback.
21
 *
22
 * @since 1.5.0
23
 *
24
 * @global wpdb $wpdb WordPress database abstraction object.
25
 *
26
 * @param string $option  Name of option to retrieve. Expected to not be SQL-escaped.
27
 * @param mixed  $default Optional. Default value to return if the option does not exist.
28
 * @return mixed Value set for the option.
29
 */
30
function get_option( $option, $default = false ) {
31
	global $wpdb;
32
33
	$option = trim( $option );
34
	if ( empty( $option ) )
35
		return false;
36
37
	/**
38
	 * Filters the value of an existing option before it is retrieved.
39
	 *
40
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
41
	 *
42
	 * Passing a truthy value to the filter will short-circuit retrieving
43
	 * the option value, returning the passed value instead.
44
	 *
45
	 * @since 1.5.0
46
	 * @since 4.4.0 The `$option` parameter was added.
47
	 *
48
	 * @param bool|mixed $pre_option Value to return instead of the option value.
49
	 *                               Default false to skip it.
50
	 * @param string     $option     Option name.
51
	 */
52
	$pre = apply_filters( "pre_option_{$option}", false, $option );
53
	if ( false !== $pre )
54
		return $pre;
55
56
	if ( defined( 'WP_SETUP_CONFIG' ) )
57
		return false;
58
59
	if ( ! wp_installing() ) {
60
		// prevent non-existent options from triggering multiple queries
61
		$notoptions = wp_cache_get( 'notoptions', 'options' );
62
		if ( isset( $notoptions[ $option ] ) ) {
63
			/**
64
			 * Filters the default value for an option.
65
			 *
66
			 * The dynamic portion of the hook name, `$option`, refers to the option name.
67
			 *
68
			 * @since 3.4.0
69
			 * @since 4.4.0 The `$option` parameter was added.
70
			 *
71
			 * @param mixed  $default The default value to return if the option does not exist
72
			 *                        in the database.
73
			 * @param string $option  Option name.
74
			 */
75
			return apply_filters( "default_option_{$option}", $default, $option );
76
		}
77
78
		$alloptions = wp_load_alloptions();
79
80
		if ( isset( $alloptions[$option] ) ) {
81
			$value = $alloptions[$option];
82
		} else {
83
			$value = wp_cache_get( $option, 'options' );
84
85
			if ( false === $value ) {
86
				$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
87
88
				// Has to be get_row instead of get_var because of funkiness with 0, false, null values
89
				if ( is_object( $row ) ) {
90
					$value = $row->option_value;
91
					wp_cache_add( $option, $value, 'options' );
92
				} else { // option does not exist, so we must cache its non-existence
93
					if ( ! is_array( $notoptions ) ) {
94
						 $notoptions = array();
95
					}
96
					$notoptions[$option] = true;
97
					wp_cache_set( 'notoptions', $notoptions, 'options' );
98
99
					/** This filter is documented in wp-includes/option.php */
100
					return apply_filters( 'default_option_' . $option, $default, $option );
101
				}
102
			}
103
		}
104
	} else {
105
		$suppress = $wpdb->suppress_errors();
106
		$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
107
		$wpdb->suppress_errors( $suppress );
108
		if ( is_object( $row ) ) {
109
			$value = $row->option_value;
110
		} else {
111
			/** This filter is documented in wp-includes/option.php */
112
			return apply_filters( 'default_option_' . $option, $default, $option );
113
		}
114
	}
115
116
	// If home is not set use siteurl.
117
	if ( 'home' == $option && '' == $value )
118
		return get_option( 'siteurl' );
119
120
	if ( in_array( $option, array('siteurl', 'home', 'category_base', 'tag_base') ) )
121
		$value = untrailingslashit( $value );
122
123
	/**
124
	 * Filters the value of an existing option.
125
	 *
126
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
127
	 *
128
	 * @since 1.5.0 As 'option_' . $setting
129
	 * @since 3.0.0
130
	 * @since 4.4.0 The `$option` parameter was added.
131
	 *
132
	 * @param mixed  $value  Value of the option. If stored serialized, it will be
133
	 *                       unserialized prior to being returned.
134
	 * @param string $option Option name.
135
	 */
136
	return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
137
}
138
139
/**
140
 * Protect WordPress special option from being modified.
141
 *
142
 * Will die if $option is in protected list. Protected options are 'alloptions'
143
 * and 'notoptions' options.
144
 *
145
 * @since 2.2.0
146
 *
147
 * @param string $option Option name.
148
 */
149
function wp_protect_special_option( $option ) {
150
	if ( 'alloptions' === $option || 'notoptions' === $option )
151
		wp_die( sprintf( __( '%s is a protected WP option and may not be modified' ), esc_html( $option ) ) );
152
}
153
154
/**
155
 * Print option value after sanitizing for forms.
156
 *
157
 * @since 1.5.0
158
 *
159
 * @param string $option Option name.
160
 */
161
function form_option( $option ) {
162
	echo esc_attr( get_option( $option ) );
163
}
164
165
/**
166
 * Loads and caches all autoloaded options, if available or all options.
167
 *
168
 * @since 2.2.0
169
 *
170
 * @global wpdb $wpdb WordPress database abstraction object.
171
 *
172
 * @return array List of all options.
173
 */
174
function wp_load_alloptions() {
175
	global $wpdb;
176
177
	if ( ! wp_installing() || ! is_multisite() )
178
		$alloptions = wp_cache_get( 'alloptions', 'options' );
179
	else
180
		$alloptions = false;
181
182
	if ( !$alloptions ) {
183
		$suppress = $wpdb->suppress_errors();
184
		if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
185
			$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
186
		$wpdb->suppress_errors($suppress);
187
		$alloptions = array();
188
		foreach ( (array) $alloptions_db as $o ) {
189
			$alloptions[$o->option_name] = $o->option_value;
190
		}
191
		if ( ! wp_installing() || ! is_multisite() )
192
			wp_cache_add( 'alloptions', $alloptions, 'options' );
193
	}
194
195
	return $alloptions;
196
}
197
198
/**
199
 * Loads and caches certain often requested site options if is_multisite() and a persistent cache is not being used.
200
 *
201
 * @since 3.0.0
202
 *
203
 * @global wpdb $wpdb WordPress database abstraction object.
204
 *
205
 * @param int $site_id Optional site ID for which to query the options. Defaults to the current site.
206
 */
207
function wp_load_core_site_options( $site_id = null ) {
208
	global $wpdb;
209
210
	if ( ! is_multisite() || wp_using_ext_object_cache() || wp_installing() )
211
		return;
212
213
	if ( empty($site_id) )
214
		$site_id = $wpdb->siteid;
215
216
	$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' );
217
218
	$core_options_in = "'" . implode("', '", $core_options) . "'";
219
	$options = $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $site_id) );
220
221
	foreach ( $options as $option ) {
222
		$key = $option->meta_key;
223
		$cache_key = "{$site_id}:$key";
224
		$option->meta_value = maybe_unserialize( $option->meta_value );
225
226
		wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
227
	}
228
}
229
230
/**
231
 * Update the value of an option that was already added.
232
 *
233
 * You do not need to serialize values. If the value needs to be serialized, then
234
 * it will be serialized before it is inserted into the database. Remember,
235
 * resources can not be serialized or added as an option.
236
 *
237
 * If the option does not exist, then the option will be added with the option value,
238
 * with an `$autoload` value of 'yes'.
239
 *
240
 * @since 1.0.0
241
 * @since 4.2.0 The `$autoload` parameter was added.
242
 *
243
 * @global wpdb $wpdb WordPress database abstraction object.
244
 *
245
 * @param string      $option   Option name. Expected to not be SQL-escaped.
246
 * @param mixed       $value    Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
247
 * @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
248
 *                              `$autoload` can only be updated using `update_option()` if `$value` is also changed.
249
 *                              Accepts 'yes'|true to enable or 'no'|false to disable. For non-existent options,
250
 *                              the default value is 'yes'. Default null.
251
 * @return bool False if value was not updated and true if value was updated.
252
 */
253
function update_option( $option, $value, $autoload = null ) {
254
	global $wpdb;
255
256
	$option = trim($option);
257
	if ( empty($option) )
258
		return false;
259
260
	wp_protect_special_option( $option );
261
262
	if ( is_object( $value ) )
263
		$value = clone $value;
264
265
	$value = sanitize_option( $option, $value );
266
	$old_value = get_option( $option );
267
268
	/**
269
	 * Filters a specific option before its value is (maybe) serialized and updated.
270
	 *
271
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
272
	 *
273
	 * @since 2.6.0
274
	 * @since 4.4.0 The `$option` parameter was added.
275
	 *
276
	 * @param mixed  $value     The new, unserialized option value.
277
	 * @param mixed  $old_value The old option value.
278
	 * @param string $option    Option name.
279
	 */
280
	$value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );
281
282
	/**
283
	 * Filters an option before its value is (maybe) serialized and updated.
284
	 *
285
	 * @since 3.9.0
286
	 *
287
	 * @param mixed  $value     The new, unserialized option value.
288
	 * @param string $option    Name of the option.
289
	 * @param mixed  $old_value The old option value.
290
	 */
291
	$value = apply_filters( 'pre_update_option', $value, $option, $old_value );
292
293
	// If the new and old values are the same, no need to update.
294
	if ( $value === $old_value )
295
		return false;
296
297
	/** This filter is documented in wp-includes/option.php */
298
	if ( apply_filters( 'default_option_' . $option, false, $option ) === $old_value ) {
299
		// Default setting for new options is 'yes'.
300
		if ( null === $autoload ) {
301
			$autoload = 'yes';
302
		}
303
304
		return add_option( $option, $value, '', $autoload );
305
	}
306
307
	$serialized_value = maybe_serialize( $value );
308
309
	/**
310
	 * Fires immediately before an option value is updated.
311
	 *
312
	 * @since 2.9.0
313
	 *
314
	 * @param string $option    Name of the option to update.
315
	 * @param mixed  $old_value The old option value.
316
	 * @param mixed  $value     The new option value.
317
	 */
318
	do_action( 'update_option', $option, $old_value, $value );
319
320
	$update_args = array(
321
		'option_value' => $serialized_value,
322
	);
323
324
	if ( null !== $autoload ) {
325
		$update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
326
	}
327
328
	$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
329
	if ( ! $result )
330
		return false;
331
332
	$notoptions = wp_cache_get( 'notoptions', 'options' );
333
	if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
334
		unset( $notoptions[$option] );
335
		wp_cache_set( 'notoptions', $notoptions, 'options' );
336
	}
337
338 View Code Duplication
	if ( ! wp_installing() ) {
339
		$alloptions = wp_load_alloptions();
340
		if ( isset( $alloptions[$option] ) ) {
341
			$alloptions[ $option ] = $serialized_value;
342
			wp_cache_set( 'alloptions', $alloptions, 'options' );
343
		} else {
344
			wp_cache_set( $option, $serialized_value, 'options' );
345
		}
346
	}
347
348
	/**
349
	 * Fires after the value of a specific option has been successfully updated.
350
	 *
351
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
352
	 *
353
	 * @since 2.0.1
354
	 * @since 4.4.0 The `$option` parameter was added.
355
	 *
356
	 * @param mixed  $old_value The old option value.
357
	 * @param mixed  $value     The new option value.
358
	 * @param string $option    Option name.
359
	 */
360
	do_action( "update_option_{$option}", $old_value, $value, $option );
361
362
	/**
363
	 * Fires after the value of an option has been successfully updated.
364
	 *
365
	 * @since 2.9.0
366
	 *
367
	 * @param string $option    Name of the updated option.
368
	 * @param mixed  $old_value The old option value.
369
	 * @param mixed  $value     The new option value.
370
	 */
371
	do_action( 'updated_option', $option, $old_value, $value );
372
	return true;
373
}
374
375
/**
376
 * Add a new option.
377
 *
378
 * You do not need to serialize values. If the value needs to be serialized, then
379
 * it will be serialized before it is inserted into the database. Remember,
380
 * resources can not be serialized or added as an option.
381
 *
382
 * You can create options without values and then update the values later.
383
 * Existing options will not be updated and checks are performed to ensure that you
384
 * aren't adding a protected WordPress option. Care should be taken to not name
385
 * options the same as the ones which are protected.
386
 *
387
 * @since 1.0.0
388
 *
389
 * @global wpdb $wpdb WordPress database abstraction object.
390
 *
391
 * @param string         $option      Name of option to add. Expected to not be SQL-escaped.
392
 * @param mixed          $value       Optional. Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
393
 * @param string         $deprecated  Optional. Description. Not used anymore.
394
 * @param string|bool    $autoload    Optional. Whether to load the option when WordPress starts up.
395
 *                                    Default is enabled. Accepts 'no' to disable for legacy reasons.
396
 * @return bool False if option was not added and true if option was added.
397
 */
398
function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
399
	global $wpdb;
400
401
	if ( !empty( $deprecated ) )
402
		_deprecated_argument( __FUNCTION__, '2.3.0' );
403
404
	$option = trim($option);
405
	if ( empty($option) )
406
		return false;
407
408
	wp_protect_special_option( $option );
409
410
	if ( is_object($value) )
411
		$value = clone $value;
412
413
	$value = sanitize_option( $option, $value );
414
415
	// Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
416
	$notoptions = wp_cache_get( 'notoptions', 'options' );
417
	if ( !is_array( $notoptions ) || !isset( $notoptions[$option] ) )
418
		/** This filter is documented in wp-includes/option.php */
419
		if ( apply_filters( 'default_option_' . $option, false, $option ) !== get_option( $option ) )
420
			return false;
421
422
	$serialized_value = maybe_serialize( $value );
423
	$autoload = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
424
425
	/**
426
	 * Fires before an option is added.
427
	 *
428
	 * @since 2.9.0
429
	 *
430
	 * @param string $option Name of the option to add.
431
	 * @param mixed  $value  Value of the option.
432
	 */
433
	do_action( 'add_option', $option, $value );
434
435
	$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 ) );
436
	if ( ! $result )
437
		return false;
438
439 View Code Duplication
	if ( ! wp_installing() ) {
440
		if ( 'yes' == $autoload ) {
441
			$alloptions = wp_load_alloptions();
442
			$alloptions[ $option ] = $serialized_value;
443
			wp_cache_set( 'alloptions', $alloptions, 'options' );
444
		} else {
445
			wp_cache_set( $option, $serialized_value, 'options' );
446
		}
447
	}
448
449
	// This option exists now
450
	$notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
451
	if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
452
		unset( $notoptions[$option] );
453
		wp_cache_set( 'notoptions', $notoptions, 'options' );
454
	}
455
456
	/**
457
	 * Fires after a specific option has been added.
458
	 *
459
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
460
	 *
461
	 * @since 2.5.0 As "add_option_{$name}"
462
	 * @since 3.0.0
463
	 *
464
	 * @param string $option Name of the option to add.
465
	 * @param mixed  $value  Value of the option.
466
	 */
467
	do_action( "add_option_{$option}", $option, $value );
468
469
	/**
470
	 * Fires after an option has been added.
471
	 *
472
	 * @since 2.9.0
473
	 *
474
	 * @param string $option Name of the added option.
475
	 * @param mixed  $value  Value of the option.
476
	 */
477
	do_action( 'added_option', $option, $value );
478
	return true;
479
}
480
481
/**
482
 * Removes option by name. Prevents removal of protected WordPress options.
483
 *
484
 * @since 1.2.0
485
 *
486
 * @global wpdb $wpdb WordPress database abstraction object.
487
 *
488
 * @param string $option Name of option to remove. Expected to not be SQL-escaped.
489
 * @return bool True, if option is successfully deleted. False on failure.
490
 */
491
function delete_option( $option ) {
492
	global $wpdb;
493
494
	$option = trim( $option );
495
	if ( empty( $option ) )
496
		return false;
497
498
	wp_protect_special_option( $option );
499
500
	// Get the ID, if no ID then return
501
	$row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
502
	if ( is_null( $row ) )
503
		return false;
504
505
	/**
506
	 * Fires immediately before an option is deleted.
507
	 *
508
	 * @since 2.9.0
509
	 *
510
	 * @param string $option Name of the option to delete.
511
	 */
512
	do_action( 'delete_option', $option );
513
514
	$result = $wpdb->delete( $wpdb->options, array( 'option_name' => $option ) );
515 View Code Duplication
	if ( ! wp_installing() ) {
516
		if ( 'yes' == $row->autoload ) {
517
			$alloptions = wp_load_alloptions();
518
			if ( is_array( $alloptions ) && isset( $alloptions[$option] ) ) {
519
				unset( $alloptions[$option] );
520
				wp_cache_set( 'alloptions', $alloptions, 'options' );
521
			}
522
		} else {
523
			wp_cache_delete( $option, 'options' );
524
		}
525
	}
526
	if ( $result ) {
527
528
		/**
529
		 * Fires after a specific option has been deleted.
530
		 *
531
		 * The dynamic portion of the hook name, `$option`, refers to the option name.
532
		 *
533
		 * @since 3.0.0
534
		 *
535
		 * @param string $option Name of the deleted option.
536
		 */
537
		do_action( "delete_option_{$option}", $option );
538
539
		/**
540
		 * Fires after an option has been deleted.
541
		 *
542
		 * @since 2.9.0
543
		 *
544
		 * @param string $option Name of the deleted option.
545
		 */
546
		do_action( 'deleted_option', $option );
547
		return true;
548
	}
549
	return false;
550
}
551
552
/**
553
 * Delete a transient.
554
 *
555
 * @since 2.8.0
556
 *
557
 * @param string $transient Transient name. Expected to not be SQL-escaped.
558
 * @return bool true if successful, false otherwise
559
 */
560 View Code Duplication
function delete_transient( $transient ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
561
562
	/**
563
	 * Fires immediately before a specific transient is deleted.
564
	 *
565
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
566
	 *
567
	 * @since 3.0.0
568
	 *
569
	 * @param string $transient Transient name.
570
	 */
571
	do_action( "delete_transient_{$transient}", $transient );
572
573
	if ( wp_using_ext_object_cache() ) {
574
		$result = wp_cache_delete( $transient, 'transient' );
575
	} else {
576
		$option_timeout = '_transient_timeout_' . $transient;
577
		$option = '_transient_' . $transient;
578
		$result = delete_option( $option );
579
		if ( $result )
580
			delete_option( $option_timeout );
581
	}
582
583
	if ( $result ) {
584
585
		/**
586
		 * Fires after a transient is deleted.
587
		 *
588
		 * @since 3.0.0
589
		 *
590
		 * @param string $transient Deleted transient name.
591
		 */
592
		do_action( 'deleted_transient', $transient );
593
	}
594
595
	return $result;
596
}
597
598
/**
599
 * Get the value of a transient.
600
 *
601
 * If the transient does not exist, does not have a value, or has expired,
602
 * then the return value will be false.
603
 *
604
 * @since 2.8.0
605
 *
606
 * @param string $transient Transient name. Expected to not be SQL-escaped.
607
 * @return mixed Value of transient.
608
 */
609
function get_transient( $transient ) {
610
611
	/**
612
	 * Filters the value of an existing transient.
613
	 *
614
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
615
	 *
616
	 * Passing a truthy value to the filter will effectively short-circuit retrieval
617
	 * of the transient, returning the passed value instead.
618
	 *
619
	 * @since 2.8.0
620
	 * @since 4.4.0 The `$transient` parameter was added
621
	 *
622
	 * @param mixed  $pre_transient The default value to return if the transient does not exist.
623
	 *                              Any value other than false will short-circuit the retrieval
624
	 *                              of the transient, and return the returned value.
625
	 * @param string $transient     Transient name.
626
	 */
627
	$pre = apply_filters( "pre_transient_{$transient}", false, $transient );
628
	if ( false !== $pre )
629
		return $pre;
630
631
	if ( wp_using_ext_object_cache() ) {
632
		$value = wp_cache_get( $transient, 'transient' );
633
	} else {
634
		$transient_option = '_transient_' . $transient;
635
		if ( ! wp_installing() ) {
636
			// If option is not in alloptions, it is not autoloaded and thus has a timeout
637
			$alloptions = wp_load_alloptions();
638 View Code Duplication
			if ( !isset( $alloptions[$transient_option] ) ) {
639
				$transient_timeout = '_transient_timeout_' . $transient;
640
				$timeout = get_option( $transient_timeout );
641
				if ( false !== $timeout && $timeout < time() ) {
642
					delete_option( $transient_option  );
643
					delete_option( $transient_timeout );
644
					$value = false;
645
				}
646
			}
647
		}
648
649
		if ( ! isset( $value ) )
650
			$value = get_option( $transient_option );
651
	}
652
653
	/**
654
	 * Filters an existing transient's value.
655
	 *
656
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
657
	 *
658
	 * @since 2.8.0
659
	 * @since 4.4.0 The `$transient` parameter was added
660
	 *
661
	 * @param mixed  $value     Value of transient.
662
	 * @param string $transient Transient name.
663
	 */
664
	return apply_filters( "transient_{$transient}", $value, $transient );
665
}
666
667
/**
668
 * Set/update the value of a transient.
669
 *
670
 * You do not need to serialize values. If the value needs to be serialized, then
671
 * it will be serialized before it is set.
672
 *
673
 * @since 2.8.0
674
 *
675
 * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
676
 *                           172 characters or fewer in length.
677
 * @param mixed  $value      Transient value. Must be serializable if non-scalar.
678
 *                           Expected to not be SQL-escaped.
679
 * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
680
 * @return bool False if value was not set and true if value was set.
681
 */
682
function set_transient( $transient, $value, $expiration = 0 ) {
683
684
	$expiration = (int) $expiration;
685
686
	/**
687
	 * Filters a specific transient before its value is set.
688
	 *
689
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
690
	 *
691
	 * @since 3.0.0
692
	 * @since 4.2.0 The `$expiration` parameter was added.
693
	 * @since 4.4.0 The `$transient` parameter was added.
694
	 *
695
	 * @param mixed  $value      New value of transient.
696
	 * @param int    $expiration Time until expiration in seconds.
697
	 * @param string $transient  Transient name.
698
	 */
699
	$value = apply_filters( "pre_set_transient_{$transient}", $value, $expiration, $transient );
700
701
	/**
702
	 * Filters the expiration for a transient before its value is set.
703
	 *
704
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
705
	 *
706
	 * @since 4.4.0
707
	 *
708
	 * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
709
	 * @param mixed  $value      New value of transient.
710
	 * @param string $transient  Transient name.
711
	 */
712
	$expiration = apply_filters( "expiration_of_transient_{$transient}", $expiration, $value, $transient );
713
714
	if ( wp_using_ext_object_cache() ) {
715
		$result = wp_cache_set( $transient, $value, 'transient', $expiration );
716
	} else {
717
		$transient_timeout = '_transient_timeout_' . $transient;
718
		$transient_option = '_transient_' . $transient;
719
		if ( false === get_option( $transient_option ) ) {
720
			$autoload = 'yes';
721
			if ( $expiration ) {
722
				$autoload = 'no';
723
				add_option( $transient_timeout, time() + $expiration, '', 'no' );
724
			}
725
			$result = add_option( $transient_option, $value, '', $autoload );
726
		} else {
727
			// If expiration is requested, but the transient has no timeout option,
728
			// delete, then re-create transient rather than update.
729
			$update = true;
730
			if ( $expiration ) {
731
				if ( false === get_option( $transient_timeout ) ) {
732
					delete_option( $transient_option );
733
					add_option( $transient_timeout, time() + $expiration, '', 'no' );
734
					$result = add_option( $transient_option, $value, '', 'no' );
735
					$update = false;
736
				} else {
737
					update_option( $transient_timeout, time() + $expiration );
738
				}
739
			}
740
			if ( $update ) {
741
				$result = update_option( $transient_option, $value );
742
			}
743
		}
744
	}
745
746
	if ( $result ) {
0 ignored issues
show
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
747
748
		/**
749
		 * Fires after the value for a specific transient has been set.
750
		 *
751
		 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
752
		 *
753
		 * @since 3.0.0
754
		 * @since 3.6.0 The `$value` and `$expiration` parameters were added.
755
		 * @since 4.4.0 The `$transient` parameter was added.
756
		 *
757
		 * @param mixed  $value      Transient value.
758
		 * @param int    $expiration Time until expiration in seconds.
759
		 * @param string $transient  The name of the transient.
760
		 */
761
		do_action( "set_transient_{$transient}", $value, $expiration, $transient );
762
763
		/**
764
		 * Fires after the value for a transient has been set.
765
		 *
766
		 * @since 3.0.0
767
		 * @since 3.6.0 The `$value` and `$expiration` parameters were added.
768
		 *
769
		 * @param string $transient  The name of the transient.
770
		 * @param mixed  $value      Transient value.
771
		 * @param int    $expiration Time until expiration in seconds.
772
		 */
773
		do_action( 'setted_transient', $transient, $value, $expiration );
774
	}
775
	return $result;
776
}
777
778
/**
779
 * Saves and restores user interface settings stored in a cookie.
780
 *
781
 * Checks if the current user-settings cookie is updated and stores it. When no
782
 * cookie exists (different browser used), adds the last saved cookie restoring
783
 * the settings.
784
 *
785
 * @since 2.7.0
786
 */
787
function wp_user_settings() {
788
789
	if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
790
		return;
791
	}
792
793
	if ( ! $user_id = get_current_user_id() ) {
794
		return;
795
	}
796
797
	if ( is_super_admin() && ! is_user_member_of_blog() ) {
798
		return;
799
	}
800
801
	$settings = (string) get_user_option( 'user-settings', $user_id );
802
803
	if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
804
		$cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user_id] );
805
806
		// No change or both empty
807
		if ( $cookie == $settings )
808
			return;
809
810
		$last_saved = (int) get_user_option( 'user-settings-time', $user_id );
811
		$current = isset( $_COOKIE['wp-settings-time-' . $user_id]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user_id] ) : 0;
812
813
		// The cookie is newer than the saved value. Update the user_option and leave the cookie as-is
814
		if ( $current > $last_saved ) {
815
			update_user_option( $user_id, 'user-settings', $cookie, false );
816
			update_user_option( $user_id, 'user-settings-time', time() - 5, false );
817
			return;
818
		}
819
	}
820
821
	// The cookie is not set in the current browser or the saved value is newer.
822
	$secure = ( 'https' === parse_url( admin_url(), PHP_URL_SCHEME ) );
823
	setcookie( 'wp-settings-' . $user_id, $settings, time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
824
	setcookie( 'wp-settings-time-' . $user_id, time(), time() + YEAR_IN_SECONDS, SITECOOKIEPATH, null, $secure );
825
	$_COOKIE['wp-settings-' . $user_id] = $settings;
826
}
827
828
/**
829
 * Retrieve user interface setting value based on setting name.
830
 *
831
 * @since 2.7.0
832
 *
833
 * @param string $name    The name of the setting.
834
 * @param string $default Optional default value to return when $name is not set.
835
 * @return mixed the last saved user setting or the default value/false if it doesn't exist.
836
 */
837
function get_user_setting( $name, $default = false ) {
838
	$all_user_settings = get_all_user_settings();
839
840
	return isset( $all_user_settings[$name] ) ? $all_user_settings[$name] : $default;
841
}
842
843
/**
844
 * Add or update user interface setting.
845
 *
846
 * Both $name and $value can contain only ASCII letters, numbers and underscores.
847
 *
848
 * This function has to be used before any output has started as it calls setcookie().
849
 *
850
 * @since 2.8.0
851
 *
852
 * @param string $name  The name of the setting.
853
 * @param string $value The value for the setting.
854
 * @return bool|null True if set successfully, false if not. Null if the current user can't be established.
855
 */
856
function set_user_setting( $name, $value ) {
857
	if ( headers_sent() ) {
858
		return false;
859
	}
860
861
	$all_user_settings = get_all_user_settings();
862
	$all_user_settings[$name] = $value;
863
864
	return wp_set_all_user_settings( $all_user_settings );
865
}
866
867
/**
868
 * Delete user interface settings.
869
 *
870
 * Deleting settings would reset them to the defaults.
871
 *
872
 * This function has to be used before any output has started as it calls setcookie().
873
 *
874
 * @since 2.7.0
875
 *
876
 * @param string $names The name or array of names of the setting to be deleted.
877
 * @return bool|null True if deleted successfully, false if not. Null if the current user can't be established.
878
 */
879
function delete_user_setting( $names ) {
880
	if ( headers_sent() ) {
881
		return false;
882
	}
883
884
	$all_user_settings = get_all_user_settings();
885
	$names = (array) $names;
886
	$deleted = false;
887
888
	foreach ( $names as $name ) {
889
		if ( isset( $all_user_settings[$name] ) ) {
890
			unset( $all_user_settings[$name] );
891
			$deleted = true;
892
		}
893
	}
894
895
	if ( $deleted ) {
896
		return wp_set_all_user_settings( $all_user_settings );
0 ignored issues
show
It seems like $all_user_settings defined by get_all_user_settings() on line 884 can also be of type null; however, wp_set_all_user_settings() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
897
	}
898
899
	return false;
900
}
901
902
/**
903
 * Retrieve all user interface settings.
904
 *
905
 * @since 2.7.0
906
 *
907
 * @global array $_updated_user_settings
908
 *
909
 * @return array the last saved user settings or empty array.
910
 */
911
function get_all_user_settings() {
912
	global $_updated_user_settings;
913
914
	if ( ! $user_id = get_current_user_id() ) {
915
		return array();
916
	}
917
918
	if ( isset( $_updated_user_settings ) && is_array( $_updated_user_settings ) ) {
919
		return $_updated_user_settings;
920
	}
921
922
	$user_settings = array();
923
924
	if ( isset( $_COOKIE['wp-settings-' . $user_id] ) ) {
925
		$cookie = preg_replace( '/[^A-Za-z0-9=&_-]/', '', $_COOKIE['wp-settings-' . $user_id] );
926
927
		if ( strpos( $cookie, '=' ) ) { // '=' cannot be 1st char
928
			parse_str( $cookie, $user_settings );
929
		}
930
	} else {
931
		$option = get_user_option( 'user-settings', $user_id );
932
933
		if ( $option && is_string( $option ) ) {
934
			parse_str( $option, $user_settings );
935
		}
936
	}
937
938
	$_updated_user_settings = $user_settings;
939
	return $user_settings;
940
}
941
942
/**
943
 * Private. Set all user interface settings.
944
 *
945
 * @since 2.8.0
946
 * @access private
947
 *
948
 * @global array $_updated_user_settings
949
 *
950
 * @param array $user_settings User settings.
951
 * @return bool|null False if the current user can't be found, null if the current
952
 *                   user is not a super admin or a member of the site, otherwise true.
953
 */
954
function wp_set_all_user_settings( $user_settings ) {
955
	global $_updated_user_settings;
956
957
	if ( ! $user_id = get_current_user_id() ) {
958
		return false;
959
	}
960
961
	if ( is_super_admin() && ! is_user_member_of_blog() ) {
962
		return;
963
	}
964
965
	$settings = '';
966
	foreach ( $user_settings as $name => $value ) {
967
		$_name = preg_replace( '/[^A-Za-z0-9_-]+/', '', $name );
968
		$_value = preg_replace( '/[^A-Za-z0-9_-]+/', '', $value );
969
970
		if ( ! empty( $_name ) ) {
971
			$settings .= $_name . '=' . $_value . '&';
972
		}
973
	}
974
975
	$settings = rtrim( $settings, '&' );
976
	parse_str( $settings, $_updated_user_settings );
977
978
	update_user_option( $user_id, 'user-settings', $settings, false );
979
	update_user_option( $user_id, 'user-settings-time', time(), false );
980
981
	return true;
982
}
983
984
/**
985
 * Delete the user settings of the current user.
986
 *
987
 * @since 2.7.0
988
 */
989
function delete_all_user_settings() {
990
	if ( ! $user_id = get_current_user_id() ) {
991
		return;
992
	}
993
994
	update_user_option( $user_id, 'user-settings', '', false );
995
	setcookie( 'wp-settings-' . $user_id, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
996
}
997
998
/**
999
 * Retrieve an option value for the current network based on name of option.
1000
 *
1001
 * @since 2.8.0
1002
 * @since 4.4.0 The `$use_cache` parameter was deprecated.
1003
 * @since 4.4.0 Modified into wrapper for get_network_option()
1004
 *
1005
 * @see get_network_option()
1006
 *
1007
 * @param string $option     Name of option to retrieve. Expected to not be SQL-escaped.
1008
 * @param mixed  $default    Optional value to return if option doesn't exist. Default false.
1009
 * @param bool   $deprecated Whether to use cache. Multisite only. Always set to true.
1010
 * @return mixed Value set for the option.
1011
 */
1012
function get_site_option( $option, $default = false, $deprecated = true ) {
1013
	return get_network_option( null, $option, $default );
1014
}
1015
1016
/**
1017
 * Add a new option for the current network.
1018
 *
1019
 * Existing options will not be updated. Note that prior to 3.3 this wasn't the case.
1020
 *
1021
 * @since 2.8.0
1022
 * @since 4.4.0 Modified into wrapper for add_network_option()
1023
 *
1024
 * @see add_network_option()
1025
 *
1026
 * @param string $option Name of option to add. Expected to not be SQL-escaped.
1027
 * @param mixed  $value  Option value, can be anything. Expected to not be SQL-escaped.
1028
 * @return bool False if the option was not added. True if the option was added.
1029
 */
1030
function add_site_option( $option, $value ) {
1031
	return add_network_option( null, $option, $value );
1032
}
1033
1034
/**
1035
 * Removes a option by name for the current network.
1036
 *
1037
 * @since 2.8.0
1038
 * @since 4.4.0 Modified into wrapper for delete_network_option()
1039
 *
1040
 * @see delete_network_option()
1041
 *
1042
 * @param string $option Name of option to remove. Expected to not be SQL-escaped.
1043
 * @return bool True, if succeed. False, if failure.
1044
 */
1045
function delete_site_option( $option ) {
1046
	return delete_network_option( null, $option );
1047
}
1048
1049
/**
1050
 * Update the value of an option that was already added for the current network.
1051
 *
1052
 * @since 2.8.0
1053
 * @since 4.4.0 Modified into wrapper for update_network_option()
1054
 *
1055
 * @see update_network_option()
1056
 *
1057
 * @param string $option Name of option. Expected to not be SQL-escaped.
1058
 * @param mixed  $value  Option value. Expected to not be SQL-escaped.
1059
 * @return bool False if value was not updated. True if value was updated.
1060
 */
1061
function update_site_option( $option, $value ) {
1062
	return update_network_option( null, $option, $value );
1063
}
1064
1065
/**
1066
 * Retrieve a network's option value based on the option name.
1067
 *
1068
 * @since 4.4.0
1069
 *
1070
 * @see get_option()
1071
 *
1072
 * @global wpdb   $wpdb
1073
 * @global object $current_site
1074
 *
1075
 * @param int      $network_id ID of the network. Can be null to default to the current network ID.
1076
 * @param string   $option     Name of option to retrieve. Expected to not be SQL-escaped.
1077
 * @param mixed    $default    Optional. Value to return if the option doesn't exist. Default false.
1078
 * @return mixed Value set for the option.
1079
 */
1080
function get_network_option( $network_id, $option, $default = false ) {
1081
	global $wpdb, $current_site;
1082
1083
	if ( $network_id && ! is_numeric( $network_id ) ) {
1084
		return false;
1085
	}
1086
1087
	$network_id = (int) $network_id;
1088
1089
	// Fallback to the current network if a network ID is not specified.
1090
	if ( ! $network_id && is_multisite() ) {
1091
		$network_id = $current_site->id;
1092
	}
1093
1094
	/**
1095
	 * Filters an existing network option before it is retrieved.
1096
	 *
1097
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
1098
	 *
1099
	 * Passing a truthy value to the filter will effectively short-circuit retrieval,
1100
	 * returning the passed value instead.
1101
	 *
1102
	 * @since 2.9.0 As 'pre_site_option_' . $key
1103
	 * @since 3.0.0
1104
	 * @since 4.4.0 The `$option` parameter was added
1105
	 *
1106
	 * @param mixed  $pre_option The default value to return if the option does not exist.
1107
	 * @param string $option     Option name.
1108
	 */
1109
	$pre = apply_filters( "pre_site_option_{$option}", false, $option );
1110
1111
	if ( false !== $pre ) {
1112
		return $pre;
1113
	}
1114
1115
	// prevent non-existent options from triggering multiple queries
1116
	$notoptions_key = "$network_id:notoptions";
1117
	$notoptions = wp_cache_get( $notoptions_key, 'site-options' );
1118
1119
	if ( isset( $notoptions[ $option ] ) ) {
1120
1121
		/**
1122
		 * Filters a specific default network option.
1123
		 *
1124
		 * The dynamic portion of the hook name, `$option`, refers to the option name.
1125
		 *
1126
		 * @since 3.4.0
1127
		 * @since 4.4.0 The `$option` parameter was added.
1128
		 *
1129
		 * @param mixed  $default The value to return if the site option does not exist
1130
		 *                        in the database.
1131
		 * @param string $option  Option name.
1132
		 */
1133
		return apply_filters( "default_site_option_{$option}", $default, $option );
1134
	}
1135
1136
	if ( ! is_multisite() ) {
1137
		/** This filter is documented in wp-includes/option.php */
1138
		$default = apply_filters( 'default_site_option_' . $option, $default, $option );
1139
		$value = get_option( $option, $default );
1140
	} else {
1141
		$cache_key = "$network_id:$option";
1142
		$value = wp_cache_get( $cache_key, 'site-options' );
1143
1144
		if ( ! isset( $value ) || false === $value ) {
1145
			$row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
1146
1147
			// Has to be get_row instead of get_var because of funkiness with 0, false, null values
1148
			if ( is_object( $row ) ) {
1149
				$value = $row->meta_value;
1150
				$value = maybe_unserialize( $value );
1151
				wp_cache_set( $cache_key, $value, 'site-options' );
1152
			} else {
1153
				if ( ! is_array( $notoptions ) ) {
1154
					$notoptions = array();
1155
				}
1156
				$notoptions[ $option ] = true;
1157
				wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1158
1159
				/** This filter is documented in wp-includes/option.php */
1160
				$value = apply_filters( 'default_site_option_' . $option, $default, $option );
1161
			}
1162
		}
1163
	}
1164
1165
	/**
1166
	 * Filters the value of an existing network option.
1167
	 *
1168
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
1169
	 *
1170
	 * @since 2.9.0 As 'site_option_' . $key
1171
	 * @since 3.0.0
1172
	 * @since 4.4.0 The `$option` parameter was added
1173
	 *
1174
	 * @param mixed  $value  Value of network option.
1175
	 * @param string $option Option name.
1176
	 */
1177
	return apply_filters( "site_option_{$option}", $value, $option );
1178
}
1179
1180
/**
1181
 * Add a new network option.
1182
 *
1183
 * Existing options will not be updated.
1184
 *
1185
 * @since 4.4.0
1186
 *
1187
 * @see add_option()
1188
 *
1189
 * @global wpdb   $wpdb
1190
 * @global object $current_site
1191
 *
1192
 * @param int    $network_id ID of the network. Can be null to default to the current network ID.
1193
 * @param string $option     Name of option to add. Expected to not be SQL-escaped.
1194
 * @param mixed  $value      Option value, can be anything. Expected to not be SQL-escaped.
1195
 * @return bool False if option was not added and true if option was added.
1196
 */
1197
function add_network_option( $network_id, $option, $value ) {
1198
	global $wpdb, $current_site;
1199
1200
	if ( $network_id && ! is_numeric( $network_id ) ) {
1201
		return false;
1202
	}
1203
1204
	$network_id = (int) $network_id;
1205
1206
	// Fallback to the current network if a network ID is not specified.
1207
	if ( ! $network_id && is_multisite() ) {
1208
		$network_id = $current_site->id;
1209
	}
1210
1211
	wp_protect_special_option( $option );
1212
1213
	/**
1214
	 * Filters the value of a specific network option before it is added.
1215
	 *
1216
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
1217
	 *
1218
	 * @since 2.9.0 As 'pre_add_site_option_' . $key
1219
	 * @since 3.0.0
1220
	 * @since 4.4.0 The `$option` parameter was added
1221
	 *
1222
	 * @param mixed  $value  Value of network option.
1223
	 * @param string $option Option name.
1224
	 */
1225
	$value = apply_filters( "pre_add_site_option_{$option}", $value, $option );
1226
1227
	$notoptions_key = "$network_id:notoptions";
1228
1229
	if ( ! is_multisite() ) {
1230
		$result = add_option( $option, $value, '', 'no' );
1231
	} else {
1232
		$cache_key = "$network_id:$option";
1233
1234
		// Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
1235
		$notoptions = wp_cache_get( $notoptions_key, 'site-options' );
1236
		if ( ! is_array( $notoptions ) || ! isset( $notoptions[ $option ] ) ) {
1237
			if ( false !== get_network_option( $network_id, $option, false ) ) {
1238
				return false;
1239
			}
1240
		}
1241
1242
		$value = sanitize_option( $option, $value );
1243
1244
		$serialized_value = maybe_serialize( $value );
1245
		$result = $wpdb->insert( $wpdb->sitemeta, array( 'site_id'    => $network_id, 'meta_key'   => $option, 'meta_value' => $serialized_value ) );
1246
1247
		if ( ! $result ) {
1248
			return false;
1249
		}
1250
1251
		wp_cache_set( $cache_key, $value, 'site-options' );
1252
1253
		// This option exists now
1254
		$notoptions = wp_cache_get( $notoptions_key, 'site-options' ); // yes, again... we need it to be fresh
1255 View Code Duplication
		if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1256
			unset( $notoptions[ $option ] );
1257
			wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1258
		}
1259
	}
1260
1261
	if ( $result ) {
1262
1263
		/**
1264
		 * Fires after a specific network option has been successfully added.
1265
		 *
1266
		 * The dynamic portion of the hook name, `$option`, refers to the option name.
1267
		 *
1268
		 * @since 2.9.0 As "add_site_option_{$key}"
1269
		 * @since 3.0.0
1270
		 *
1271
		 * @param string $option Name of the network option.
1272
		 * @param mixed  $value  Value of the network option.
1273
		 */
1274
		do_action( "add_site_option_{$option}", $option, $value );
1275
1276
		/**
1277
		 * Fires after a network option has been successfully added.
1278
		 *
1279
		 * @since 3.0.0
1280
		 *
1281
		 * @param string $option Name of the network option.
1282
		 * @param mixed  $value  Value of the network option.
1283
		 */
1284
		do_action( 'add_site_option', $option, $value );
1285
1286
		return true;
1287
	}
1288
1289
	return false;
1290
}
1291
1292
/**
1293
 * Removes a network option by name.
1294
 *
1295
 * @since 4.4.0
1296
 *
1297
 * @see delete_option()
1298
 *
1299
 * @global wpdb   $wpdb
1300
 * @global object $current_site
1301
 *
1302
 * @param int    $network_id ID of the network. Can be null to default to the current network ID.
1303
 * @param string $option     Name of option to remove. Expected to not be SQL-escaped.
1304
 * @return bool True, if succeed. False, if failure.
1305
 */
1306
function delete_network_option( $network_id, $option ) {
1307
	global $wpdb, $current_site;
1308
1309
	if ( $network_id && ! is_numeric( $network_id ) ) {
1310
		return false;
1311
	}
1312
1313
	$network_id = (int) $network_id;
1314
1315
	// Fallback to the current network if a network ID is not specified.
1316
	if ( ! $network_id && is_multisite() ) {
1317
		$network_id = $current_site->id;
1318
	}
1319
1320
	/**
1321
	 * Fires immediately before a specific network option is deleted.
1322
	 *
1323
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
1324
	 *
1325
	 * @since 3.0.0
1326
	 * @since 4.4.0 The `$option` parameter was added
1327
	 *
1328
	 * @param string $option Option name.
1329
	 */
1330
	do_action( "pre_delete_site_option_{$option}", $option );
1331
1332
	if ( ! is_multisite() ) {
1333
		$result = delete_option( $option );
1334
	} else {
1335
		$row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );
1336
		if ( is_null( $row ) || ! $row->meta_id ) {
1337
			return false;
1338
		}
1339
		$cache_key = "$network_id:$option";
1340
		wp_cache_delete( $cache_key, 'site-options' );
1341
1342
		$result = $wpdb->delete( $wpdb->sitemeta, array( 'meta_key' => $option, 'site_id' => $network_id ) );
1343
	}
1344
1345
	if ( $result ) {
1346
1347
		/**
1348
		 * Fires after a specific network option has been deleted.
1349
		 *
1350
		 * The dynamic portion of the hook name, `$option`, refers to the option name.
1351
		 *
1352
		 * @since 2.9.0 As "delete_site_option_{$key}"
1353
		 * @since 3.0.0
1354
		 *
1355
		 * @param string $option Name of the network option.
1356
		 */
1357
		do_action( "delete_site_option_{$option}", $option );
1358
1359
		/**
1360
		 * Fires after a network option has been deleted.
1361
		 *
1362
		 * @since 3.0.0
1363
		 *
1364
		 * @param string $option Name of the network option.
1365
		 */
1366
		do_action( 'delete_site_option', $option );
1367
1368
		return true;
1369
	}
1370
1371
	return false;
1372
}
1373
1374
/**
1375
 * Update the value of a network option that was already added.
1376
 *
1377
 * @since 4.4.0
1378
 *
1379
 * @see update_option()
1380
 *
1381
 * @global wpdb   $wpdb
1382
 * @global object $current_site
1383
 *
1384
 * @param int      $network_id ID of the network. Can be null to default to the current network ID.
1385
 * @param string   $option     Name of option. Expected to not be SQL-escaped.
1386
 * @param mixed    $value      Option value. Expected to not be SQL-escaped.
1387
 * @return bool False if value was not updated and true if value was updated.
1388
 */
1389
function update_network_option( $network_id, $option, $value ) {
1390
	global $wpdb, $current_site;
1391
1392
	if ( $network_id && ! is_numeric( $network_id ) ) {
1393
		return false;
1394
	}
1395
1396
	$network_id = (int) $network_id;
1397
1398
	// Fallback to the current network if a network ID is not specified.
1399
	if ( ! $network_id && is_multisite() ) {
1400
		$network_id = $current_site->id;
1401
	}
1402
1403
	wp_protect_special_option( $option );
1404
1405
	$old_value = get_network_option( $network_id, $option, false );
1406
1407
	/**
1408
	 * Filters a specific network option before its value is updated.
1409
	 *
1410
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
1411
	 *
1412
	 * @since 2.9.0 As 'pre_update_site_option_' . $key
1413
	 * @since 3.0.0
1414
	 * @since 4.4.0 The `$option` parameter was added
1415
	 *
1416
	 * @param mixed  $value     New value of the network option.
1417
	 * @param mixed  $old_value Old value of the network option.
1418
	 * @param string $option    Option name.
1419
	 */
1420
	$value = apply_filters( "pre_update_site_option_{$option}", $value, $old_value, $option );
1421
1422
	if ( $value === $old_value ) {
1423
		return false;
1424
	}
1425
1426
	if ( false === $old_value ) {
1427
		return add_network_option( $network_id, $option, $value );
1428
	}
1429
1430
	$notoptions_key = "$network_id:notoptions";
1431
	$notoptions = wp_cache_get( $notoptions_key, 'site-options' );
1432 View Code Duplication
	if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
1433
		unset( $notoptions[ $option ] );
1434
		wp_cache_set( $notoptions_key, $notoptions, 'site-options' );
1435
	}
1436
1437
	if ( ! is_multisite() ) {
1438
		$result = update_option( $option, $value, 'no' );
1439
	} else {
1440
		$value = sanitize_option( $option, $value );
1441
1442
		$serialized_value = maybe_serialize( $value );
1443
		$result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $serialized_value ), array( 'site_id' => $network_id, 'meta_key' => $option ) );
1444
1445
		if ( $result ) {
1446
			$cache_key = "$network_id:$option";
1447
			wp_cache_set( $cache_key, $value, 'site-options' );
1448
		}
1449
	}
1450
1451
	if ( $result ) {
1452
1453
		/**
1454
		 * Fires after the value of a specific network option has been successfully updated.
1455
		 *
1456
		 * The dynamic portion of the hook name, `$option`, refers to the option name.
1457
		 *
1458
		 * @since 2.9.0 As "update_site_option_{$key}"
1459
		 * @since 3.0.0
1460
		 *
1461
		 * @param string $option    Name of the network option.
1462
		 * @param mixed  $value     Current value of the network option.
1463
		 * @param mixed  $old_value Old value of the network option.
1464
		 */
1465
		do_action( "update_site_option_{$option}", $option, $value, $old_value );
1466
1467
		/**
1468
		 * Fires after the value of a network option has been successfully updated.
1469
		 *
1470
		 * @since 3.0.0
1471
		 *
1472
		 * @param string $option    Name of the network option.
1473
		 * @param mixed  $value     Current value of the network option.
1474
		 * @param mixed  $old_value Old value of the network option.
1475
		 */
1476
		do_action( 'update_site_option', $option, $value, $old_value );
1477
1478
		return true;
1479
	}
1480
1481
	return false;
1482
}
1483
1484
/**
1485
 * Delete a site transient.
1486
 *
1487
 * @since 2.9.0
1488
 *
1489
 * @param string $transient Transient name. Expected to not be SQL-escaped.
1490
 * @return bool True if successful, false otherwise
1491
 */
1492 View Code Duplication
function delete_site_transient( $transient ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1493
1494
	/**
1495
	 * Fires immediately before a specific site transient is deleted.
1496
	 *
1497
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1498
	 *
1499
	 * @since 3.0.0
1500
	 *
1501
	 * @param string $transient Transient name.
1502
	 */
1503
	do_action( "delete_site_transient_{$transient}", $transient );
1504
1505
	if ( wp_using_ext_object_cache() ) {
1506
		$result = wp_cache_delete( $transient, 'site-transient' );
1507
	} else {
1508
		$option_timeout = '_site_transient_timeout_' . $transient;
1509
		$option = '_site_transient_' . $transient;
1510
		$result = delete_site_option( $option );
1511
		if ( $result )
1512
			delete_site_option( $option_timeout );
1513
	}
1514
	if ( $result ) {
1515
1516
		/**
1517
		 * Fires after a transient is deleted.
1518
		 *
1519
		 * @since 3.0.0
1520
		 *
1521
		 * @param string $transient Deleted transient name.
1522
		 */
1523
		do_action( 'deleted_site_transient', $transient );
1524
	}
1525
1526
	return $result;
1527
}
1528
1529
/**
1530
 * Get the value of a site transient.
1531
 *
1532
 * If the transient does not exist, does not have a value, or has expired,
1533
 * then the return value will be false.
1534
 *
1535
 * @since 2.9.0
1536
 *
1537
 * @see get_transient()
1538
 *
1539
 * @param string $transient Transient name. Expected to not be SQL-escaped.
1540
 * @return mixed Value of transient.
1541
 */
1542
function get_site_transient( $transient ) {
1543
1544
	/**
1545
	 * Filters the value of an existing site transient.
1546
	 *
1547
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1548
	 *
1549
	 * Passing a truthy value to the filter will effectively short-circuit retrieval,
1550
	 * returning the passed value instead.
1551
	 *
1552
	 * @since 2.9.0
1553
	 * @since 4.4.0 The `$transient` parameter was added.
1554
	 *
1555
	 * @param mixed  $pre_site_transient The default value to return if the site transient does not exist.
1556
	 *                                   Any value other than false will short-circuit the retrieval
1557
	 *                                   of the transient, and return the returned value.
1558
	 * @param string $transient          Transient name.
1559
	 */
1560
	$pre = apply_filters( "pre_site_transient_{$transient}", false, $transient );
1561
1562
	if ( false !== $pre )
1563
		return $pre;
1564
1565
	if ( wp_using_ext_object_cache() ) {
1566
		$value = wp_cache_get( $transient, 'site-transient' );
1567
	} else {
1568
		// Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
1569
		$no_timeout = array('update_core', 'update_plugins', 'update_themes');
1570
		$transient_option = '_site_transient_' . $transient;
1571 View Code Duplication
		if ( ! in_array( $transient, $no_timeout ) ) {
1572
			$transient_timeout = '_site_transient_timeout_' . $transient;
1573
			$timeout = get_site_option( $transient_timeout );
1574
			if ( false !== $timeout && $timeout < time() ) {
1575
				delete_site_option( $transient_option  );
1576
				delete_site_option( $transient_timeout );
1577
				$value = false;
1578
			}
1579
		}
1580
1581
		if ( ! isset( $value ) )
1582
			$value = get_site_option( $transient_option );
1583
	}
1584
1585
	/**
1586
	 * Filters the value of an existing site transient.
1587
	 *
1588
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1589
	 *
1590
	 * @since 2.9.0
1591
	 * @since 4.4.0 The `$transient` parameter was added.
1592
	 *
1593
	 * @param mixed  $value     Value of site transient.
1594
	 * @param string $transient Transient name.
1595
	 */
1596
	return apply_filters( "site_transient_{$transient}", $value, $transient );
1597
}
1598
1599
/**
1600
 * Set/update the value of a site transient.
1601
 *
1602
 * You do not need to serialize values, if the value needs to be serialize, then
1603
 * it will be serialized before it is set.
1604
 *
1605
 * @since 2.9.0
1606
 *
1607
 * @see set_transient()
1608
 *
1609
 * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
1610
 *                           40 characters or fewer in length.
1611
 * @param mixed  $value      Transient value. Expected to not be SQL-escaped.
1612
 * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
1613
 * @return bool False if value was not set and true if value was set.
1614
 */
1615
function set_site_transient( $transient, $value, $expiration = 0 ) {
1616
1617
	/**
1618
	 * Filters the value of a specific site transient before it is set.
1619
	 *
1620
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1621
	 *
1622
	 * @since 3.0.0
1623
	 * @since 4.4.0 The `$transient` parameter was added.
1624
	 *
1625
	 * @param mixed  $value     New value of site transient.
1626
	 * @param string $transient Transient name.
1627
	 */
1628
	$value = apply_filters( "pre_set_site_transient_{$transient}", $value, $transient );
1629
1630
	$expiration = (int) $expiration;
1631
1632
	/**
1633
	 * Filters the expiration for a site transient before its value is set.
1634
	 *
1635
	 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1636
	 *
1637
	 * @since 4.4.0
1638
	 *
1639
	 * @param int    $expiration Time until expiration in seconds. Use 0 for no expiration.
1640
	 * @param mixed  $value      New value of site transient.
1641
	 * @param string $transient  Transient name.
1642
	 */
1643
	$expiration = apply_filters( "expiration_of_site_transient_{$transient}", $expiration, $value, $transient );
1644
1645
	if ( wp_using_ext_object_cache() ) {
1646
		$result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
1647
	} else {
1648
		$transient_timeout = '_site_transient_timeout_' . $transient;
1649
		$option = '_site_transient_' . $transient;
1650
		if ( false === get_site_option( $option ) ) {
1651
			if ( $expiration )
1652
				add_site_option( $transient_timeout, time() + $expiration );
1653
			$result = add_site_option( $option, $value );
1654
		} else {
1655
			if ( $expiration )
1656
				update_site_option( $transient_timeout, time() + $expiration );
1657
			$result = update_site_option( $option, $value );
1658
		}
1659
	}
1660
	if ( $result ) {
1661
1662
		/**
1663
		 * Fires after the value for a specific site transient has been set.
1664
		 *
1665
		 * The dynamic portion of the hook name, `$transient`, refers to the transient name.
1666
		 *
1667
		 * @since 3.0.0
1668
		 * @since 4.4.0 The `$transient` parameter was added
1669
		 *
1670
		 * @param mixed  $value      Site transient value.
1671
		 * @param int    $expiration Time until expiration in seconds.
1672
		 * @param string $transient  Transient name.
1673
		 */
1674
		do_action( "set_site_transient_{$transient}", $value, $expiration, $transient );
1675
1676
		/**
1677
		 * Fires after the value for a site transient has been set.
1678
		 *
1679
		 * @since 3.0.0
1680
		 *
1681
		 * @param string $transient  The name of the site transient.
1682
		 * @param mixed  $value      Site transient value.
1683
		 * @param int    $expiration Time until expiration in seconds.
1684
		 */
1685
		do_action( 'setted_site_transient', $transient, $value, $expiration );
1686
	}
1687
	return $result;
1688
}
1689