Completed
Push — try/remote-provision ( 47bd35 )
by
unknown
09:29
created

Jetpack_CLI::partner_provision()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 23
Code Lines 14

Duplication

Lines 3
Ratio 13.04 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 12
nop 2
dl 3
loc 23
rs 8.5906
c 0
b 0
f 0
1
<?php
2
3
WP_CLI::add_command( 'jetpack', 'Jetpack_CLI' );
4
5
/**
6
 * Control your local Jetpack installation.
7
 */
8
class Jetpack_CLI extends WP_CLI_Command {
9
10
	// Aesthetics
11
	public $green_open  = "\033[32m";
12
	public $red_open    = "\033[31m";
13
	public $yellow_open = "\033[33m";
14
	public $color_close = "\033[0m";
15
16
	/**
17
	 * Get Jetpack Details
18
	 *
19
	 * ## OPTIONS
20
	 *
21
	 * empty: Leave it empty for basic stats
22
	 *
23
	 * full: View full stats.  It's the data from the heartbeat
24
	 *
25
	 * ## EXAMPLES
26
	 *
27
	 * wp jetpack status
28
	 * wp jetpack status full
29
	 *
30
	 */
31
	public function status( $args, $assoc_args ) {
32
33
		WP_CLI::line( sprintf( __( 'Checking status for %s', 'jetpack' ), esc_url( get_site_url() ) ) );
34
35
		if ( ! Jetpack::is_active() ) {
36
			WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
37
		}
38
39
		if ( isset( $args[0] ) && 'full' !== $args[0] ) {
40
			/* translators: %s is a command like "prompt" */
41
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $args[0] ) );
42
		}
43
44
		$master_user_email = Jetpack::get_master_user_email();
45
46
		/*
47
		 * Are they asking for all data?
48
		 *
49
		 * Loop through heartbeat data and organize by priority.
50
		 */
51
		$all_data = ( isset( $args[0] ) && 'full' == $args[0] ) ? 'full' : false;
52
		if ( $all_data ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $all_data of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
53
			WP_CLI::success( __( 'Jetpack is currently connected to WordPress.com', 'jetpack' ) );
54
			WP_CLI::line( sprintf( __( "The Jetpack Version is %s", 'jetpack' ), JETPACK__VERSION ) );
55
			WP_CLI::line( sprintf( __( "The WordPress.com blog_id is %d", 'jetpack' ), Jetpack_Options::get_option( 'id' ) ) );
56
			WP_CLI::line( sprintf( __( 'The WordPress.com account for the primary connection is %s', 'jetpack' ), $master_user_email ) );
57
58
			// Heartbeat data
59
			WP_CLI::line( "\n" . __( 'Additional data: ', 'jetpack' ) );
60
61
			// Get the filtered heartbeat data.
62
			// Filtered so we can color/list by severity
63
			$stats = Jetpack::jetpack_check_heartbeat_data();
64
65
			// Display red flags first
66
			foreach ( $stats['bad'] as $stat => $value ) {
67
				printf( "$this->red_open%-'.16s %s $this->color_close\n", $stat, $value );
68
			}
69
70
			// Display caution warnings next
71
			foreach ( $stats['caution'] as $stat => $value ) {
72
				printf( "$this->yellow_open%-'.16s %s $this->color_close\n", $stat, $value );
73
			}
74
75
			// The rest of the results are good!
76
			foreach ( $stats['good'] as $stat => $value ) {
77
78
				// Modules should get special spacing for aestetics
79
				if ( strpos( $stat, 'odule-' ) ) {
80
					printf( "%-'.30s %s\n", $stat, $value );
81
					usleep( 4000 ); // For dramatic effect lolz
82
					continue;
83
				}
84
				printf( "%-'.16s %s\n", $stat, $value );
85
				usleep( 4000 ); // For dramatic effect lolz
86
			}
87
		} else {
88
			// Just the basics
89
			WP_CLI::success( __( 'Jetpack is currently connected to WordPress.com', 'jetpack' ) );
90
			WP_CLI::line( sprintf( __( 'The Jetpack Version is %s', 'jetpack' ), JETPACK__VERSION ) );
91
			WP_CLI::line( sprintf( __( 'The WordPress.com blog_id is %d', 'jetpack' ), Jetpack_Options::get_option( 'id' ) ) );
92
			WP_CLI::line( sprintf( __( 'The WordPress.com account for the primary connection is %s', 'jetpack' ), $master_user_email ) );
93
			WP_CLI::line( "\n" . _x( "View full status with 'wp jetpack status full'", '"wp jetpack status full" is a command - do not translate', 'jetpack' ) );
94
		}
95
	}
96
97
	/**
98
	 * Tests the active connection
99
	 *
100
	 * Does a two-way test to verify that the local site can communicate with remote Jetpack/WP.com servers and that Jetpack/WP.com servers can talk to the local site.
101
	 *
102
	 * ## EXAMPLES
103
	 *
104
	 * wp jetpack test-connection
105
	 *
106
	 * @subcommand test-connection
107
	 */
108
	public function test_connection( $args, $assoc_args ) {
109
110
		WP_CLI::line( sprintf( __( 'Testing connection for %s', 'jetpack' ), esc_url( get_site_url() ) ) );
111
112
		if ( ! Jetpack::is_active() ) {
113
			WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
114
		}
115
116
		$response = Jetpack_Client::wpcom_json_api_request_as_blog(
117
			sprintf( '/jetpack-blogs/%d/test-connection', Jetpack_Options::get_option( 'id' ) ),
118
			Jetpack_Client::WPCOM_JSON_API_VERSION
119
		);
120
121
		if ( is_wp_error( $response ) ) {
122
			/* translators: %1$s is the error code, %2$s is the error message */
123
			WP_CLI::error( sprintf( __( 'Failed to test connection (#%1$s: %2$s)', 'jetpack' ), $response->get_error_code(), $response->get_error_message() ) );
124
		}
125
126
		$body = wp_remote_retrieve_body( $response );
127
		if ( ! $body ) {
128
			WP_CLI::error( __( 'Failed to test connection (empty response body)', 'jetpack' ) );
129
		}
130
131
		$result = json_decode( $body );
132
		$is_connected = (bool) $result->connected;
133
		$message = $result->message;
134
135
		if ( $is_connected ) {
136
			WP_CLI::success( $message );
137
		} else {
138
			WP_CLI::error( $message );
139
		}
140
	}
141
142
	/**
143
	 * Disconnect Jetpack Blogs or Users
144
	 *
145
	 * ## OPTIONS
146
	 *
147
	 * blog: Disconnect the entire blog.
148
	 *
149
	 * user <user_identifier>: Disconnect a specific user from WordPress.com.
150
	 *
151
	 * Please note, the primary account that the blog is connected
152
	 * to WordPress.com with cannot be disconnected without
153
	 * disconnecting the entire blog.
154
	 *
155
	 * ## EXAMPLES
156
	 *
157
	 * wp jetpack disconnect blog
158
	 * wp jetpack disconnect user 13
159
	 * wp jetpack disconnect user username
160
	 * wp jetpack disconnect user [email protected]
161
	 *
162
	 * @synopsis <blog|user> [<user_identifier>]
163
	 */
164
	public function disconnect( $args, $assoc_args ) {
165
		if ( ! Jetpack::is_active() ) {
166
			WP_CLI::error( __( 'You cannot disconnect, without having first connected.', 'jetpack' ) );
167
		}
168
169
		$action = isset( $args[0] ) ? $args[0] : 'prompt';
170
		if ( ! in_array( $action, array( 'blog', 'user', 'prompt' ) ) ) {
171
			/* translators: %s is a command like "prompt" */
172
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
173
		}
174
175
		if ( in_array( $action, array( 'user' ) ) ) {
176
			if ( isset( $args[1] ) ) {
177
				$user_id = $args[1];
178
				if ( ctype_digit( $user_id ) ) {
179
					$field = 'id';
180
					$user_id = (int) $user_id;
181
				} elseif ( is_email( $user_id ) ) {
182
					$field = 'email';
183
					$user_id = sanitize_user( $user_id, true );
184
				} else {
185
					$field = 'login';
186
					$user_id = sanitize_user( $user_id, true );
187
				}
188
				if ( ! $user = get_user_by( $field, $user_id ) ) {
189
					WP_CLI::error( __( 'Please specify a valid user.', 'jetpack' ) );
190
				}
191
			} else {
192
				WP_CLI::error( __( 'Please specify a user by either ID, username, or email.', 'jetpack' ) );
193
			}
194
		}
195
196
		switch ( $action ) {
197
			case 'blog':
198
				Jetpack::log( 'disconnect' );
199
				Jetpack::disconnect();
200
				WP_CLI::success( sprintf(
201
					__( 'Jetpack has been successfully disconnected for %s.', 'jetpack' ),
202
					esc_url( get_site_url() )
203
				) );
204
				break;
205
			case 'user':
206
				if ( Jetpack::unlink_user( $user->ID ) ) {
207
					Jetpack::log( 'unlink', $user->ID );
0 ignored issues
show
Bug introduced by
The variable $user 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...
208
					WP_CLI::success( __( 'User has been successfully disconnected.', 'jetpack' ) );
209
				} else {
210
					/* translators: %s is a username */
211
					WP_CLI::error( sprintf( __( "User %s could not be disconnected. Are you sure they're connected currently?", 'jetpack' ), "{$user->login} <{$user->email}>" ) );
212
				}
213
				break;
214
			case 'prompt':
215
				WP_CLI::error( __( 'Please specify if you would like to disconnect a blog or user.', 'jetpack' ) );
216
				break;
217
		}
218
	}
219
220
	/**
221
	 * Reset Jetpack options and settings to default
222
	 *
223
	 * ## OPTIONS
224
	 *
225
	 * modules: Resets modules to default state ( get_default_modules() )
226
	 *
227
	 * options: Resets all Jetpack options except:
228
	 *  - All private options (Blog token, user token, etc...)
229
	 *  - id (The Client ID/WP.com Blog ID of this site)
230
	 *  - master_user
231
	 *  - version
232
	 *  - activated
233
	 *
234
	 * ## EXAMPLES
235
	 *
236
	 * wp jetpack reset options
237
	 * wp jetpack reset modules
238
	 *
239
	 * @synopsis <modules|options>
240
	 */
241
	public function reset( $args, $assoc_args ) {
242
		$action = isset( $args[0] ) ? $args[0] : 'prompt';
243 View Code Duplication
		if ( ! in_array( $action, array( 'options', 'modules' ) ) ) {
244
			/* translators: %s is a command like "prompt" */
245
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
246
		}
247
248
		// Are you sure?
249
		jetpack_cli_are_you_sure();
250
251
		switch ( $action ) {
252
			case 'options':
253
				$options_to_reset = Jetpack_Options::get_options_for_reset();
254
255
				// Reset the Jetpack options
256
				WP_CLI::line( sprintf(
257
					__( "Resetting Jetpack Options for %s...\n", "jetpack" ),
258
					esc_url( get_site_url() )
259
				) );
260
				sleep(1); // Take a breath
261
				foreach ( $options_to_reset['jp_options'] as $option_to_reset ) {
262
					Jetpack_Options::delete_option( $option_to_reset );
263
					usleep( 100000 );
264
					/* translators: This is the result of an action. The option named %s was reset */
265
					WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
266
				}
267
268
				// Reset the WP options
269
				WP_CLI::line( __( "Resetting the jetpack options stored in wp_options...\n", "jetpack" ) );
270
				usleep( 500000 ); // Take a breath
271
				foreach ( $options_to_reset['wp_options'] as $option_to_reset ) {
272
					delete_option( $option_to_reset );
273
					usleep( 100000 );
274
					/* translators: This is the result of an action. The option named %s was reset */
275
					WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
276
				}
277
278
				// Reset to default modules
279
				WP_CLI::line( __( "Resetting default modules...\n", "jetpack" ) );
280
				usleep( 500000 ); // Take a breath
281
				$default_modules = Jetpack::get_default_modules();
282
				Jetpack::update_active_modules( $default_modules );
283
				WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
284
285
				// Jumpstart option is special
286
				Jetpack_Options::update_option( 'jumpstart', 'new_connection' );
287
				WP_CLI::success( __( 'jumpstart option reset', 'jetpack' ) );
288
				break;
289 View Code Duplication
			case 'modules':
290
				$default_modules = Jetpack::get_default_modules();
291
				Jetpack::update_active_modules( $default_modules );
292
				WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
293
				break;
294
			case 'prompt':
295
				WP_CLI::error( __( 'Please specify if you would like to reset your options, or modules', 'jetpack' ) );
296
				break;
297
		}
298
	}
299
300
	/**
301
	 * Manage Jetpack Modules
302
	 *
303
	 * ## OPTIONS
304
	 *
305
	 * list          : View all available modules, and their status.
306
	 * activate all  : Activate all modules
307
	 * deactivate all: Deactivate all modules
308
	 *
309
	 * activate   <module_slug> : Activate a module.
310
	 * deactivate <module_slug> : Deactivate a module.
311
	 * toggle     <module_slug> : Toggle a module on or off.
312
	 *
313
	 * ## EXAMPLES
314
	 *
315
	 * wp jetpack module list
316
	 * wp jetpack module activate stats
317
	 * wp jetpack module deactivate stats
318
	 * wp jetpack module toggle stats
319
	 *
320
	 * wp jetpack module activate all
321
	 * wp jetpack module deactivate all
322
	 *
323
	 * @synopsis <list|activate|deactivate|toggle> [<module_name>]
324
	 */
325
	public function module( $args, $assoc_args ) {
326
		$action = isset( $args[0] ) ? $args[0] : 'list';
327
		if ( ! in_array( $action, array( 'list', 'activate', 'deactivate', 'toggle' ) ) ) {
328
			/* translators: %s is a command like "prompt" */
329
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
330
		}
331
		if ( in_array( $action, array( 'activate', 'deactivate', 'toggle' ) ) ) {
332
			if ( isset( $args[1] ) ) {
333
				$module_slug = $args[1];
334
				if ( 'all' !== $module_slug && ! Jetpack::is_module( $module_slug ) ) {
335
					WP_CLI::error( sprintf( __( '%s is not a valid module.', 'jetpack' ), $module_slug ) );
336
				}
337
				if ( 'toggle' == $action ) {
338
					$action = Jetpack::is_module_active( $module_slug ) ? 'deactivate' : 'activate';
339
				}
340
				// Bulk actions
341
				if ( 'all' == $args[1] ) {
342
					$action = ( 'deactivate' == $action ) ? 'deactivate_all' : 'activate_all';
343
				}
344
			} else {
345
				WP_CLI::line( __( 'Please specify a valid module.', 'jetpack' ) );
346
				$action = 'list';
347
			}
348
		}
349
		switch ( $action ) {
350
			case 'list':
351
				WP_CLI::line( __( 'Available Modules:', 'jetpack' ) );
352
				$modules = Jetpack::get_available_modules();
353
				sort( $modules );
354
				foreach( $modules as $module_slug ) {
355
					if ( 'vaultpress' == $module_slug ) {
356
						continue;
357
					}
358
					$active = Jetpack::is_module_active( $module_slug ) ? __( 'Active', 'jetpack' ) : __( 'Inactive', 'jetpack' );
359
					WP_CLI::line( "\t" . str_pad( $module_slug, 24 ) . $active );
360
				}
361
				break;
362 View Code Duplication
			case 'activate':
363
				$module = Jetpack::get_module( $module_slug );
0 ignored issues
show
Bug introduced by
The variable $module_slug 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...
364
				Jetpack::log( 'activate', $module_slug );
365
				Jetpack::activate_module( $module_slug, false, false );
366
				WP_CLI::success( sprintf( __( '%s has been activated.', 'jetpack' ), $module['name'] ) );
367
				break;
368 View Code Duplication
			case 'activate_all':
369
				$modules = Jetpack::get_available_modules();
370
				Jetpack::update_active_modules( $modules );
371
				WP_CLI::success( __( 'All modules activated!', 'jetpack' ) );
372
				break;
373 View Code Duplication
			case 'deactivate':
374
				$module = Jetpack::get_module( $module_slug );
375
				Jetpack::log( 'deactivate', $module_slug );
376
				Jetpack::deactivate_module( $module_slug );
377
				WP_CLI::success( sprintf( __( '%s has been deactivated.', 'jetpack' ), $module['name'] ) );
378
				break;
379
			case 'deactivate_all':
380
				Jetpack::delete_active_modules();
381
				WP_CLI::success( __( 'All modules deactivated!', 'jetpack' ) );
382
				break;
383
			case 'toggle':
384
				// Will never happen, should have been handled above and changed to activate or deactivate.
385
				break;
386
		}
387
	}
388
389
	/**
390
	 * Manage Protect Settings
391
	 *
392
	 * ## OPTIONS
393
	 *
394
	 * whitelist: Whitelist an IP address.  You can also read or clear the whitelist.
395
	 *
396
	 *
397
	 * ## EXAMPLES
398
	 *
399
	 * wp jetpack protect whitelist <ip address>
400
	 * wp jetpack protect whitelist list
401
	 * wp jetpack protect whitelist clear
402
	 *
403
	 * @synopsis <whitelist> [<ip|ip_low-ip_high|list|clear>]
404
	 */
405
	public function protect( $args, $assoc_args ) {
406
		$action = isset( $args[0] ) ? $args[0] : 'prompt';
407
		if ( ! in_array( $action, array( 'whitelist' ) ) ) {
408
			/* translators: %s is a command like "prompt" */
409
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
410
		}
411
		// Check if module is active
412
		if ( ! Jetpack::is_module_active( __FUNCTION__ ) ) {
413
			WP_CLI::error( sprintf( _x( '%s is not active. You can activate it with "wp jetpack module activate %s"', '"wp jetpack module activate" is a command - do not translate', 'jetpack' ), __FUNCTION__, __FUNCTION__ ) );
414
		}
415
		if ( in_array( $action, array( 'whitelist' ) ) ) {
416
			if ( isset( $args[1] ) ) {
417
				$action = 'whitelist';
418
			} else {
419
				$action = 'prompt';
420
			}
421
		}
422
		switch ( $action ) {
423
			case 'whitelist':
424
				$whitelist         = array();
425
				$new_ip            = $args[1];
426
				$current_whitelist = get_site_option( 'jetpack_protect_whitelist', array() );
427
428
				// Build array of IPs that are already whitelisted.
429
				// Re-build manually instead of using jetpack_protect_format_whitelist() so we can easily get
430
				// low & high range params for jetpack_protect_ip_address_is_in_range();
431
				foreach( $current_whitelist as $whitelisted ) {
432
433
					// IP ranges
434
					if ( $whitelisted->range ) {
435
436
						// Is it already whitelisted?
437
						if ( jetpack_protect_ip_address_is_in_range( $new_ip, $whitelisted->range_low, $whitelisted->range_high ) ) {
438
							/* translators: %s is an IP address */
439
							WP_CLI::error( sprintf( __( '%s has already been whitelisted', 'jetpack' ), $new_ip ) );
440
							break;
441
						}
442
						$whitelist[] = $whitelisted->range_low . " - " . $whitelisted->range_high;
443
444
					} else { // Individual IPs
445
446
						// Check if the IP is already whitelisted (single IP only)
447
						if ( $new_ip == $whitelisted->ip_address ) {
448
							/* translators: %s is an IP address */
449
							WP_CLI::error( sprintf( __( '%s has already been whitelisted', 'jetpack' ), $new_ip ) );
450
							break;
451
						}
452
						$whitelist[] = $whitelisted->ip_address;
453
454
					}
455
				}
456
457
				/*
458
				 * List the whitelist
459
				 * Done here because it's easier to read the $whitelist array after it's been rebuilt
460
				 */
461
				if ( isset( $args[1] ) && 'list' == $args[1] ) {
462
					if ( ! empty( $whitelist ) ) {
463
						WP_CLI::success( __( 'Here are your whitelisted IPs:', 'jetpack' ) );
464
						foreach ( $whitelist as $ip ) {
465
							WP_CLI::line( "\t" . str_pad( $ip, 24 ) ) ;
466
						}
467
					} else {
468
						WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
469
					}
470
					break;
471
				}
472
473
				/*
474
				 * Clear the whitelist
475
				 */
476
				if ( isset( $args[1] ) && 'clear' == $args[1] ) {
477 View Code Duplication
					if ( ! empty( $whitelist ) ) {
478
						$whitelist = array();
479
						jetpack_protect_save_whitelist( $whitelist );
480
						WP_CLI::success( __( 'Cleared all whitelisted IPs', 'jetpack' ) );
481
					} else {
482
						WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
483
					}
484
					break;
485
				}
486
487
				// Append new IP to whitelist array
488
				array_push( $whitelist, $new_ip );
489
490
				// Save whitelist if there are no errors
491
				$result = jetpack_protect_save_whitelist( $whitelist );
492
				if ( is_wp_error( $result ) ) {
493
					WP_CLI::error( __( $result, 'jetpack' ) );
494
				}
495
496
				/* translators: %s is an IP address */
497
				WP_CLI::success( sprintf( __( '%s has been whitelisted.', 'jetpack' ), $new_ip ) );
498
				break;
499
			case 'prompt':
500
				WP_CLI::error(
501
					__( 'No command found.', 'jetpack' ) . "\n" .
502
					__( 'Please enter the IP address you want to whitelist.', 'jetpack' ) . "\n" .
503
					_x( 'You can save a range of IPs {low_range}-{high_range}. No spaces allowed.  (example: 1.1.1.1-2.2.2.2)', 'Instructions on how to whitelist IP ranges - low_range/high_range should be translated.', 'jetpack' ) . "\n" .
504
					_x( "You can also 'list' or 'clear' the whitelist.", "'list' and 'clear' are commands and should not be translated", 'jetpack' ) . "\n"
505
				);
506
				break;
507
		}
508
	}
509
510
	/**
511
	 * Manage Jetpack Options
512
	 *
513
	 * ## OPTIONS
514
	 *
515
	 * list   : List all jetpack options and their values
516
	 * delete : Delete an option
517
	 *          - can only delete options that are white listed.
518
	 * update : update an option
519
	 *          - can only update option strings
520
	 * get    : get the value of an option
521
	 *
522
	 * ## EXAMPLES
523
	 *
524
	 * wp jetpack options list
525
	 * wp jetpack options get    <option_name>
526
	 * wp jetpack options delete <option_name>
527
	 * wp jetpack options update <option_name> [<option_value>]
528
	 *
529
	 * @synopsis <list|get|delete|update> [<option_name>] [<option_value>]
530
	 */
531
	public function options( $args, $assoc_args ) {
532
		$action = isset( $args[0] ) ? $args[0] : 'list';
533
		$safe_to_modify = Jetpack_Options::get_options_for_reset();
534
535
		// Jumpstart is special
536
		array_push( $safe_to_modify, 'jumpstart' );
537
538
		// Is the option flagged as unsafe?
539
		$flagged = ! in_array( $args[1], $safe_to_modify );
540
541 View Code Duplication
		if ( ! in_array( $action, array( 'list', 'get', 'delete', 'update' ) ) ) {
542
			/* translators: %s is a command like "prompt" */
543
			WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
544
		}
545
546
		if ( isset( $args[0] ) ) {
547
			if ( 'get' == $args[0] && isset( $args[1] ) ) {
548
				$action = 'get';
549
			} else if ( 'delete' == $args[0] && isset( $args[1] ) ) {
550
				$action = 'delete';
551 View Code Duplication
			} else if ( 'update' == $args[0] && isset( $args[1] ) ) {
552
				$action = 'update';
553
			} else {
554
				$action = 'list';
555
			}
556
		}
557
558
		// Bail if the option isn't found
559
		$option = isset( $args[1] ) ? Jetpack_Options::get_option( $args[1] ) : false;
560
		if ( isset( $args[1] ) && ! $option && 'update' !== $args[0] ) {
561
			WP_CLI::error( __( 'Option not found or is empty.  Use "list" to list option names', 'jetpack' ) );
562
		}
563
564
		// Let's print_r the option if it's an array
565
		// Used in the 'get' and 'list' actions
566
		$option = is_array( $option ) ? print_r( $option ) : $option;
567
568
		switch ( $action ) {
569
			case 'get':
570
				WP_CLI::success( "\t" . $option );
571
				break;
572
			case 'delete':
573
				jetpack_cli_are_you_sure( $flagged );
574
575
				Jetpack_Options::delete_option( $args[1] );
576
				WP_CLI::success( sprintf( __( 'Deleted option: %s', 'jetpack' ), $args[1] ) );
577
				break;
578
			case 'update':
579
				jetpack_cli_are_you_sure( $flagged );
580
581
				// Updating arrays would get pretty tricky...
582
				$value = Jetpack_Options::get_option( $args[1] );
583
				if ( $value && is_array( $value ) ) {
584
					WP_CLI::error( __( 'Sorry, no updating arrays at this time', 'jetpack' ) );
585
				}
586
587
				Jetpack_Options::update_option( $args[1], $args[2] );
588
				WP_CLI::success( sprintf( _x( 'Updated option: %s to "%s"', 'Updating an option from "this" to "that".', 'jetpack' ), $args[1], $args[2] ) );
589
				break;
590
			case 'list':
591
				$options_compact     = Jetpack_Options::get_option_names();
592
				$options_non_compact = Jetpack_Options::get_option_names( 'non_compact' );
593
				$options_private     = Jetpack_Options::get_option_names( 'private' );
594
				$options             = array_merge( $options_compact, $options_non_compact, $options_private );
595
596
				// Table headers
597
				WP_CLI::line( "\t" . str_pad( __( 'Option', 'jetpack' ), 30 ) . __( 'Value', 'jetpack' ) );
598
599
				// List out the options and their values
600
				// Tell them if the value is empty or not
601
				// Tell them if it's an array
602
				foreach ( $options as $option ) {
603
					$value = Jetpack_Options::get_option( $option );
604
					if ( ! $value ) {
605
						WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Empty' );
606
						continue;
607
					}
608
609
					if ( ! is_array( $value ) ) {
610
						WP_CLI::line( "\t" . str_pad( $option, 30 ) . $value );
611
					} else if ( is_array( $value ) ) {
612
						WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Array - Use "get <option>" to read option array.' );
613
					}
614
				}
615
				$option_text = '{' . _x( 'option', 'a variable command that a user can write, provided in the printed instructions', 'jetpack' ) . '}';
616
				$value_text  = '{' . _x( 'value', 'the value that they want to update the option to', 'jetpack' ) . '}';
617
618
				WP_CLI::success(
619
					_x( "Above are your options. You may 'get', 'delete', and 'update' them.", "'get', 'delete', and 'update' are commands - do not translate.", 'jetpack' ) . "\n" .
620
					str_pad( 'wp jetpack options get', 26 )    . $option_text . "\n" .
621
					str_pad( 'wp jetpack options delete', 26 ) . $option_text . "\n" .
622
					str_pad( 'wp jetpack options update', 26 ) . "$option_text $value_text" . "\n" .
623
					_x( "Type 'wp jetpack options' for more info.", "'wp jetpack options' is a command - do not translate.", 'jetpack' ) . "\n"
624
				);
625
				break;
626
		}
627
	}
628
629
	/**
630
	 * Get the status of or start a new Jetpack sync.
631
	 *
632
	 * ## OPTIONS
633
	 *
634
	 * status : Print the current sync status
635
	 * start  : Start a full sync from this site to WordPress.com
636
	 *
637
	 * ## EXAMPLES
638
	 *
639
	 * wp jetpack sync status
640
	 * wp jetpack sync start --modules=functions --sync_wait_time=5
641
	 *
642
	 * @synopsis <status|start> [--<field>=<value>]
643
	 */
644
	public function sync( $args, $assoc_args ) {
645
		if ( ! Jetpack_Sync_Actions::sync_allowed() ) {
646
			WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site.', 'jetpack' ) );
647
		}
648
649
		$action = isset( $args[0] ) ? $args[0] : 'status';
650
651
		switch ( $action ) {
652
			case 'status':
653
				$status = Jetpack_Sync_Actions::get_sync_status();
654
				$collection = array();
655
				foreach ( $status as $key => $item ) {
656
					$collection[]  = array(
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 2 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
657
						'option' => $key,
658
						'value' => is_scalar( $item ) ? $item : json_encode( $item )
659
					);
660
				}
661
662
				WP_CLI\Utils\format_items( 'table', $collection, array( 'option', 'value' ) );
663
				break;
664
			case 'start':
665
				// Get the original settings so that we can restore them later
666
				$original_settings = Jetpack_Sync_Settings::get_settings();
667
668
				// Initialize sync settigns so we can sync as quickly as possible
669
				$sync_settings = wp_parse_args(
670
					array_intersect_key( $assoc_args, Jetpack_Sync_Settings::$valid_settings ),
0 ignored issues
show
Bug introduced by
The property valid_settings cannot be accessed from this context as it is declared private in class Jetpack_Sync_Settings.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
671
					array(
672
						'sync_wait_time' => 0,
673
						'enqueue_wait_time' => 0,
674
						'queue_max_writes_sec' => 10000,
675
						'max_queue_size_full_sync' => 100000
676
					)
677
				);
678
				Jetpack_Sync_Settings::update_settings( $sync_settings );
679
680
				// Convert comma-delimited string of modules to an array
681 View Code Duplication
				if ( ! empty( $assoc_args['modules'] ) ) {
682
					$modules = array_map( 'trim', explode( ',', $assoc_args['modules'] ) );
683
684
					// Convert the array so that the keys are the module name and the value is true to indicate
685
					// that we want to sync the module
686
					$modules = array_map( '__return_true', array_flip( $modules ) );
687
				}
688
689 View Code Duplication
				foreach ( array( 'posts', 'comments', 'users' ) as $module_name ) {
690
					if (
691
						'users' === $module_name &&
692
						isset( $assoc_args[ $module_name ] ) &&
693
						'initial' === $assoc_args[ $module_name ]
694
					) {
695
						$modules[ 'users' ] = 'initial';
0 ignored issues
show
Bug introduced by
The variable $modules 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...
696
					} elseif ( isset( $assoc_args[ $module_name ] ) ) {
697
						$ids = explode( ',', $assoc_args[ $module_name ] );
698
						if ( count( $ids ) > 0 ) {
699
							$modules[ $module_name ] = $ids;
700
						}
701
					}
702
				}
703
704
				if ( empty( $modules ) ) {
705
					$modules = null;
706
				}
707
708
				// Kick off a full sync
709
				if ( Jetpack_Sync_Actions::do_full_sync( $modules ) ) {
710 View Code Duplication
					if ( $modules ) {
711
						WP_CLI::log( sprintf( __( 'Initialized a new full sync with modules: %s', 'jetpack' ), join( ', ', array_keys( $modules ) ) ) );
712
					} else {
713
						WP_CLI::log( __( 'Initialized a new full sync', 'jetpack' ) );
714
					}
715 View Code Duplication
				} else {
716
717
					// Reset sync settings to original.
718
					Jetpack_Sync_Settings::update_settings( $original_settings );
719
720
					if ( $modules ) {
721
						WP_CLI::error( sprintf( __( 'Could not start a new full sync with modules: %s', 'jetpack' ), join( ', ', $modules ) ) );
722
					} else {
723
						WP_CLI::error( __( 'Could not start a new full sync', 'jetpack' ) );
724
					}
725
				}
726
727
				// Keep sending to WPCOM until there's nothing to send
728
				$i = 1;
729
				do {
730
					$result = Jetpack_Sync_Actions::$sender->do_full_sync();
0 ignored issues
show
Bug introduced by
The property sender cannot be accessed from this context as it is declared private in class Jetpack_Sync_Actions.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
731
					if ( is_wp_error( $result ) ) {
732
						$queue_empty_error = ( 'empty_queue_full_sync' == $result->get_error_code() );
733
						if ( ! $queue_empty_error || ( $queue_empty_error && ( 1 == $i ) ) ) {
734
							WP_CLI::error( sprintf( __( 'Sync errored with code: %s', 'jetpack' ), $result->get_error_code() ) );
735
						}
736
					} else {
737
						if ( 1 == $i ) {
738
							WP_CLI::log( __( 'Sent data to WordPress.com', 'jetpack' ) );
739
						} else {
740
							WP_CLI::log( __( 'Sent more data to WordPress.com', 'jetpack' ) );
741
						}
742
					}
743
					$i++;
744
				} while ( $result && ! is_wp_error( $result ) );
745
746
				// Reset sync settings to original.
747
				Jetpack_Sync_Settings::update_settings( $original_settings );
748
749
				WP_CLI::success( __( 'Finished syncing to WordPress.com', 'jetpack' ) );
750
				break;
751
		}
752
	}
753
754
	/**
755
	 * List the contents of a specific Jetpack sync queue.
756
	 *
757
	 * ## OPTIONS
758
	 *
759
	 * peek : List the 100 front-most items on the queue.
760
	 *
761
	 * ## EXAMPLES
762
	 *
763
	 * wp jetpack sync_queue full_sync peek
764
	 *
765
	 * @synopsis <incremental|full_sync> <peek>
766
	 */
767
	public function sync_queue( $args, $assoc_args ) {
768
		if ( ! Jetpack_Sync_Actions::sync_allowed() ) {
769
			WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site.', 'jetpack' ) );
770
		}
771
772
		$queue_name = isset( $args[0] ) ? $args[0] : 'sync';
773
		$action = isset( $args[1] ) ? $args[1] : 'peek';
774
775
		// We map the queue name that way we can support more friendly queue names in the commands, but still use
776
		// the queue name that the code expects.
777
		$queue_name_map = $allowed_queues = array(
0 ignored issues
show
Unused Code introduced by
$allowed_queues is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
778
			'incremental' => 'sync',
779
			'full'        => 'full_sync',
780
		);
781
		$mapped_queue_name = isset( $queue_name_map[ $queue_name ] ) ? $queue_name_map[ $queue_name ] : $queue_name;
782
783
		switch( $action ) {
784
			case 'peek':
785
				require_once JETPACK__PLUGIN_DIR . 'sync/class.jetpack-sync-queue.php';
786
				$queue = new Jetpack_Sync_Queue( $mapped_queue_name );
787
				$items = $queue->peek( 100 );
788
789
				if ( empty( $items ) ) {
790
					/* translators: %s is the name of the queue, either 'incremental' or 'full' */
791
					WP_CLI::log( sprintf( __( 'Nothing is in the queue: %s', 'jetpack' ), $queue_name  ) );
792
				} else {
793
					$collection = array();
794
					foreach ( $items as $item ) {
795
						$collection[] = array(
796
							'action'          => $item[0],
797
							'args'            => json_encode( $item[1] ),
798
							'current_user_id' => $item[2],
799
							'microtime'       => $item[3],
800
							'importing'       => (string) $item[4],
801
						);
802
					}
803
					WP_CLI\Utils\format_items(
804
						'table',
805
						$collection,
806
						array(
807
							'action',
808
							'args',
809
							'current_user_id',
810
							'microtime',
811
							'importing',
812
						)
813
					);
814
				}
815
				break;
816
		}
817
	}
818
819
	/**
820
	 * Cancel's the current Jetpack plan granted by this partner, if applicable
821
	 *
822
	 * Returns success or error JSON
823
	 *
824
	 * <token_json>
825
	 * : JSON blob of WPCOM API token
826
	 *  [--partner-tracking-id=<partner_tracking_id>]
827
	 * : This is an optional ID that a host can pass to help identify a site in logs on WordPress.com
828
	 *
829
	 *  * @synopsis <token_json> [--partner-tracking-id=<partner_tracking_id>]
830
	 */
831
	public function partner_cancel( $args, $named_args ) {
832
		list( $token_json ) = $args;
833
834 View Code Duplication
		if ( ! $token_json || ! ( $token = json_decode( $token_json ) ) ) {
835
			$this->partner_provision_error( new WP_Error( 'missing_access_token',  sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
836
		}
837
838
		if ( isset( $token->error ) ) {
839
			$this->partner_provision_error( new WP_Error( $token->error, $token->message ) );
0 ignored issues
show
Bug introduced by
The variable $token 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...
840
		}
841
842
		if ( ! isset( $token->access_token ) ) {
843
			$this->partner_provision_error( new WP_Error( 'missing_access_token', __( 'Missing or invalid access token', 'jetpack' ) ) );
844
		}
845
846
		$site_identifier = Jetpack_Options::get_option( 'id' );
847
848
		if ( ! $site_identifier ) {
849
			$site_identifier = Jetpack::build_raw_urls( get_home_url() );
850
		}
851
852
		$request = array(
853
			'headers' => array(
854
				'Authorization' => "Bearer " . $token->access_token,
855
				'Host'          => defined( 'JETPACK__WPCOM_JSON_API_HOST_HEADER' ) ? JETPACK__WPCOM_JSON_API_HOST_HEADER : 'public-api.wordpress.com',
856
			),
857
			'timeout' => 60,
858
			'method'  => 'POST',
859
		);
860
861
		$url = sprintf( 'https://%s/rest/v1.3/jpphp/%s/partner-cancel', $this->get_api_host(), $site_identifier );
862 View Code Duplication
		if ( ! empty( $named_args ) && ! empty( $named_args['partner-tracking-id'] ) ) {
863
			$url = esc_url_raw( add_query_arg( 'partner_tracking_id', $named_args['partner-tracking-id'], $url ) );
864
		}
865
866
		$result = Jetpack_Client::_wp_remote_request( $url, $request );
867
868
		Jetpack_Options::delete_option( 'onboarding' );
869
870
		if ( is_wp_error( $result ) ) {
871
			$this->partner_provision_error( $result );
872
		}
873
874
		WP_CLI::log( wp_remote_retrieve_body( $result ) );
875
	}
876
877
	/**
878
	 * Provision a site using a Jetpack Partner license
879
	 *
880
	 * Returns JSON blob
881
	 *
882
	 * ## OPTIONS
883
	 *
884
	 * <token_json>
885
	 * : JSON blob of WPCOM API token
886
	 * [--plan=<plan_name>]
887
	 * : Slug of the requested plan, e.g. premium
888
	 * [--wpcom_user_id=<user_id>]
889
	 * : WordPress.com ID of user to connect as (must be whitelisted against partner key)
890
	 * [--wpcom_user_email=<wpcom_user_email>]
891
	 * : Override the email we send to WordPress.com for registration
892
	 * [--onboarding=<onboarding>]
893
	 * : Guide the user through an onboarding wizard
894
	 * [--force_register=<register>]
895
	 * : Whether to force a site to register
896
	 * [--force_connect=<force_connect>]
897
	 * : Force JPS to not reuse existing credentials
898
	 * [--home_url=<home_url>]
899
	 * : Overrides the home option via the home_url filter, or the WP_HOME constant
900
	 * [--site_url=<site_url>]
901
	 * : Overrides the siteurl option via the site_url filter, or the WP_SITEURL constant
902
	 * [--partner-tracking-id=<partner_tracking_id>]
903
	 * : This is an optional ID that a host can pass to help identify a site in logs on WordPress.com
904
	 *
905
	 * ## EXAMPLES
906
	 *
907
	 *     $ wp jetpack partner_provision '{ some: "json" }' premium 1
908
	 *     { success: true }
909
	 *
910
	 * @synopsis <token_json> [--wpcom_user_id=<user_id>] [--plan=<plan_name>] [--onboarding=<onboarding>] [--force_register=<register>] [--force_connect=<force_connect>] [--home_url=<home_url>] [--site_url=<site_url>] [--wpcom_user_email=<wpcom_user_email>] [--partner-tracking-id=<partner_tracking_id>]
911
	 */
912
	public function partner_provision( $args, $named_args ) {
913
		list( $token_json ) = $args;
914
915 View Code Duplication
		if ( ! $token_json || ! ( $token = json_decode( $token_json ) ) ) {
916
			$this->partner_provision_error( new WP_Error( 'missing_access_token',  sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
917
		}
918
919
		if ( isset( $token->error ) ) {
920
			$message = isset( $token->message )
0 ignored issues
show
Bug introduced by
The variable $token 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...
921
				? $token->message
922
				: '';
923
			$this->partner_provision_error( new WP_Error( $token->error, $message ) );
924
		}
925
926
		if ( ! isset( $token->access_token ) ) {
927
			$this->partner_provision_error( new WP_Error( 'missing_access_token', __( 'Missing or invalid access token', 'jetpack' ) ) );
928
		}
929
930
		require_once( '_inc/class.jetpack-provision.php' );
931
		$body_json = Jetpack_Provision::partner_provision( $token->access_token, $named_args );
932
933
		WP_CLI::log( json_encode( $body_json ) );
934
	}
935
936
	/**
937
	 * Manages your Jetpack sitemap
938
	 *
939
	 * ## OPTIONS
940
	 *
941
	 * rebuild : Rebuild all sitemaps
942
	 * --purge : if set, will remove all existing sitemap data before rebuilding
943
	 *
944
	 * ## EXAMPLES
945
	 *
946
	 * wp jetpack sitemap rebuild
947
	 *
948
	 * @subcommand sitemap
949
	 * @synopsis <rebuild> [--purge]
950
	 */
951
	public function sitemap( $args, $assoc_args ) {
952
		if ( ! Jetpack::is_active() ) {
953
			WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
954
		}
955
		if ( ! Jetpack::is_module_active( 'sitemaps' ) ) {
956
			WP_CLI::error( __( 'Jetpack Sitemaps module is not currently active. Activate it first if you want to work with sitemaps.', 'jetpack' ) );
957
		}
958
		if ( ! class_exists( 'Jetpack_Sitemap_Builder' ) ) {
959
			WP_CLI::error( __( 'Jetpack Sitemaps module is active, but unavailable. This can happen if your site is set to discourage search engine indexing. Please enable search engine indexing to allow sitemap generation.', 'jetpack' ) );
960
		}
961
962
		if ( isset( $assoc_args['purge'] ) && $assoc_args['purge'] ) {
963
			$librarian = new Jetpack_Sitemap_Librarian();
964
			$librarian->delete_all_stored_sitemap_data();
965
		}
966
967
		$sitemap_builder = new Jetpack_Sitemap_Builder();
968
		$sitemap_builder->update_sitemap();
969
	}
970
971
	private function get_api_host() {
972
		$env_api_host = getenv( 'JETPACK_START_API_HOST', true );
973
		return $env_api_host ? $env_api_host : JETPACK__WPCOM_JSON_API_HOST;
974
	}
975
976
	private function partner_provision_error( $error ) {
977
		WP_CLI::log( json_encode( array(
978
			'success'       => false,
979
			'error_code'    => $error->get_error_code(),
980
			'error_message' => $error->get_error_message()
981
		) ) );
982
		exit( 1 );
0 ignored issues
show
Coding Style Compatibility introduced by
The method partner_provision_error() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
983
	}
984
}
985
986
/*
987
 * Standard "ask for permission to continue" function.
988
 * If action cancelled, ask if they need help.
989
 *
990
 * Written outside of the class so it's not listed as an executable command w/ 'wp jetpack'
991
 *
992
 * @param $flagged   bool   false = normal option | true = flagged by get_jetpack_options_for_reset()
993
 * @param $error_msg string (optional)
994
 */
995
function jetpack_cli_are_you_sure( $flagged = false, $error_msg = false ) {
996
	$cli = new Jetpack_CLI();
997
998
	// Default cancellation message
999
	if ( ! $error_msg ) {
1000
		$error_msg =
1001
			__( 'Action cancelled. Have a question?', 'jetpack' )
1002
			. ' '
1003
			. $cli->green_open
1004
			. 'jetpack.com/support'
1005
			.  $cli->color_close;
1006
	}
1007
1008
	if ( ! $flagged ) {
1009
		$prompt_message = __( 'Are you sure? This cannot be undone. Type "yes" to continue:', '"yes" is a command.  Do not translate that.', 'jetpack' );
1010
	} else {
1011
		/* translators: Don't translate the word yes here. */
1012
		$prompt_message = __( 'Are you sure? Modifying this option may disrupt your Jetpack connection.  Type "yes" to continue.', 'jetpack' );
1013
	}
1014
1015
	WP_CLI::line( $prompt_message );
1016
	$handle = fopen( "php://stdin", "r" );
1017
	$line = fgets( $handle );
1018
	if ( 'yes' != trim( $line ) ){
1019
		WP_CLI::error( $error_msg );
1020
	}
1021
}
1022