Completed
Push — add/track-primary-user-errors ( 8bc3c7...21fa5f )
by
unknown
259:19 queued 251:29
created

Jetpack_Options::delete_grouped_option()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
/**
3
 * Legacy Jetpack_Options class.
4
 *
5
 * @package automattic/jetpack-options
6
 */
7
8
use Automattic\Jetpack\Constants;
9
10
/**
11
 * Class Jetpack_Options
12
 */
13
class Jetpack_Options {
14
15
	/**
16
	 * An array that maps a grouped option type to an option name.
17
	 *
18
	 * @var array
19
	 */
20
	private static $grouped_options = array(
21
		'compact' => 'jetpack_options',
22
		'private' => 'jetpack_private_options',
23
	);
24
25
	/**
26
	 * Returns an array of option names for a given type.
27
	 *
28
	 * @param string $type The type of option to return. Defaults to 'compact'.
29
	 *
30
	 * @return array
31
	 */
32
	public static function get_option_names( $type = 'compact' ) {
33
		switch ( $type ) {
34
			case 'non-compact':
35
			case 'non_compact':
36
				return array(
37
					'activated',
38
					'active_modules',
39
					'allowed_xsite_search_ids', // (array) Array of WP.com blog ids that are allowed to search the content of this site
40
					'available_modules',
41
					'do_activate',
42
					'edit_links_calypso_redirect', // (bool) Whether post/page edit links on front end should point to Calypso.
43
					'log',
44
					'slideshow_background_color',
45
					'widget_twitter',
46
					'wpcc_options',
47
					'relatedposts',
48
					'file_data',
49
					'autoupdate_plugins',          // (array)  An array of plugin ids ( eg. jetpack/jetpack ) that should be autoupdated
50
					'autoupdate_plugins_translations', // (array)  An array of plugin ids ( eg. jetpack/jetpack ) that should be autoupdated translation files.
51
					'autoupdate_themes',           // (array)  An array of theme ids ( eg. twentyfourteen ) that should be autoupdated
52
					'autoupdate_themes_translations', // (array)  An array of theme ids ( eg. twentyfourteen ) that should autoupdated translation files.
53
					'autoupdate_core',             // (bool)   Whether or not to autoupdate core
54
					'autoupdate_translations',     // (bool)   Whether or not to autoupdate all translations
55
					'json_api_full_management',    // (bool)   Allow full management (eg. Activate, Upgrade plugins) of the site via the JSON API.
56
					'sync_non_public_post_stati',  // (bool)   Allow synchronisation of posts and pages with non-public status.
57
					'site_icon_url',               // (string) url to the full site icon
58
					'site_icon_id',                // (int)    Attachment id of the site icon file
59
					'dismissed_manage_banner',     // (bool) Dismiss Jetpack manage banner allows the user to dismiss the banner permanently
60
					'unique_connection',           // (array)  A flag to determine a unique connection to wordpress.com two values "connected" and "disconnected" with values for how many times each has occured
61
					'protect_whitelist',           // (array) IP Address for the Protect module to ignore
62
					'sync_error_idc',              // (bool|array) false or array containing the site's home and siteurl at time of IDC error
63
					'sync_health_status',          // (bool|array) An array of data relating to Jetpack's sync health.
64
					'safe_mode_confirmed',         // (bool) True if someone confirms that this site was correctly put into safe mode automatically after an identity crisis is discovered.
65
					'migrate_for_idc',             // (bool) True if someone confirms that this site should migrate stats and subscribers from its previous URL
66
					'dismissed_connection_banner', // (bool) True if the connection banner has been dismissed
67
					'ab_connect_banner_green_bar', // (int) Version displayed of the A/B test for the green bar at the top of the connect banner.
68
					'onboarding',                  // (string) Auth token to be used in the onboarding connection flow
69
					'tos_agreed',                  // (bool)   Whether or not the TOS for connection has been agreed upon.
70
					'static_asset_cdn_files',      // (array) An nested array of files that we can swap out for cdn versions.
71
					'mapbox_api_key',              // (string) Mapbox API Key, for use with Map block.
72
					'mailchimp',                   // (string) Mailchimp keyring data, for mailchimp block.
73
					'xmlrpc_errors',               // (array) Keys are XML-RPC signature error codes. Values are truthy.
74
					'dismissed_wizard_banner',     // (int) True if the Wizard banner has been dismissed.
75
					'get_master_user_error',       // (string) error triggered when master user is missing, used to send data via heartbeat.
76
				);
77
78
			case 'private':
79
				return array(
80
					'blog_token',  // (string) The Client Secret/Blog Token of this site.
81
					'user_token',  // (string) The User Token of this site. (deprecated)
82
					'user_tokens',  // (array)  User Tokens for each user of this site who has connected to jetpack.wordpress.com.
83
				);
84
85
			case 'network':
86
				return array(
87
					'onboarding',                   // (string) Auth token to be used in the onboarding connection flow
88
					'file_data',                     // (array) List of absolute paths to all Jetpack modules
89
				);
90
		}
91
92
		return array(
93
			'id',                           // (int)    The Client ID/WP.com Blog ID of this site.
94
			'publicize_connections',        // (array)  An array of Publicize connections from WordPress.com.
95
			'master_user',                  // (int)    The local User ID of the user who connected this site to jetpack.wordpress.com.
96
			'version',                      // (string) Used during upgrade procedure to auto-activate new modules. version:time.
97
			'old_version',                  // (string) Used to determine which modules are the most recently added. previous_version:time.
98
			'fallback_no_verify_ssl_certs', // (int)    Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
99
			'time_diff',                    // (int)    Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack_Options::get_option( 'time_diff' )
100
			'public',                       // (int|bool) If we think this site is public or not (1, 0), false if we haven't yet tried to figure it out.
101
			'videopress',                   // (array)  VideoPress options array.
102
			'is_network_site',              // (int|bool) If we think this site is a network or a single blog (1, 0), false if we haven't yet tried to figue it out.
103
			'social_links',                 // (array)  The specified links for each social networking site.
104
			'identity_crisis_whitelist',    // (array)  An array of options, each having an array of the values whitelisted for it.
105
			'gplus_authors',                // (array)  The Google+ authorship information for connected users.
106
			'last_heartbeat',               // (int)    The timestamp of the last heartbeat that fired.
107
			'hide_jitm',                    // (array)  A list of just in time messages that we should not show because they have been dismissed by the user.
108
			'custom_css_4.7_migration',     // (bool)   Whether Custom CSS has scanned for and migrated any legacy CSS CPT entries to the new Core format.
109
			'image_widget_migration',       // (bool)   Whether any legacy Image Widgets have been converted to the new Core widget.
110
			'gallery_widget_migration',     // (bool)   Whether any legacy Gallery Widgets have been converted to the new Core widget.
111
			'sso_first_login',              // (bool)   Is this the first time the user logins via SSO.
112
			'dismissed_hints',              // (array)  Part of Plugin Search Hints. List of cards that have been dismissed.
113
			'first_admin_view',             // (bool)   Set to true the first time the user views the admin. Usually after the initial connection.
114
			'setup_wizard_questionnaire',   // (array)  List of user choices from the setup wizard.
115
			'setup_wizard_status',          // (string) Status of the setup wizard.
116
		);
117
	}
118
119
	/**
120
	 * Is the option name valid?
121
	 *
122
	 * @param string      $name  The name of the option.
123
	 * @param string|null $group The name of the group that the option is in. Default to null, which will search non_compact.
124
	 *
125
	 * @return bool Is the option name valid?
126
	 */
127
	public static function is_valid( $name, $group = null ) {
128
		if ( is_array( $name ) ) {
129
			$compact_names = array();
130
			foreach ( array_keys( self::$grouped_options ) as $_group ) {
131
				$compact_names = array_merge( $compact_names, self::get_option_names( $_group ) );
132
			}
133
134
			$result = array_diff( $name, self::get_option_names( 'non_compact' ), $compact_names );
135
136
			return empty( $result );
137
		}
138
139 View Code Duplication
		if ( is_null( $group ) || 'non_compact' === $group ) {
140
			if ( in_array( $name, self::get_option_names( $group ), true ) ) {
141
				return true;
142
			}
143
		}
144
145
		foreach ( array_keys( self::$grouped_options ) as $_group ) {
146 View Code Duplication
			if ( is_null( $group ) || $group === $_group ) {
147
				if ( in_array( $name, self::get_option_names( $_group ), true ) ) {
148
					return true;
149
				}
150
			}
151
		}
152
153
		return false;
154
	}
155
156
	/**
157
	 * Checks if an option must be saved for the whole network in WP Multisite
158
	 *
159
	 * @param string $option_name Option name. It must come _without_ `jetpack_%` prefix. The method will prefix the option name.
160
	 *
161
	 * @return bool
162
	 */
163
	public static function is_network_option( $option_name ) {
164
		if ( ! is_multisite() ) {
165
			return false;
166
		}
167
		return in_array( $option_name, self::get_option_names( 'network' ), true );
168
	}
169
170
	/**
171
	 * Filters the requested option.
172
	 * This is a wrapper around `get_option_from_database` so that we can filter the option.
173
	 *
174
	 * @param string $name Option name. It must come _without_ `jetpack_%` prefix. The method will prefix the option name.
175
	 * @param mixed  $default (optional).
176
	 *
177
	 * @return mixed
178
	 */
179
	public static function get_option( $name, $default = false ) {
180
		/**
181
		 * Filter Jetpack Options.
182
		 * Can be useful in environments when Jetpack is running with a different setup
183
		 *
184
		 * @since 8.8.0
185
		 *
186
		 * @param string $value The value from the database.
187
		 * @param string $name Option name, _without_ `jetpack_%` prefix.
188
		 * @return string $value, unless the filters modify it.
189
		 */
190
		return apply_filters( 'jetpack_options', self::get_option_from_database( $name, $default ), $name );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $name.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
191
	}
192
193
	/**
194
	 * Returns the requested option.  Looks in jetpack_options or jetpack_$name as appropriate.
195
	 *
196
	 * @param string $name Option name. It must come _without_ `jetpack_%` prefix. The method will prefix the option name.
197
	 * @param mixed  $default (optional).
198
	 *
199
	 * @return mixed
200
	 */
201
	private static function get_option_from_database( $name, $default = false ) {
202 View Code Duplication
		if ( self::is_valid( $name, 'non_compact' ) ) {
203
			if ( self::is_network_option( $name ) ) {
204
				return get_site_option( "jetpack_$name", $default );
205
			}
206
207
			return get_option( "jetpack_$name", $default );
208
		}
209
210
		foreach ( array_keys( self::$grouped_options ) as $group ) {
211
			if ( self::is_valid( $name, $group ) ) {
212
				return self::get_grouped_option( $group, $name, $default );
213
			}
214
		}
215
216
		trigger_error( sprintf( 'Invalid Jetpack option name: %s', esc_html( $name ) ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Don't wish to change legacy behavior.
217
218
		return $default;
219
	}
220
221
	/**
222
	 * Returns the requested option, and ensures it's autoloaded in the future.
223
	 * This does _not_ adjust the prefix in any way (does not prefix jetpack_%)
224
	 *
225
	 * @param string $name Option name.
226
	 * @param mixed  $default (optional).
227
	 *
228
	 * @return mixed
229
	 */
230
	public static function get_option_and_ensure_autoload( $name, $default ) {
231
		// In this function the name is not adjusted by prefixing jetpack_
232
		// so if it has already prefixed, we'll replace it and then
233
		// check if the option name is a network option or not.
234
		$jetpack_name      = preg_replace( '/^jetpack_/', '', $name, 1 );
235
		$is_network_option = self::is_network_option( $jetpack_name );
236
		$value             = $is_network_option ? get_site_option( $name ) : get_option( $name );
237
238
		if ( false === $value && false !== $default ) {
239
			if ( $is_network_option ) {
240
				add_site_option( $name, $default );
241
			} else {
242
				add_option( $name, $default );
243
			}
244
			$value = $default;
245
		}
246
247
		return $value;
248
	}
249
250
	/**
251
	 * Update grouped option
252
	 *
253
	 * @param string $group Options group.
254
	 * @param string $name Options name.
255
	 * @param mixed  $value Options value.
256
	 *
257
	 * @return bool Success or failure.
258
	 */
259
	private static function update_grouped_option( $group, $name, $value ) {
260
		$options = get_option( self::$grouped_options[ $group ] );
261
		if ( ! is_array( $options ) ) {
262
			$options = array();
263
		}
264
		$options[ $name ] = $value;
265
266
		return update_option( self::$grouped_options[ $group ], $options );
267
	}
268
269
	/**
270
	 * Updates the single given option.  Updates jetpack_options or jetpack_$name as appropriate.
271
	 *
272
	 * @param string $name Option name. It must come _without_ `jetpack_%` prefix. The method will prefix the option name.
273
	 * @param mixed  $value Option value.
274
	 * @param string $autoload If not compact option, allows specifying whether to autoload or not.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $autoload not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
275
	 *
276
	 * @return bool Was the option successfully updated?
277
	 */
278
	public static function update_option( $name, $value, $autoload = null ) {
279
		/**
280
		 * Fires before Jetpack updates a specific option.
281
		 *
282
		 * @since 3.0.0
283
		 *
284
		 * @param str $name The name of the option being updated.
285
		 * @param mixed $value The new value of the option.
286
		 */
287
		do_action( 'pre_update_jetpack_option_' . $name, $name, $value );
288 View Code Duplication
		if ( self::is_valid( $name, 'non_compact' ) ) {
289
			if ( self::is_network_option( $name ) ) {
290
				return update_site_option( "jetpack_$name", $value );
291
			}
292
293
			return update_option( "jetpack_$name", $value, $autoload );
294
295
		}
296
297
		foreach ( array_keys( self::$grouped_options ) as $group ) {
298
			if ( self::is_valid( $name, $group ) ) {
299
				return self::update_grouped_option( $group, $name, $value );
300
			}
301
		}
302
303
		trigger_error( sprintf( 'Invalid Jetpack option name: %s', esc_html( $name ) ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Don't want to change legacy behavior.
304
305
		return false;
306
	}
307
308
	/**
309
	 * Updates the multiple given options.  Updates jetpack_options and/or jetpack_$name as appropriate.
310
	 *
311
	 * @param array $array array( option name => option value, ... ).
312
	 */
313
	public static function update_options( $array ) {
314
		$names = array_keys( $array );
315
316
		foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ), self::get_option_names( 'private' ) ) as $unknown_name ) {
317
			trigger_error( sprintf( 'Invalid Jetpack option name: %s', esc_html( $unknown_name ) ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Don't change legacy behavior.
318
			unset( $array[ $unknown_name ] );
319
		}
320
321
		foreach ( $names as $name ) {
322
			self::update_option( $name, $array[ $name ] );
323
		}
324
	}
325
326
	/**
327
	 * Deletes the given option.  May be passed multiple option names as an array.
328
	 * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
329
	 *
330
	 * @param string|array $names Option names. They must come _without_ `jetpack_%` prefix. The method will prefix the option names.
331
	 *
332
	 * @return bool Was the option successfully deleted?
333
	 */
334
	public static function delete_option( $names ) {
335
		$result = true;
336
		$names  = (array) $names;
337
338
		if ( ! self::is_valid( $names ) ) {
0 ignored issues
show
Documentation introduced by
$names is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
339
			// phpcs:disable -- This line triggers a handful of errors; ignoring to avoid changing legacy behavior.
340
			trigger_error( sprintf( 'Invalid Jetpack option names: %s', print_r( $names, 1 ) ), E_USER_WARNING );
341
			// phpcs:enable
342
			return false;
343
		}
344
345
		foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
346
			if ( self::is_network_option( $name ) ) {
347
				$result = delete_site_option( "jetpack_$name" );
348
			} else {
349
				$result = delete_option( "jetpack_$name" );
350
			}
351
		}
352
353
		foreach ( array_keys( self::$grouped_options ) as $group ) {
354
			if ( ! self::delete_grouped_option( $group, $names ) ) {
355
				$result = false;
356
			}
357
		}
358
359
		return $result;
360
	}
361
362
	/**
363
	 * Get group option.
364
	 *
365
	 * @param string $group Option group name.
366
	 * @param string $name Option name.
367
	 * @param mixed  $default Default option value.
368
	 *
369
	 * @return mixed Option.
370
	 */
371
	private static function get_grouped_option( $group, $name, $default ) {
372
		$options = get_option( self::$grouped_options[ $group ] );
373
		if ( is_array( $options ) && isset( $options[ $name ] ) ) {
374
			return $options[ $name ];
375
		}
376
377
		return $default;
378
	}
379
380
	/**
381
	 * Delete grouped option.
382
	 *
383
	 * @param string $group Option group name.
384
	 * @param array  $names Option names.
385
	 *
386
	 * @return bool Success or failure.
387
	 */
388
	private static function delete_grouped_option( $group, $names ) {
389
		$options = get_option( self::$grouped_options[ $group ], array() );
390
391
		$to_delete = array_intersect( $names, self::get_option_names( $group ), array_keys( $options ) );
392
		if ( $to_delete ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $to_delete of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
393
			foreach ( $to_delete as $name ) {
394
				unset( $options[ $name ] );
395
			}
396
397
			return update_option( self::$grouped_options[ $group ], $options );
398
		}
399
400
		return true;
401
	}
402
403
	/*
404
	 * Raw option methods allow Jetpack to get / update / delete options via direct DB queries, including options
405
	 * that are not created by the Jetpack plugin. This is helpful only in rare cases when we need to bypass
406
	 * cache and filters.
407
	 */
408
409
	/**
410
	 * Deletes an option via $wpdb query.
411
	 *
412
	 * @param string $name Option name.
413
	 *
414
	 * @return bool Is the option deleted?
415
	 */
416
	public static function delete_raw_option( $name ) {
417
		if ( self::bypass_raw_option( $name ) ) {
418
			return delete_option( $name );
419
		}
420
		global $wpdb;
421
		$result = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name = %s", $name ) );
422
		return $result;
423
	}
424
425
	/**
426
	 * Updates an option via $wpdb query.
427
	 *
428
	 * @param string $name Option name.
429
	 * @param mixed  $value Option value.
430
	 * @param bool   $autoload Specifying whether to autoload or not.
431
	 *
432
	 * @return bool Is the option updated?
433
	 */
434
	public static function update_raw_option( $name, $value, $autoload = false ) {
435
		if ( self::bypass_raw_option( $name ) ) {
436
			return update_option( $name, $value, $autoload );
437
		}
438
		global $wpdb;
439
		$autoload_value = $autoload ? 'yes' : 'no';
440
441
		$old_value = $wpdb->get_var(
442
			$wpdb->prepare(
443
				"SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
444
				$name
445
			)
446
		);
447
		if ( $old_value === $value ) {
448
			return false;
449
		}
450
451
		$serialized_value = maybe_serialize( $value );
452
		// below we used "insert ignore" to at least suppress the resulting error.
453
		$updated_num = $wpdb->query(
454
			$wpdb->prepare(
455
				"UPDATE $wpdb->options SET option_value = %s WHERE option_name = %s",
456
				$serialized_value,
457
				$name
458
			)
459
		);
460
461
		// Try inserting the option if the value doesn't exits.
462
		if ( ! $updated_num ) {
463
			$updated_num = $wpdb->query(
464
				$wpdb->prepare(
465
					"INSERT IGNORE INTO $wpdb->options ( option_name, option_value, autoload ) VALUES ( %s, %s, %s )",
466
					$name,
467
					$serialized_value,
468
					$autoload_value
469
				)
470
			);
471
		}
472
		return (bool) $updated_num;
473
	}
474
475
	/**
476
	 * Gets an option via $wpdb query.
477
	 *
478
	 * @since 5.4.0
479
	 *
480
	 * @param string $name Option name.
481
	 * @param mixed  $default Default option value if option is not found.
482
	 *
483
	 * @return mixed Option value, or null if option is not found and default is not specified.
484
	 */
485
	public static function get_raw_option( $name, $default = null ) {
486
		if ( self::bypass_raw_option( $name ) ) {
487
			return get_option( $name, $default );
488
		}
489
490
		global $wpdb;
491
		$value = $wpdb->get_var(
492
			$wpdb->prepare(
493
				"SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
494
				$name
495
			)
496
		);
497
		$value = maybe_unserialize( $value );
498
499
		if ( null === $value && null !== $default ) {
500
			return $default;
501
		}
502
503
		return $value;
504
	}
505
506
	/**
507
	 * This function checks for a constant that, if present, will disable direct DB queries Jetpack uses to manage certain options and force Jetpack to always use Options API instead.
508
	 * Options can be selectively managed via a blocklist by filtering option names via the jetpack_disabled_raw_option filter.
509
	 *
510
	 * @param string $name Option name.
511
	 *
512
	 * @return bool
513
	 */
514
	public static function bypass_raw_option( $name ) {
515
516
		if ( Constants::get_constant( 'JETPACK_DISABLE_RAW_OPTIONS' ) ) {
517
			return true;
518
		}
519
		/**
520
		 * Allows to disable particular raw options.
521
		 *
522
		 * @since 5.5.0
523
		 *
524
		 * @param array $disabled_raw_options An array of option names that you can selectively blocklist from being managed via direct database queries.
525
		 */
526
		$disabled_raw_options = apply_filters( 'jetpack_disabled_raw_options', array() );
527
		return isset( $disabled_raw_options[ $name ] );
528
	}
529
530
	/**
531
	 * Gets all known options that are used by Jetpack and managed by Jetpack_Options.
532
	 *
533
	 * @since 5.4.0
534
	 *
535
	 * @param boolean $strip_unsafe_options If true, and by default, will strip out options necessary for the connection to WordPress.com.
536
	 * @return array An array of all options managed via the Jetpack_Options class.
537
	 */
538
	public static function get_all_jetpack_options( $strip_unsafe_options = true ) {
539
		$jetpack_options            = self::get_option_names();
540
		$jetpack_options_non_compat = self::get_option_names( 'non_compact' );
541
		$jetpack_options_private    = self::get_option_names( 'private' );
542
543
		$all_jp_options = array_merge( $jetpack_options, $jetpack_options_non_compat, $jetpack_options_private );
544
545
		if ( $strip_unsafe_options ) {
546
			// Flag some Jetpack options as unsafe.
547
			$unsafe_options = array(
548
				'id',                           // (int)    The Client ID/WP.com Blog ID of this site.
549
				'master_user',                  // (int)    The local User ID of the user who connected this site to jetpack.wordpress.com.
550
				'version',                      // (string) Used during upgrade procedure to auto-activate new modules. version:time
551
552
				// non_compact.
553
				'activated',
554
555
				// private.
556
				'register',
557
				'blog_token',                  // (string) The Client Secret/Blog Token of this site.
558
				'user_token',                  // (string) The User Token of this site. (deprecated)
559
				'user_tokens',
560
			);
561
562
			// Remove the unsafe Jetpack options.
563
			foreach ( $unsafe_options as $unsafe_option ) {
564
				$key = array_search( $unsafe_option, $all_jp_options, true );
565
				if ( false !== $key ) {
566
					unset( $all_jp_options[ $key ] );
567
				}
568
			}
569
		}
570
571
		return $all_jp_options;
572
	}
573
574
	/**
575
	 * Get all options that are not managed by the Jetpack_Options class that are used by Jetpack.
576
	 *
577
	 * @since 5.4.0
578
	 *
579
	 * @return array
580
	 */
581
	public static function get_all_wp_options() {
582
		// A manual build of the wp options.
583
		return array(
584
			'sharing-options',
585
			'disabled_likes',
586
			'disabled_reblogs',
587
			'jetpack_comments_likes_enabled',
588
			'stats_options',
589
			'stats_dashboard_widget',
590
			'safecss_preview_rev',
591
			'safecss_rev',
592
			'safecss_revision_migrated',
593
			'nova_menu_order',
594
			'jetpack_portfolio',
595
			'jetpack_portfolio_posts_per_page',
596
			'jetpack_testimonial',
597
			'jetpack_testimonial_posts_per_page',
598
			'sharedaddy_disable_resources',
599
			'sharing-options',
600
			'sharing-services',
601
			'site_icon_temp_data',
602
			'featured-content',
603
			'site_logo',
604
			'jetpack_dismissed_notices',
605
			'jetpack-twitter-cards-site-tag',
606
			'jetpack-sitemap-state',
607
			'jetpack_sitemap_post_types',
608
			'jetpack_sitemap_location',
609
			'jetpack_protect_key',
610
			'jetpack_protect_blocked_attempts',
611
			'jetpack_protect_activating',
612
			'jetpack_connection_banner_ab',
613
			'jetpack_active_plan',
614
			'jetpack_activation_source',
615
			'jetpack_sso_match_by_email',
616
			'jetpack_sso_require_two_step',
617
			'jetpack_sso_remove_login_form',
618
			'jetpack_last_connect_url_check',
619
			'jpo_business_address',
620
			'jpo_site_type',
621
			'jpo_homepage_format',
622
			'jpo_contact_page',
623
			'jetpack_excluded_extensions',
624
		);
625
	}
626
627
	/**
628
	 * Gets all options that can be safely reset by CLI.
629
	 *
630
	 * @since 5.4.0
631
	 *
632
	 * @return array array Associative array containing jp_options which are managed by the Jetpack_Options class and wp_options which are not.
633
	 */
634
	public static function get_options_for_reset() {
635
		$all_jp_options = self::get_all_jetpack_options();
636
637
		$wp_options = self::get_all_wp_options();
638
639
		$options = array(
640
			'jp_options' => $all_jp_options,
641
			'wp_options' => $wp_options,
642
		);
643
644
		return $options;
645
	}
646
647
	/**
648
	 * Delete all known options
649
	 *
650
	 * @since 5.4.0
651
	 *
652
	 * @return void
653
	 */
654
	public static function delete_all_known_options() {
655
		// Delete all compact options.
656
		foreach ( (array) self::$grouped_options as $option_name ) {
657
			delete_option( $option_name );
658
		}
659
660
		// Delete all non-compact Jetpack options.
661
		foreach ( (array) self::get_option_names( 'non-compact' ) as $option_name ) {
662
			self::delete_option( $option_name );
663
		}
664
665
		// Delete all options that can be reset via CLI, that aren't Jetpack options.
666
		foreach ( (array) self::get_all_wp_options() as $option_name ) {
667
			delete_option( $option_name );
668
		}
669
	}
670
}
671