PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.2.1
Jetpack – WP Security, Backup, Speed, & Growth v7.2.1
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
← All changes | class.jetpack-cli.php +292 -963 13.7.27.2.1 View file →
@@ -1,62 +1,19 @@
1 -<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 -/**
3 - * WP-CLI command class.
4 - *
5 - * @package automattic/jetpack
6 - */
1 +<?php
7 2
8 -use Automattic\Jetpack\Connection\Client;
9 -use Automattic\Jetpack\Connection\Manager as Connection_Manager;
10 -use Automattic\Jetpack\Connection\Tokens;
11 -use Automattic\Jetpack\Identity_Crisis;
12 -use Automattic\Jetpack\IP\Utils as IP_Utils;
13 -use Automattic\Jetpack\Publicize\Publicize;
14 -use Automattic\Jetpack\Status;
15 -use Automattic\Jetpack\Sync\Actions;
16 -use Automattic\Jetpack\Sync\Listener;
17 -use Automattic\Jetpack\Sync\Modules;
18 -use Automattic\Jetpack\Sync\Queue;
19 -use Automattic\Jetpack\Sync\Settings;
20 -use Automattic\Jetpack\Waf\Brute_Force_Protection\Brute_Force_Protection_Shared_Functions;
21 -
22 -if ( ! class_exists( 'WP_CLI_Command' ) ) {
23 - return;
24 -}
25 -
26 -// @phan-suppress-next-line PhanUndeclaredFunctionInCallable -- https://github.com/phan/phan/issues/4763
27 3 WP_CLI::add_command( 'jetpack', 'Jetpack_CLI' );
28 4
29 5 /**
30 6 * Control your local Jetpack installation.
7 + *
8 + * Minimum PHP requirement for WP-CLI is PHP 5.3, so ignore PHP 5.2 compatibility issues.
9 + * @phpcs:disable PHPCompatibility.PHP.NewLanguageConstructs.t_ns_separatorFound
31 10 */
32 11 class Jetpack_CLI extends WP_CLI_Command {
33 - /**
34 - * Console escape code for green.
35 - *
36 - * @var string
37 - */
38 - public $green_open = "\033[32m";
39 -
40 - /**
41 - * Console escape code for red.
42 - *
43 - * @var string
44 - */
45 - public $red_open = "\033[31m";
46 -
47 - /**
48 - * Console escape code for yellow.
49 - *
50 - * @var string
51 - */
12 + // Aesthetics
13 + public $green_open = "\033[32m";
14 + public $red_open = "\033[31m";
52 15 public $yellow_open = "\033[33m";
53 -
54 - /**
55 - * Console escape code to reset coloring.
56 - *
57 - * @var string
58 - */
59 16 public $color_close = "\033[0m";
60 17
61 18 /**
62 19 * Get Jetpack Details
@@ -71,14 +28,12 @@
71 28 *
72 29 * wp jetpack status
73 30 * wp jetpack status full
74 31 *
75 - * @param array $args Positional args.
76 32 */
77 - public function status( $args ) {
78 - require_once JETPACK__PLUGIN_DIR . '_inc/lib/debugger.php';
33 + public function status( $args, $assoc_args ) {
34 + jetpack_require_lib( 'debugger' );
79 35
80 - /* translators: %s is the site URL */
81 36 WP_CLI::line( sprintf( __( 'Checking status for %s', 'jetpack' ), esc_url( get_home_url() ) ) );
82 37
83 38 if ( isset( $args[0] ) && 'full' !== $args[0] ) {
84 39 /* translators: %s is a command like "prompt" */
@@ -95,22 +50,19 @@
95 50 WP_CLI::success( __( 'Jetpack is currently connected to WordPress.com', 'jetpack' ) );
96 51 } else {
97 52 $error = array();
98 53 foreach ( $cxntests->list_fails() as $fail ) {
99 - $error[] = $fail['name'] . ( empty( $fail['message'] ) ? '' : ': ' . $fail['message'] );
54 + $error[] = $fail['name'] . ': ' . $fail['message'];
100 55 }
101 56 WP_CLI::error_multi_line( $error );
102 57
103 58 $cxntests->output_results_for_cli();
104 59
105 - WP_CLI::error( __( 'One or more tests did not pass. Please investigate!', 'jetpack' ) ); // Exit CLI.
60 + WP_CLI::error( __('Jetpack connection is broken.', 'jetpack' ) ); // Exit CLI.
106 61 }
107 62
108 - /* translators: %s is current version of Jetpack, for example 7.3 */
109 63 WP_CLI::line( sprintf( __( 'The Jetpack Version is %s', 'jetpack' ), JETPACK__VERSION ) );
110 - /* translators: %d is WP.com ID of this blog */
111 64 WP_CLI::line( sprintf( __( 'The WordPress.com blog_id is %d', 'jetpack' ), Jetpack_Options::get_option( 'id' ) ) );
112 - /* translators: %s is the email address of the connection owner */
113 65 WP_CLI::line( sprintf( __( 'The WordPress.com account for the primary connection is %s', 'jetpack' ), $master_user_email ) );
114 66
115 67 /*
116 68 * Are they asking for all data?
@@ -116,41 +68,41 @@
116 68 * Are they asking for all data?
117 69 *
118 70 * Loop through heartbeat data and organize by priority.
119 71 */
120 - $all_data = ( isset( $args[0] ) && 'full' === $args[0] ) ? 'full' : false;
72 + $all_data = ( isset( $args[0] ) && 'full' == $args[0] ) ? 'full' : false;
121 73 if ( $all_data ) {
122 - // Heartbeat data.
74 + // Heartbeat data
123 75 WP_CLI::line( "\n" . __( 'Additional data: ', 'jetpack' ) );
124 76
125 77 // Get the filtered heartbeat data.
126 - // Filtered so we can color/list by severity.
78 + // Filtered so we can color/list by severity
127 79 $stats = Jetpack::jetpack_check_heartbeat_data();
128 80
129 - // Display red flags first.
81 + // Display red flags first
130 82 foreach ( $stats['bad'] as $stat => $value ) {
131 - WP_CLI::line( sprintf( "$this->red_open%-'.16s %s $this->color_close", $stat, $value ) );
83 + printf( "$this->red_open%-'.16s %s $this->color_close\n", $stat, $value );
132 84 }
133 85
134 - // Display caution warnings next.
86 + // Display caution warnings next
135 87 foreach ( $stats['caution'] as $stat => $value ) {
136 - WP_CLI::line( sprintf( "$this->yellow_open%-'.16s %s $this->color_close", $stat, $value ) );
88 + printf( "$this->yellow_open%-'.16s %s $this->color_close\n", $stat, $value );
137 89 }
138 90
139 91 // The rest of the results are good!
140 92 foreach ( $stats['good'] as $stat => $value ) {
141 93
142 - // Modules should get special spacing for aestetics.
94 + // Modules should get special spacing for aestetics
143 95 if ( strpos( $stat, 'odule-' ) ) {
144 - WP_CLI::line( sprintf( "%-'.30s %s", $stat, $value ) );
145 - usleep( 4000 ); // For dramatic effect lolz.
96 + printf( "%-'.30s %s\n", $stat, $value );
97 + usleep( 4000 ); // For dramatic effect lolz
146 98 continue;
147 99 }
148 - WP_CLI::line( sprintf( "%-'.16s %s", $stat, $value ) );
149 - usleep( 4000 ); // For dramatic effect lolz.
100 + printf( "%-'.16s %s\n", $stat, $value );
101 + usleep( 4000 ); // For dramatic effect lolz
150 102 }
151 103 } else {
152 - // Just the basics.
104 + // Just the basics
153 105 WP_CLI::line( "\n" . _x( "View full status with 'wp jetpack status full'", '"wp jetpack status full" is a command - do not translate', 'jetpack' ) );
154 106 }
155 107 }
156 108
@@ -164,20 +116,19 @@
164 116 * wp jetpack test-connection
165 117 *
166 118 * @subcommand test-connection
167 119 */
168 - public function test_connection() {
120 + public function test_connection( $args, $assoc_args ) {
169 121
170 - /* translators: %s is the site URL */
171 122 WP_CLI::line( sprintf( __( 'Testing connection for %s', 'jetpack' ), esc_url( get_site_url() ) ) );
172 123
173 - if ( ! Jetpack::is_connection_ready() ) {
124 + if ( ! Jetpack::is_active() ) {
174 125 WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
175 126 }
176 127
177 - $response = Client::wpcom_json_api_request_as_blog(
128 + $response = Jetpack_Client::wpcom_json_api_request_as_blog(
178 129 sprintf( '/jetpack-blogs/%d/test-connection', Jetpack_Options::get_option( 'id' ) ),
179 - Client::WPCOM_JSON_API_VERSION
130 + Jetpack_Client::WPCOM_JSON_API_VERSION
180 131 );
181 132
182 133 if ( is_wp_error( $response ) ) {
183 134 /* translators: %1$s is the error code, %2$s is the error message */
@@ -188,11 +139,11 @@
188 139 if ( ! $body ) {
189 140 WP_CLI::error( __( 'Failed to test connection (empty response body)', 'jetpack' ) );
190 141 }
191 142
192 - $result = json_decode( $body );
143 + $result = json_decode( $body );
193 144 $is_connected = (bool) $result->connected;
194 - $message = $result->message;
145 + $message = $result->message;
195 146
196 147 if ( $is_connected ) {
197 148 WP_CLI::success( $message );
198 149 } else {
@@ -208,52 +159,46 @@
208 159 * blog: Disconnect the entire blog.
209 160 *
210 161 * user <user_identifier>: Disconnect a specific user from WordPress.com.
211 162 *
212 - * [--force]
213 - * If the user ID provided is the connection owner, it will only be disconnected if --force is passed
163 + * Please note, the primary account that the blog is connected
164 + * to WordPress.com with cannot be disconnected without
165 + * disconnecting the entire blog.
214 166 *
215 167 * ## EXAMPLES
216 168 *
217 169 * wp jetpack disconnect blog
218 170 * wp jetpack disconnect user 13
219 - * wp jetpack disconnect user 1 --force
220 171 * wp jetpack disconnect user username
221 172 * wp jetpack disconnect user email@domain.com
222 173 *
223 - * @synopsis <blog|user> [<user_identifier>] [--force]
224 - *
225 - * @param array $args Positional args.
226 - * @param array $assoc_args Named args.
174 + * @synopsis <blog|user> [<user_identifier>]
227 175 */
228 176 public function disconnect( $args, $assoc_args ) {
229 - $user = null;
230 - if ( ! Jetpack::is_connection_ready() ) {
231 - WP_CLI::success( __( 'The site is not currently connected, so nothing to do!', 'jetpack' ) );
232 - return;
177 + if ( ! Jetpack::is_active() ) {
178 + WP_CLI::error( __( 'You cannot disconnect, without having first connected.', 'jetpack' ) );
233 179 }
234 180
235 181 $action = isset( $args[0] ) ? $args[0] : 'prompt';
236 - if ( ! in_array( $action, array( 'blog', 'user', 'prompt' ), true ) ) {
182 + if ( ! in_array( $action, array( 'blog', 'user', 'prompt' ) ) ) {
237 183 /* translators: %s is a command like "prompt" */
238 184 WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
239 185 }
240 186
241 - if ( in_array( $action, array( 'user' ), true ) ) {
187 + if ( in_array( $action, array( 'user' ) ) ) {
242 188 if ( isset( $args[1] ) ) {
243 189 $user_id = $args[1];
244 190 if ( ctype_digit( $user_id ) ) {
245 - $field = 'id';
191 + $field = 'id';
246 192 $user_id = (int) $user_id;
247 193 } elseif ( is_email( $user_id ) ) {
248 - $field = 'email';
194 + $field = 'email';
249 195 $user_id = sanitize_user( $user_id, true );
250 196 } else {
251 - $field = 'login';
197 + $field = 'login';
252 198 $user_id = sanitize_user( $user_id, true );
253 199 }
254 - $user = get_user_by( $field, $user_id );
255 - if ( ! $user ) {
200 + if ( ! $user = get_user_by( $field, $user_id ) ) {
256 201 WP_CLI::error( __( 'Please specify a valid user.', 'jetpack' ) );
257 202 }
258 203 } else {
259 204 WP_CLI::error( __( 'Please specify a user by either ID, username, or email.', 'jetpack' ) );
@@ -259,40 +204,24 @@
259 204 WP_CLI::error( __( 'Please specify a user by either ID, username, or email.', 'jetpack' ) );
260 205 }
261 206 }
262 207
263 - $force_user_disconnect = ! empty( $assoc_args['force'] );
264 -
265 208 switch ( $action ) {
266 209 case 'blog':
267 210 Jetpack::log( 'disconnect' );
268 - ( new Connection_Manager( 'jetpack' ) )->disconnect_site();
269 - WP_CLI::success(
270 - sprintf(
271 - /* translators: %s is the site URL */
272 - __( 'Jetpack has been successfully disconnected for %s.', 'jetpack' ),
273 - esc_url( get_site_url() )
274 - )
275 - );
211 + Jetpack::disconnect();
212 + WP_CLI::success( sprintf(
213 + __( 'Jetpack has been successfully disconnected for %s.', 'jetpack' ),
214 + esc_url( get_site_url() )
215 + ) );
276 216 break;
277 217 case 'user':
278 - $connection_manager = new Connection_Manager( 'jetpack' );
279 - $disconnected = $connection_manager->disconnect_user( $user->ID, $force_user_disconnect );
280 - if ( $disconnected ) {
218 + if ( Jetpack::unlink_user( $user->ID ) ) {
281 219 Jetpack::log( 'unlink', $user->ID );
282 220 WP_CLI::success( __( 'User has been successfully disconnected.', 'jetpack' ) );
283 221 } else {
284 - if ( ! $connection_manager->is_user_connected( $user->ID ) ) {
285 - /* translators: %s is a username */
286 - $error_message = sprintf( __( 'User %s could not be disconnected because it is not connected!', 'jetpack' ), "{$user->data->user_login} <{$user->data->user_email}>" );
287 - } elseif ( ! $force_user_disconnect && $connection_manager->is_connection_owner( $user->ID ) ) {
288 - /* translators: %s is a username */
289 - $error_message = sprintf( __( 'User %s could not be disconnected because it is the connection owner! If you want to disconnect in anyway, use the --force parameter.', 'jetpack' ), "{$user->data->user_login} <{$user->data->user_email}>" );
290 - } else {
291 - /* translators: %s is a username */
292 - $error_message = sprintf( __( 'User %s could not be disconnected.', 'jetpack' ), "{$user->data->user_login} <{$user->data->user_email}>" );
293 - }
294 - WP_CLI::error( $error_message );
222 + /* translators: %s is a username */
223 + WP_CLI::error( sprintf( __( "User %s could not be disconnected. Are you sure they're connected currently?", 'jetpack' ), "{$user->login} <{$user->email}>" ) );
295 224 }
296 225 break;
297 226 case 'prompt':
298 227 WP_CLI::error( __( 'Please specify if you would like to disconnect a blog or user.', 'jetpack' ) );
@@ -317,191 +246,71 @@
317 246 * ## EXAMPLES
318 247 *
319 248 * wp jetpack reset options
320 249 * wp jetpack reset modules
321 - * wp jetpack reset sync-checksum --dry-run --offset=0
322 250 *
323 - * @synopsis <modules|options|sync-checksum> [--dry-run] [--offset=<offset>]
324 - *
325 - * @param array $args Positional args.
326 - * @param array $assoc_args Named args.
251 + * @synopsis <modules|options>
327 252 */
328 253 public function reset( $args, $assoc_args ) {
329 254 $action = isset( $args[0] ) ? $args[0] : 'prompt';
330 - if ( ! in_array( $action, array( 'options', 'modules', 'sync-checksum' ), true ) ) {
255 + if ( ! in_array( $action, array( 'options', 'modules' ) ) ) {
331 256 /* translators: %s is a command like "prompt" */
332 257 WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
333 258 }
334 259
335 - $is_dry_run = ! empty( $assoc_args['dry-run'] );
260 + // Are you sure?
261 + jetpack_cli_are_you_sure();
336 262
337 - if ( $is_dry_run ) {
338 - WP_CLI::warning(
339 - __( "\nThis is a dry run.\n", 'jetpack' ) .
340 - __( "No actions will be taken.\n", 'jetpack' ) .
341 - __( "The following messages will give you preview of what will happen when you run this command.\n\n", 'jetpack' )
342 - );
343 - } else {
344 - // We only need to confirm "Are you sure?" when we are not doing a dry run.
345 - jetpack_cli_are_you_sure();
346 - }
347 -
348 263 switch ( $action ) {
349 264 case 'options':
350 265 $options_to_reset = Jetpack_Options::get_options_for_reset();
351 - // Reset the Jetpack options.
352 - WP_CLI::line(
353 - sprintf(
354 - /* translators: %s is the site URL */
355 - __( "Resetting Jetpack Options for %s...\n", 'jetpack' ),
356 - esc_url( get_site_url() )
357 - )
358 - );
359 - sleep( 1 ); // Take a breath.
266 +
267 + // Reset the Jetpack options
268 + WP_CLI::line( sprintf(
269 + __( "Resetting Jetpack Options for %s...\n", "jetpack" ),
270 + esc_url( get_site_url() )
271 + ) );
272 + sleep(1); // Take a breath
360 273 foreach ( $options_to_reset['jp_options'] as $option_to_reset ) {
361 - if ( ! $is_dry_run ) {
362 - Jetpack_Options::delete_option( $option_to_reset );
363 - usleep( 100000 );
364 - }
365 -
274 + Jetpack_Options::delete_option( $option_to_reset );
275 + usleep( 100000 );
366 276 /* translators: This is the result of an action. The option named %s was reset */
367 277 WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
368 278 }
369 279
370 - // Reset the WP options.
371 - WP_CLI::line( __( "Resetting the jetpack options stored in wp_options...\n", 'jetpack' ) );
372 - usleep( 500000 ); // Take a breath.
280 + // Reset the WP options
281 + WP_CLI::line( __( "Resetting the jetpack options stored in wp_options...\n", "jetpack" ) );
282 + usleep( 500000 ); // Take a breath
373 283 foreach ( $options_to_reset['wp_options'] as $option_to_reset ) {
374 - if ( ! $is_dry_run ) {
375 - delete_option( $option_to_reset );
376 - usleep( 100000 );
377 - }
284 + delete_option( $option_to_reset );
285 + usleep( 100000 );
378 286 /* translators: This is the result of an action. The option named %s was reset */
379 287 WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
380 288 }
381 289
382 - // Reset to default modules.
383 - WP_CLI::line( __( "Resetting default modules...\n", 'jetpack' ) );
384 - usleep( 500000 ); // Take a breath.
290 + // Reset to default modules
291 + WP_CLI::line( __( "Resetting default modules...\n", "jetpack" ) );
292 + usleep( 500000 ); // Take a breath
385 293 $default_modules = Jetpack::get_default_modules();
386 - if ( ! $is_dry_run ) {
387 - Jetpack::update_active_modules( $default_modules );
388 - }
294 + Jetpack::update_active_modules( $default_modules );
389 295 WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
296 +
297 + // Jumpstart option is special
298 + Jetpack_Options::update_option( 'jumpstart', 'new_connection' );
299 + WP_CLI::success( __( 'jumpstart option reset', 'jetpack' ) );
390 300 break;
391 301 case 'modules':
392 - if ( ! $is_dry_run ) {
393 - $default_modules = Jetpack::get_default_modules();
394 - Jetpack::update_active_modules( $default_modules );
395 - }
396 -
302 + $default_modules = Jetpack::get_default_modules();
303 + Jetpack::update_active_modules( $default_modules );
397 304 WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
398 305 break;
399 306 case 'prompt':
400 - WP_CLI::error( __( 'Please specify if you would like to reset your options, modules or sync-checksum', 'jetpack' ) );
307 + WP_CLI::error( __( 'Please specify if you would like to reset your options, or modules', 'jetpack' ) );
401 308 break;
402 - case 'sync-checksum':
403 - $option = 'jetpack_callables_sync_checksum';
404 -
405 - if ( is_multisite() ) {
406 - $offset = isset( $assoc_args['offset'] ) ? (int) $assoc_args['offset'] : 0;
407 -
408 - /*
409 - * 1000 is a good limit since we don't expect the number of sites to be more than 1000
410 - * Offset can be used to paginate and try to clean up more sites.
411 - */
412 - $sites = get_sites(
413 - array(
414 - 'number' => 1000,
415 - 'offset' => $offset,
416 - )
417 - );
418 - $count_fixes = 0;
419 - foreach ( $sites as $site ) {
420 - switch_to_blog( $site->blog_id );
421 - $count = self::count_option( $option );
422 - if ( $count > 1 ) {
423 - if ( ! $is_dry_run ) {
424 - delete_option( $option );
425 - }
426 - WP_CLI::line(
427 - sprintf(
428 - /* translators: %1$d is a number, %2$s is the name of an option, %2$s is the site URL. */
429 - __( 'Deleted %1$d %2$s options from %3$s', 'jetpack' ),
430 - $count,
431 - $option,
432 - "{$site->domain}{$site->path}"
433 - )
434 - );
435 - ++$count_fixes;
436 - if ( ! $is_dry_run ) {
437 - /*
438 - * We could be deleting a lot of options rows at the same time.
439 - * Allow some time for replication to catch up.
440 - */
441 - sleep( 3 );
442 - }
443 - }
444 -
445 - restore_current_blog();
446 - }
447 - if ( $count_fixes ) {
448 - WP_CLI::success(
449 - sprintf(
450 - /* translators: %1$s is the name of an option, %2$d is a number of sites. */
451 - __( 'Successfully reset %1$s on %2$d sites.', 'jetpack' ),
452 - $option,
453 - $count_fixes
454 - )
455 - );
456 - } else {
457 - WP_CLI::success( __( 'No options were deleted.', 'jetpack' ) );
458 - }
459 - return;
460 - }
461 -
462 - $count = self::count_option( $option );
463 - if ( $count > 1 ) {
464 - if ( ! $is_dry_run ) {
465 - delete_option( $option );
466 - }
467 - WP_CLI::success(
468 - sprintf(
469 - /* translators: %1$d is a number, %2$s is the name of an option. */
470 - __( 'Deleted %1$d %2$s options', 'jetpack' ),
471 - $count,
472 - $option
473 - )
474 - );
475 - return;
476 - }
477 -
478 - WP_CLI::success( __( 'No options were deleted.', 'jetpack' ) );
479 - break;
480 -
481 309 }
482 310 }
483 311
484 312 /**
485 - * Return the number of times an option appears
486 - * Normally an option would only appear 1 since the option key is supposed to be unique
487 - * but if a site hasn't updated the DB schema then that would not be the case.
488 - *
489 - * @param string $option Option name.
490 - *
491 - * @return int
492 - */
493 - private static function count_option( $option ) {
494 - global $wpdb;
495 - return (int) $wpdb->get_var(
496 - $wpdb->prepare(
497 - "SELECT COUNT(*) FROM $wpdb->options WHERE option_name = %s",
498 - $option
499 - )
500 - );
501 - }
502 -
503 - /**
504 313 * Manage Jetpack Modules
505 314 *
506 315 * ## OPTIONS
507 316 *
@@ -540,15 +349,11 @@
540 349 * wp jetpack module deactivate stats
541 350 * wp jetpack module toggle stats
542 351 * wp jetpack module activate all
543 352 * wp jetpack module deactivate all
544 - *
545 - * @param array $args Positional args.
546 - * @param array $assoc_args Named args.
547 353 */
548 354 public function module( $args, $assoc_args ) {
549 - $module_slug = null;
550 - $action = isset( $args[0] ) ? $args[0] : 'list';
355 + $action = isset( $args[0] ) ? $args[0] : 'list';
551 356
552 357 if ( isset( $args[1] ) ) {
553 358 $module_slug = $args[1];
554 359 if ( 'all' !== $module_slug && ! Jetpack::is_module( $module_slug ) ) {
@@ -591,12 +396,10 @@
591 396 case 'activate':
592 397 $module = Jetpack::get_module( $module_slug );
593 398 Jetpack::log( 'activate', $module_slug );
594 399 if ( Jetpack::activate_module( $module_slug, false, false ) ) {
595 - /* translators: %s is the name of a Jetpack module */
596 400 WP_CLI::success( sprintf( __( '%s has been activated.', 'jetpack' ), $module['name'] ) );
597 401 } else {
598 - /* translators: %s is the name of a Jetpack module */
599 402 WP_CLI::error( sprintf( __( '%s could not be activated.', 'jetpack' ), $module['name'] ) );
600 403 }
601 404 break;
602 405 case 'activate_all':
@@ -607,9 +410,8 @@
607 410 case 'deactivate':
608 411 $module = Jetpack::get_module( $module_slug );
609 412 Jetpack::log( 'deactivate', $module_slug );
610 413 Jetpack::deactivate_module( $module_slug );
611 - /* translators: %s is the name of a Jetpack module */
612 414 WP_CLI::success( sprintf( __( '%s has been deactivated.', 'jetpack' ), $module['name'] ) );
613 415 break;
614 416 case 'deactivate_all':
615 417 Jetpack::delete_active_modules();
@@ -625,122 +427,119 @@
625 427 * Manage Protect Settings
626 428 *
627 429 * ## OPTIONS
628 430 *
629 - * allow: Add an IP address to an always allow list. You can also read or clear the allow list.
431 + * whitelist: Whitelist an IP address. You can also read or clear the whitelist.
630 432 *
631 433 *
632 434 * ## EXAMPLES
633 435 *
634 - * wp jetpack protect allow <ip address>
635 - * wp jetpack protect allow list
636 - * wp jetpack protect allow clear
436 + * wp jetpack protect whitelist <ip address>
437 + * wp jetpack protect whitelist list
438 + * wp jetpack protect whitelist clear
637 439 *
638 - * @synopsis <allow> [<ip|ip_low-ip_high|list|clear>]
639 - *
640 - * @param array $args Positional args.
440 + * @synopsis <whitelist> [<ip|ip_low-ip_high|list|clear>]
641 441 */
642 - public function protect( $args ) {
442 + public function protect( $args, $assoc_args ) {
643 443 $action = isset( $args[0] ) ? $args[0] : 'prompt';
644 - if ( ! in_array( $action, array( 'whitelist', 'allow' ), true ) ) { // Still allow "whitelist" for legacy support.
444 + if ( ! in_array( $action, array( 'whitelist' ) ) ) {
645 445 /* translators: %s is a command like "prompt" */
646 446 WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
647 447 }
648 - // Check if module is active.
448 + // Check if module is active
649 449 if ( ! Jetpack::is_module_active( __FUNCTION__ ) ) {
650 - /* translators: %s is a module name */
651 - WP_CLI::error( sprintf( _x( '%1$s is not active. You can activate it with "wp jetpack module activate %2$s"', '"wp jetpack module activate" is a command - do not translate', 'jetpack' ), __FUNCTION__, __FUNCTION__ ) );
450 + 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__ ) );
652 451 }
653 - if ( in_array( $action, array( 'allow', 'whitelist' ), true ) ) {
452 + if ( in_array( $action, array( 'whitelist' ) ) ) {
654 453 if ( isset( $args[1] ) ) {
655 - $action = 'allow';
454 + $action = 'whitelist';
656 455 } else {
657 456 $action = 'prompt';
658 457 }
659 458 }
660 459 switch ( $action ) {
661 - case 'allow':
662 - $allow = array();
663 - $new_ip = $args[1];
664 - $current_allow = get_site_option( 'jetpack_protect_whitelist', array() ); // @todo Update the option name.
460 + case 'whitelist':
461 + $whitelist = array();
462 + $new_ip = $args[1];
463 + $current_whitelist = get_site_option( 'jetpack_protect_whitelist', array() );
665 464
666 - // Build array of IPs that are already on the allowed list.
667 - // Re-build manually instead of using jetpack_protect_format_allow_list() so we can easily get
668 - // low & high range params for IP_Utils::ip_address_is_in_range().
669 - foreach ( $current_allow as $allowed ) {
465 + // Build array of IPs that are already whitelisted.
466 + // Re-build manually instead of using jetpack_protect_format_whitelist() so we can easily get
467 + // low & high range params for jetpack_protect_ip_address_is_in_range();
468 + foreach( $current_whitelist as $whitelisted ) {
670 469
671 - // IP ranges.
672 - if ( $allowed->range ) {
470 + // IP ranges
471 + if ( $whitelisted->range ) {
673 472
674 - // Is it already on the allowed list?
675 - if ( IP_Utils::ip_address_is_in_range( $new_ip, $allowed->range_low, $allowed->range_high ) ) {
473 + // Is it already whitelisted?
474 + if ( jetpack_protect_ip_address_is_in_range( $new_ip, $whitelisted->range_low, $whitelisted->range_high ) ) {
676 475 /* translators: %s is an IP address */
677 - WP_CLI::error( sprintf( __( '%s is already on the always allow list.', 'jetpack' ), $new_ip ) );
476 + WP_CLI::error( sprintf( __( '%s has already been whitelisted', 'jetpack' ), $new_ip ) );
678 477 break;
679 478 }
680 - $allow[] = $allowed->range_low . ' - ' . $allowed->range_high;
479 + $whitelist[] = $whitelisted->range_low . " - " . $whitelisted->range_high;
681 480
682 - } else { // Individual IPs.
481 + } else { // Individual IPs
683 482
684 - // Check if the IP is already on the allow list (single IP only).
685 - if ( $new_ip === $allowed->ip_address ) {
483 + // Check if the IP is already whitelisted (single IP only)
484 + if ( $new_ip == $whitelisted->ip_address ) {
686 485 /* translators: %s is an IP address */
687 - WP_CLI::error( sprintf( __( '%s is already on the always allow list.', 'jetpack' ), $new_ip ) );
486 + WP_CLI::error( sprintf( __( '%s has already been whitelisted', 'jetpack' ), $new_ip ) );
688 487 break;
689 488 }
690 - $allow[] = $allowed->ip_address;
489 + $whitelist[] = $whitelisted->ip_address;
691 490
692 491 }
693 492 }
694 493
695 494 /*
696 - * List the allowed IPs.
697 - * Done here because it's easier to read the $allow array after it's been rebuilt.
495 + * List the whitelist
496 + * Done here because it's easier to read the $whitelist array after it's been rebuilt
698 497 */
699 - if ( isset( $args[1] ) && 'list' === $args[1] ) {
700 - if ( ! empty( $allow ) ) {
701 - WP_CLI::success( __( 'Here are your always allowed IPs:', 'jetpack' ) );
702 - foreach ( $allow as $ip ) {
703 - WP_CLI::line( "\t" . str_pad( $ip, 24 ) );
498 + if ( isset( $args[1] ) && 'list' == $args[1] ) {
499 + if ( ! empty( $whitelist ) ) {
500 + WP_CLI::success( __( 'Here are your whitelisted IPs:', 'jetpack' ) );
501 + foreach ( $whitelist as $ip ) {
502 + WP_CLI::line( "\t" . str_pad( $ip, 24 ) ) ;
704 503 }
705 504 } else {
706 - WP_CLI::line( __( 'Always allow list is empty.', 'jetpack' ) );
505 + WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
707 506 }
708 507 break;
709 508 }
710 509
711 510 /*
712 - * Clear the always allow list.
511 + * Clear the whitelist
713 512 */
714 - if ( isset( $args[1] ) && 'clear' === $args[1] ) {
715 - if ( ! empty( $allow ) ) {
716 - $allow = array();
717 - Brute_Force_Protection_Shared_Functions::save_allow_list( $allow ); // @todo Need to update function name in the Protect module.
718 - WP_CLI::success( __( 'Cleared all IPs from the always allow list.', 'jetpack' ) );
513 + if ( isset( $args[1] ) && 'clear' == $args[1] ) {
514 + if ( ! empty( $whitelist ) ) {
515 + $whitelist = array();
516 + jetpack_protect_save_whitelist( $whitelist );
517 + WP_CLI::success( __( 'Cleared all whitelisted IPs', 'jetpack' ) );
719 518 } else {
720 - WP_CLI::line( __( 'Always allow list is empty.', 'jetpack' ) );
519 + WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
721 520 }
722 521 break;
723 522 }
724 523
725 - // Append new IP to allow array.
726 - array_push( $allow, $new_ip );
524 + // Append new IP to whitelist array
525 + array_push( $whitelist, $new_ip );
727 526
728 - // Save allow list if there are no errors.
729 - $result = Brute_Force_Protection_Shared_Functions::save_allow_list( $allow ); // @todo Need to update function name in the Protect module.
527 + // Save whitelist if there are no errors
528 + $result = jetpack_protect_save_whitelist( $whitelist );
730 529 if ( is_wp_error( $result ) ) {
731 - WP_CLI::error( $result );
530 + WP_CLI::error( __( $result, 'jetpack' ) );
732 531 }
733 532
734 533 /* translators: %s is an IP address */
735 - WP_CLI::success( sprintf( __( '%s has been added to the always allowed list.', 'jetpack' ), $new_ip ) );
534 + WP_CLI::success( sprintf( __( '%s has been whitelisted.', 'jetpack' ), $new_ip ) );
736 535 break;
737 536 case 'prompt':
738 537 WP_CLI::error(
739 538 __( 'No command found.', 'jetpack' ) . "\n" .
740 - __( 'Please enter the IP address you want to always allow.', 'jetpack' ) . "\n" .
741 - _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 add IP ranges - low_range/high_range should be translated.', 'jetpack' ) . "\n" .
742 - _x( "You can also 'list' or 'clear' the always allowed list.", "'list' and 'clear' are commands and should not be translated", 'jetpack' ) . "\n"
539 + __( 'Please enter the IP address you want to whitelist.', 'jetpack' ) . "\n" .
540 + _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" .
541 + _x( "You can also 'list' or 'clear' the whitelist.", "'list' and 'clear' are commands and should not be translated", 'jetpack' ) . "\n"
743 542 );
744 543 break;
745 544 }
746 545 }
@@ -764,29 +563,30 @@
764 563 * wp jetpack options delete <option_name>
765 564 * wp jetpack options update <option_name> [<option_value>]
766 565 *
767 566 * @synopsis <list|get|delete|update> [<option_name>] [<option_value>]
768 - *
769 - * @param array $args Positional args.
770 567 */
771 - public function options( $args ) {
772 - $action = isset( $args[0] ) ? $args[0] : 'list';
568 + public function options( $args, $assoc_args ) {
569 + $action = isset( $args[0] ) ? $args[0] : 'list';
773 570 $safe_to_modify = Jetpack_Options::get_options_for_reset();
774 571
572 + // Jumpstart is special
573 + array_push( $safe_to_modify, 'jumpstart' );
574 +
775 575 // Is the option flagged as unsafe?
776 - $flagged = ! in_array( $args[1], $safe_to_modify, true );
576 + $flagged = ! in_array( $args[1], $safe_to_modify );
777 577
778 - if ( ! in_array( $action, array( 'list', 'get', 'delete', 'update' ), true ) ) {
578 + if ( ! in_array( $action, array( 'list', 'get', 'delete', 'update' ) ) ) {
779 579 /* translators: %s is a command like "prompt" */
780 580 WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
781 581 }
782 582
783 583 if ( isset( $args[0] ) ) {
784 - if ( 'get' === $args[0] && isset( $args[1] ) ) {
584 + if ( 'get' == $args[0] && isset( $args[1] ) ) {
785 585 $action = 'get';
786 - } elseif ( 'delete' === $args[0] && isset( $args[1] ) ) {
586 + } else if ( 'delete' == $args[0] && isset( $args[1] ) ) {
787 587 $action = 'delete';
788 - } elseif ( 'update' === $args[0] && isset( $args[1] ) ) {
588 + } else if ( 'update' == $args[0] && isset( $args[1] ) ) {
789 589 $action = 'update';
790 590 } else {
791 591 $action = 'list';
792 592 }
@@ -791,18 +591,17 @@
791 591 $action = 'list';
792 592 }
793 593 }
794 594
795 - // Bail if the option isn't found.
595 + // Bail if the option isn't found
796 596 $option = isset( $args[1] ) ? Jetpack_Options::get_option( $args[1] ) : false;
797 597 if ( isset( $args[1] ) && ! $option && 'update' !== $args[0] ) {
798 - WP_CLI::error( __( 'Option not found or is empty. Use "list" to list option names', 'jetpack' ) );
598 + WP_CLI::error( __( 'Option not found or is empty. Use "list" to list option names', 'jetpack' ) );
799 599 }
800 600
801 - // Let's print_r the option if it's an array.
802 - // Used in the 'get' and 'list' actions.
803 - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
804 - $option = is_array( $option ) ? print_r( $option, true ) : $option;
601 + // Let's print_r the option if it's an array
602 + // Used in the 'get' and 'list' actions
603 + $option = is_array( $option ) ? print_r( $option ) : $option;
805 604
806 605 switch ( $action ) {
807 606 case 'get':
808 607 WP_CLI::success( "\t" . $option );
@@ -810,9 +609,8 @@
810 609 case 'delete':
811 610 jetpack_cli_are_you_sure( $flagged );
812 611
813 612 Jetpack_Options::delete_option( $args[1] );
814 - /* translators: %s is the option name */
815 613 WP_CLI::success( sprintf( __( 'Deleted option: %s', 'jetpack' ), $args[1] ) );
816 614 break;
817 615 case 'update':
818 616 jetpack_cli_are_you_sure( $flagged );
@@ -823,10 +621,9 @@
823 621 WP_CLI::error( __( 'Sorry, no updating arrays at this time', 'jetpack' ) );
824 622 }
825 623
826 624 Jetpack_Options::update_option( $args[1], $args[2] );
827 - /* translators: %1$s is the previous value, %2$s is the new value */
828 - WP_CLI::success( sprintf( _x( 'Updated option: %1$s to "%2$s"', 'Updating an option from "this" to "that".', 'jetpack' ), $args[1], $args[2] ) );
625 + WP_CLI::success( sprintf( _x( 'Updated option: %s to "%s"', 'Updating an option from "this" to "that".', 'jetpack' ), $args[1], $args[2] ) );
829 626 break;
830 627 case 'list':
831 628 $options_compact = Jetpack_Options::get_option_names();
832 629 $options_non_compact = Jetpack_Options::get_option_names( 'non_compact' );
@@ -832,14 +629,14 @@
832 629 $options_non_compact = Jetpack_Options::get_option_names( 'non_compact' );
833 630 $options_private = Jetpack_Options::get_option_names( 'private' );
834 631 $options = array_merge( $options_compact, $options_non_compact, $options_private );
835 632
836 - // Table headers.
633 + // Table headers
837 634 WP_CLI::line( "\t" . str_pad( __( 'Option', 'jetpack' ), 30 ) . __( 'Value', 'jetpack' ) );
838 635
839 - // List out the options and their values.
840 - // Tell them if the value is empty or not.
841 - // Tell them if it's an array.
636 + // List out the options and their values
637 + // Tell them if the value is empty or not
638 + // Tell them if it's an array
842 639 foreach ( $options as $option ) {
843 640 $value = Jetpack_Options::get_option( $option );
844 641 if ( ! $value ) {
845 642 WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Empty' );
@@ -847,9 +644,9 @@
847 644 }
848 645
849 646 if ( ! is_array( $value ) ) {
850 647 WP_CLI::line( "\t" . str_pad( $option, 30 ) . $value );
851 - } elseif ( is_array( $value ) ) {
648 + } else if ( is_array( $value ) ) {
852 649 WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Array - Use "get <option>" to read option array.' );
853 650 }
854 651 }
855 652 $option_text = '{' . _x( 'option', 'a variable command that a user can write, provided in the printed instructions', 'jetpack' ) . '}';
@@ -856,11 +653,11 @@
856 653 $value_text = '{' . _x( 'value', 'the value that they want to update the option to', 'jetpack' ) . '}';
857 654
858 655 WP_CLI::success(
859 656 _x( "Above are your options. You may 'get', 'delete', and 'update' them.", "'get', 'delete', and 'update' are commands - do not translate.", 'jetpack' ) . "\n" .
860 - str_pad( 'wp jetpack options get', 26 ) . $option_text . "\n" .
657 + str_pad( 'wp jetpack options get', 26 ) . $option_text . "\n" .
861 658 str_pad( 'wp jetpack options delete', 26 ) . $option_text . "\n" .
862 - str_pad( 'wp jetpack options update', 26 ) . "$option_text $value_text\n" .
659 + str_pad( 'wp jetpack options update', 26 ) . "$option_text $value_text" . "\n" .
863 660 _x( "Type 'wp jetpack options' for more info.", "'wp jetpack options' is a command - do not translate.", 'jetpack' ) . "\n"
864 661 );
865 662 break;
866 663 }
@@ -870,150 +667,60 @@
870 667 * Get the status of or start a new Jetpack sync.
871 668 *
872 669 * ## OPTIONS
873 670 *
874 - * status : Print the current sync status
875 - * settings : Prints the current sync settings
876 - * start : Start a full sync from this site to WordPress.com
877 - * enable : Enables sync on the site
878 - * disable : Disable sync on a site
879 - * reset : Disables sync and Resets the sync queues on a site
671 + * status : Print the current sync status
672 + * start : Start a full sync from this site to WordPress.com
880 673 *
881 674 * ## EXAMPLES
882 675 *
883 676 * wp jetpack sync status
884 - * wp jetpack sync settings
885 677 * wp jetpack sync start --modules=functions --sync_wait_time=5
886 - * wp jetpack sync enable
887 - * wp jetpack sync disable
888 - * wp jetpack sync reset
889 - * wp jetpack sync reset --queue=full or regular
890 678 *
891 679 * @synopsis <status|start> [--<field>=<value>]
892 - *
893 - * @param array $args Positional args.
894 - * @param array $assoc_args Named args.
895 680 */
896 681 public function sync( $args, $assoc_args ) {
682 + if ( ! Jetpack_Sync_Actions::sync_allowed() ) {
683 + WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site.', 'jetpack' ) );
684 + }
897 685
898 686 $action = isset( $args[0] ) ? $args[0] : 'status';
899 687
900 688 switch ( $action ) {
901 689 case 'status':
902 - $status = Actions::get_sync_status();
690 + $status = Jetpack_Sync_Actions::get_sync_status();
903 691 $collection = array();
904 692 foreach ( $status as $key => $item ) {
905 - $collection[] = array(
693 + $collection[] = array(
906 694 'option' => $key,
907 - 'value' => is_scalar( $item ) ? $item : wp_json_encode( $item ),
695 + 'value' => is_scalar( $item ) ? $item : json_encode( $item )
908 696 );
909 697 }
910 - WP_CLI::log( __( 'Sync Status:', 'jetpack' ) );
698 +
911 699 WP_CLI\Utils\format_items( 'table', $collection, array( 'option', 'value' ) );
912 700 break;
913 - case 'settings':
914 - WP_CLI::log( __( 'Sync Settings:', 'jetpack' ) );
915 - $settings = array();
916 - foreach ( Settings::get_settings() as $setting => $item ) {
917 - $settings[] = array(
918 - 'setting' => $setting,
919 - 'value' => is_scalar( $item ) ? $item : wp_json_encode( $item ),
920 - );
921 - }
922 - WP_CLI\Utils\format_items( 'table', $settings, array( 'setting', 'value' ) );
923 - break;
924 - case 'disable':
925 - // Don't set it via the Settings since that also resets the queues.
926 - update_option( 'jetpack_sync_settings_disable', 1 );
927 - /* translators: %s is the site URL */
928 - WP_CLI::log( sprintf( __( 'Sync Disabled on %s', 'jetpack' ), get_site_url() ) );
929 - break;
930 - case 'enable':
931 - Settings::update_settings( array( 'disable' => 0 ) );
932 - /* translators: %s is the site URL */
933 - WP_CLI::log( sprintf( __( 'Sync Enabled on %s', 'jetpack' ), get_site_url() ) );
934 - break;
935 - case 'reset':
936 - // Don't set it via the Settings since that also resets the queues.
937 - update_option( 'jetpack_sync_settings_disable', 1 );
938 -
939 - /* translators: %s is the site URL */
940 - WP_CLI::log( sprintf( __( 'Sync Disabled on %s. Use `wp jetpack sync enable` to enable syncing again.', 'jetpack' ), get_site_url() ) );
941 - $listener = Listener::get_instance();
942 - if ( empty( $assoc_args['queue'] ) ) {
943 - $listener->get_sync_queue()->reset();
944 - $listener->get_full_sync_queue()->reset();
945 - /* translators: %s is the site URL */
946 - WP_CLI::log( sprintf( __( 'Reset Full Sync and Regular Queues Queue on %s', 'jetpack' ), get_site_url() ) );
947 - break;
948 - }
949 -
950 - if ( ! empty( $assoc_args['queue'] ) ) {
951 - switch ( $assoc_args['queue'] ) {
952 - case 'regular':
953 - $listener->get_sync_queue()->reset();
954 - /* translators: %s is the site URL */
955 - WP_CLI::log( sprintf( __( 'Reset Regular Sync Queue on %s', 'jetpack' ), get_site_url() ) );
956 - break;
957 - case 'full':
958 - $listener->get_full_sync_queue()->reset();
959 - /* translators: %s is the site URL */
960 - WP_CLI::log( sprintf( __( 'Reset Full Sync Queue on %s', 'jetpack' ), get_site_url() ) );
961 - break;
962 - default:
963 - WP_CLI::error( __( 'Please specify what type of queue do you want to reset: `full` or `regular`.', 'jetpack' ) );
964 - break;
965 - }
966 - }
967 -
968 - break;
969 701 case 'start':
970 - if ( ! Actions::sync_allowed() ) {
971 - if ( Settings::get_setting( 'disable' ) ) {
972 - WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site. It is currently disabled. Run `wp jetpack sync enable` to enable it.', 'jetpack' ) );
973 - return;
974 - }
975 - $connection = new Connection_Manager();
976 - if ( ! $connection->is_connected() ) {
977 - if ( ! doing_action( 'jetpack_site_registered' ) ) {
978 - WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site. Jetpack is not connected.', 'jetpack' ) );
979 - return;
980 - }
981 - }
702 + // Get the original settings so that we can restore them later
703 + $original_settings = Jetpack_Sync_Settings::get_settings();
982 704
983 - $status = new Status();
984 -
985 - if ( $status->is_offline_mode() ) {
986 - WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site. The site is in offline mode.', 'jetpack' ) );
987 - return;
988 - }
989 - if ( $status->in_safe_mode() ) {
990 - WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site. The site is in safe mode.', 'jetpack' ) );
991 - return;
992 - }
993 - }
994 - // Get the original settings so that we can restore them later.
995 - $original_settings = Settings::get_settings();
996 -
997 - // Initialize sync settigns so we can sync as quickly as possible.
705 + // Initialize sync settigns so we can sync as quickly as possible
998 706 $sync_settings = wp_parse_args(
999 - array_intersect_key( $assoc_args, Settings::$valid_settings ),
707 + array_intersect_key( $assoc_args, Jetpack_Sync_Settings::$valid_settings ),
1000 708 array(
1001 - 'sync_wait_time' => 0,
1002 - 'enqueue_wait_time' => 0,
1003 - 'queue_max_writes_sec' => 10000,
1004 - 'max_queue_size_full_sync' => 100000,
1005 - 'full_sync_send_duration' => HOUR_IN_SECONDS,
709 + 'sync_wait_time' => 0,
710 + 'enqueue_wait_time' => 0,
711 + 'queue_max_writes_sec' => 10000,
712 + 'max_queue_size_full_sync' => 100000
1006 713 )
1007 714 );
1008 - Settings::update_settings( $sync_settings );
715 + Jetpack_Sync_Settings::update_settings( $sync_settings );
1009 716
1010 - // Convert comma-delimited string of modules to an array.
717 + // Convert comma-delimited string of modules to an array
1011 718 if ( ! empty( $assoc_args['modules'] ) ) {
1012 719 $modules = array_map( 'trim', explode( ',', $assoc_args['modules'] ) );
1013 720
1014 721 // Convert the array so that the keys are the module name and the value is true to indicate
1015 - // that we want to sync the module.
722 + // that we want to sync the module
1016 723 $modules = array_map( '__return_true', array_flip( $modules ) );
1017 724 }
1018 725
1019 726 foreach ( array( 'posts', 'comments', 'users' ) as $module_name ) {
@@ -1021,12 +728,12 @@
1021 728 'users' === $module_name &&
1022 729 isset( $assoc_args[ $module_name ] ) &&
1023 730 'initial' === $assoc_args[ $module_name ]
1024 731 ) {
1025 - $modules['users'] = 'initial';
732 + $modules[ 'users' ] = 'initial';
1026 733 } elseif ( isset( $assoc_args[ $module_name ] ) ) {
1027 734 $ids = explode( ',', $assoc_args[ $module_name ] );
1028 - if ( $ids !== array() ) {
735 + if ( count( $ids ) > 0 ) {
1029 736 $modules[ $module_name ] = $ids;
1030 737 }
1031 738 }
1032 739 }
@@ -1034,13 +741,12 @@
1034 741 if ( empty( $modules ) ) {
1035 742 $modules = null;
1036 743 }
1037 744
1038 - // Kick off a full sync.
1039 - if ( Actions::do_full_sync( $modules ) ) {
745 + // Kick off a full sync
746 + if ( Jetpack_Sync_Actions::do_full_sync( $modules ) ) {
1040 747 if ( $modules ) {
1041 - /* translators: %s is a comma separated list of Jetpack modules */
1042 - WP_CLI::log( sprintf( __( 'Initialized a new full sync with modules: %s', 'jetpack' ), implode( ', ', array_keys( $modules ) ) ) );
748 + WP_CLI::log( sprintf( __( 'Initialized a new full sync with modules: %s', 'jetpack' ), join( ', ', array_keys( $modules ) ) ) );
1043 749 } else {
1044 750 WP_CLI::log( __( 'Initialized a new full sync', 'jetpack' ) );
1045 751 }
1046 752 } else {
@@ -1045,45 +751,38 @@
1045 751 }
1046 752 } else {
1047 753
1048 754 // Reset sync settings to original.
1049 - Settings::update_settings( $original_settings );
755 + Jetpack_Sync_Settings::update_settings( $original_settings );
1050 756
1051 757 if ( $modules ) {
1052 - /* translators: %s is a comma separated list of Jetpack modules */
1053 - WP_CLI::error( sprintf( __( 'Could not start a new full sync with modules: %s', 'jetpack' ), implode( ', ', $modules ) ) );
758 + WP_CLI::error( sprintf( __( 'Could not start a new full sync with modules: %s', 'jetpack' ), join( ', ', $modules ) ) );
1054 759 } else {
1055 760 WP_CLI::error( __( 'Could not start a new full sync', 'jetpack' ) );
1056 761 }
1057 762 }
1058 763
1059 - // Keep sending to WPCOM until there's nothing to send.
764 + // Keep sending to WPCOM until there's nothing to send
1060 765 $i = 1;
1061 766 do {
1062 - $result = Actions::$sender->do_full_sync();
767 + $result = Jetpack_Sync_Actions::$sender->do_full_sync();
1063 768 if ( is_wp_error( $result ) ) {
1064 - $queue_empty_error = ( 'empty_queue_full_sync' === $result->get_error_code() );
1065 - if ( ! $queue_empty_error || ( $queue_empty_error && ( 1 === $i ) ) ) {
1066 - /* translators: %s is an error code */
769 + $queue_empty_error = ( 'empty_queue_full_sync' == $result->get_error_code() );
770 + if ( ! $queue_empty_error || ( $queue_empty_error && ( 1 == $i ) ) ) {
1067 771 WP_CLI::error( sprintf( __( 'Sync errored with code: %s', 'jetpack' ), $result->get_error_code() ) );
1068 772 }
1069 773 } else {
1070 - if ( 1 === $i ) {
774 + if ( 1 == $i ) {
1071 775 WP_CLI::log( __( 'Sent data to WordPress.com', 'jetpack' ) );
1072 776 } else {
1073 777 WP_CLI::log( __( 'Sent more data to WordPress.com', 'jetpack' ) );
1074 778 }
1075 -
1076 - // Immediate Full Sync does not wait for WP.com to process data so we need to enforce a wait.
1077 - if ( Modules::get_module( 'full-sync' ) instanceof \Automattic\Jetpack\Sync\Modules\Full_Sync_Immediately ) {
1078 - sleep( 15 );
1079 - }
1080 779 }
1081 - ++$i;
780 + $i++;
1082 781 } while ( $result && ! is_wp_error( $result ) );
1083 782
1084 783 // Reset sync settings to original.
1085 - Settings::update_settings( $original_settings );
784 + Jetpack_Sync_Settings::update_settings( $original_settings );
1086 785
1087 786 WP_CLI::success( __( 'Finished syncing to WordPress.com', 'jetpack' ) );
1088 787 break;
1089 788 }
@@ -1100,42 +799,40 @@
1100 799 *
1101 800 * wp jetpack sync_queue full_sync peek
1102 801 *
1103 802 * @synopsis <incremental|full_sync> <peek>
1104 - *
1105 - * @param array $args Positional args.
1106 803 */
1107 - public function sync_queue( $args ) {
1108 - if ( ! Actions::sync_allowed() ) {
804 + public function sync_queue( $args, $assoc_args ) {
805 + if ( ! Jetpack_Sync_Actions::sync_allowed() ) {
1109 806 WP_CLI::error( __( 'Jetpack sync is not currently allowed for this site.', 'jetpack' ) );
1110 807 }
1111 808
1112 809 $queue_name = isset( $args[0] ) ? $args[0] : 'sync';
1113 - $action = isset( $args[1] ) ? $args[1] : 'peek';
810 + $action = isset( $args[1] ) ? $args[1] : 'peek';
1114 811
1115 812 // We map the queue name that way we can support more friendly queue names in the commands, but still use
1116 813 // the queue name that the code expects.
1117 - $allowed_queues = array(
814 + $queue_name_map = $allowed_queues = array(
1118 815 'incremental' => 'sync',
1119 816 'full' => 'full_sync',
1120 817 );
1121 - $queue_name_map = $allowed_queues;
1122 818 $mapped_queue_name = isset( $queue_name_map[ $queue_name ] ) ? $queue_name_map[ $queue_name ] : $queue_name;
1123 819
1124 - switch ( $action ) {
820 + switch( $action ) {
1125 821 case 'peek':
1126 - $queue = new Queue( $mapped_queue_name );
822 + require_once JETPACK__PLUGIN_DIR . 'sync/class.jetpack-sync-queue.php';
823 + $queue = new Jetpack_Sync_Queue( $mapped_queue_name );
1127 824 $items = $queue->peek( 100 );
1128 825
1129 826 if ( empty( $items ) ) {
1130 827 /* translators: %s is the name of the queue, either 'incremental' or 'full' */
1131 - WP_CLI::log( sprintf( __( 'Nothing is in the queue: %s', 'jetpack' ), $queue_name ) );
828 + WP_CLI::log( sprintf( __( 'Nothing is in the queue: %s', 'jetpack' ), $queue_name ) );
1132 829 } else {
1133 830 $collection = array();
1134 831 foreach ( $items as $item ) {
1135 832 $collection[] = array(
1136 833 'action' => $item[0],
1137 - 'args' => wp_json_encode( $item[1] ),
834 + 'args' => json_encode( $item[1] ),
1138 835 'current_user_id' => $item[2],
1139 836 'microtime' => $item[3],
1140 837 'importing' => (string) $item[4],
1141 838 );
@@ -1165,20 +862,15 @@
1165 862 * : JSON blob of WPCOM API token
1166 863 * [--partner_tracking_id=<partner_tracking_id>]
1167 864 * : This is an optional ID that a host can pass to help identify a site in logs on WordPress.com
1168 865 *
1169 - * @synopsis <token_json> [--partner_tracking_id=<partner_tracking_id>]
1170 - *
1171 - * @param array $args Positional args.
1172 - * @param array $named_args Named args.
866 + * * @synopsis <token_json> [--partner_tracking_id=<partner_tracking_id>]
1173 867 */
1174 868 public function partner_cancel( $args, $named_args ) {
1175 869 list( $token_json ) = $args;
1176 870
1177 - $token = $token_json ? json_decode( $token_json ) : null;
1178 - if ( ! $token ) {
1179 - /* translators: %s is the invalid JSON string */
1180 - $this->partner_provision_error( new WP_Error( 'missing_access_token', sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
871 + if ( ! $token_json || ! ( $token = json_decode( $token_json ) ) ) {
872 + $this->partner_provision_error( new WP_Error( 'missing_access_token', sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
1181 873 }
1182 874
1183 875 if ( isset( $token->error ) ) {
1184 876 $this->partner_provision_error( new WP_Error( $token->error, $token->message ) );
@@ -1187,27 +879,24 @@
1187 879 if ( ! isset( $token->access_token ) ) {
1188 880 $this->partner_provision_error( new WP_Error( 'missing_access_token', __( 'Missing or invalid access token', 'jetpack' ) ) );
1189 881 }
1190 882
1191 - if ( Identity_Crisis::validate_sync_error_idc_option() ) {
1192 - $this->partner_provision_error(
1193 - new WP_Error(
1194 - 'site_in_safe_mode',
1195 - esc_html__( 'Can not cancel a plan while in safe mode. See: https://jetpack.com/support/safe-mode/', 'jetpack' )
1196 - )
1197 - );
883 + if ( Jetpack::validate_sync_error_idc_option() ) {
884 + $this->partner_provision_error( new WP_Error(
885 + 'site_in_safe_mode',
886 + esc_html__( 'Can not cancel a plan while in safe mode. See: https://jetpack.com/support/safe-mode/', 'jetpack' )
887 + ) );
1198 888 }
1199 889
1200 890 $site_identifier = Jetpack_Options::get_option( 'id' );
1201 891
1202 892 if ( ! $site_identifier ) {
1203 - $status = new Status();
1204 - $site_identifier = $status->get_site_suffix();
893 + $site_identifier = Jetpack::build_raw_urls( get_home_url() );
1205 894 }
1206 895
1207 896 $request = array(
1208 897 'headers' => array(
1209 - 'Authorization' => 'Bearer ' . $token->access_token,
898 + 'Authorization' => "Bearer " . $token->access_token,
1210 899 'Host' => 'public-api.wordpress.com',
1211 900 ),
1212 901 'timeout' => 60,
1213 902 'method' => 'POST',
@@ -1212,14 +901,14 @@
1212 901 'timeout' => 60,
1213 902 'method' => 'POST',
1214 903 );
1215 904
1216 - $url = sprintf( '%s/rest/v1.3/jpphp/%s/partner-cancel', $this->get_api_host(), $site_identifier );
905 + $url = sprintf( 'https://%s/rest/v1.3/jpphp/%s/partner-cancel', $this->get_api_host(), $site_identifier );
1217 906 if ( ! empty( $named_args ) && ! empty( $named_args['partner_tracking_id'] ) ) {
1218 907 $url = esc_url_raw( add_query_arg( 'partner_tracking_id', $named_args['partner_tracking_id'], $url ) );
1219 908 }
1220 909
1221 - $result = Client::_wp_remote_request( $url, $request );
910 + $result = Jetpack_Client::_wp_remote_request( $url, $request );
1222 911
1223 912 Jetpack_Options::delete_option( 'onboarding' );
1224 913
1225 914 if ( is_wp_error( $result ) ) {
@@ -1262,19 +951,14 @@
1262 951 * $ wp jetpack partner_provision '{ some: "json" }' premium 1
1263 952 * { success: true }
1264 953 *
1265 954 * @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>]
1266 - *
1267 - * @param array $args Positional args.
1268 - * @param array $named_args Named args.
1269 955 */
1270 956 public function partner_provision( $args, $named_args ) {
1271 957 list( $token_json ) = $args;
1272 958
1273 - $token = $token_json ? json_decode( $token_json ) : null;
1274 - if ( ! $token ) {
1275 - /* translators: %s is the invalid JSON string */
1276 - $this->partner_provision_error( new WP_Error( 'missing_access_token', sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
959 + if ( ! $token_json || ! ( $token = json_decode( $token_json ) ) ) {
960 + $this->partner_provision_error( new WP_Error( 'missing_access_token', sprintf( __( 'Invalid token JSON: %s', 'jetpack' ), $token_json ) ) );
1277 961 }
1278 962
1279 963 if ( isset( $token->error ) ) {
1280 964 $message = isset( $token->message )
@@ -1291,21 +975,17 @@
1291 975
1292 976 $body_json = Jetpack_Provision::partner_provision( $token->access_token, $named_args );
1293 977
1294 978 if ( is_wp_error( $body_json ) ) {
1295 - WP_CLI::error(
1296 - wp_json_encode(
1297 - array(
1298 - 'success' => false,
1299 - 'error_code' => $body_json->get_error_code(),
1300 - 'error_message' => $body_json->get_error_message(),
1301 - )
1302 - )
1303 - );
979 + error_log( json_encode( array(
980 + 'success' => false,
981 + 'error_code' => $body_json->get_error_code(),
982 + 'error_message' => $body_json->get_error_message()
983 + ) ) );
1304 984 exit( 1 );
1305 985 }
1306 986
1307 - WP_CLI::log( wp_json_encode( $body_json ) );
987 + WP_CLI::log( json_encode( $body_json ) );
1308 988 }
1309 989
1310 990 /**
1311 991 * Manages your Jetpack sitemap
@@ -1320,14 +1000,11 @@
1320 1000 * wp jetpack sitemap rebuild
1321 1001 *
1322 1002 * @subcommand sitemap
1323 1003 * @synopsis <rebuild> [--purge]
1324 - *
1325 - * @param array $args Positional args.
1326 - * @param array $assoc_args Named args.
1327 1004 */
1328 1005 public function sitemap( $args, $assoc_args ) {
1329 - if ( ! Jetpack::is_connection_ready() ) {
1006 + if ( ! Jetpack::is_active() ) {
1330 1007 WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
1331 1008 }
1332 1009 if ( ! Jetpack::is_module_active( 'sitemaps' ) ) {
1333 1010 WP_CLI::error( __( 'Jetpack Sitemaps module is not currently active. Activate it first if you want to work with sitemaps.', 'jetpack' ) );
@@ -1352,11 +1029,8 @@
1352 1029 *
1353 1030 * wp jetpack authorize_user --token=123456789abcdef
1354 1031 *
1355 1032 * @synopsis --token=<value>
1356 - *
1357 - * @param array $args Positional args.
1358 - * @param array $named_args Named args.
1359 1033 */
1360 1034 public function authorize_user( $args, $named_args ) {
1361 1035 if ( ! is_user_logged_in() ) {
1362 1036 WP_CLI::error( __( 'Please select a user to authorize via the --user global argument.', 'jetpack' ) );
@@ -1365,16 +1039,16 @@
1365 1039 if ( empty( $named_args['token'] ) ) {
1366 1040 WP_CLI::error( __( 'A non-empty token argument must be passed.', 'jetpack' ) );
1367 1041 }
1368 1042
1369 - $is_connection_owner = ! Jetpack::connection()->has_connected_owner();
1370 - $current_user_id = get_current_user_id();
1043 + $is_master_user = ! Jetpack::is_active();
1044 + $current_user_id = get_current_user_id();
1371 1045
1372 - ( new Tokens() )->update_user_token( $current_user_id, sprintf( '%s.%d', $named_args['token'], $current_user_id ), $is_connection_owner );
1046 + Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $named_args['token'], $current_user_id ), $is_master_user );
1373 1047
1374 1048 WP_CLI::log( wp_json_encode( $named_args ) );
1375 1049
1376 - if ( $is_connection_owner ) {
1050 + if ( $is_master_user ) {
1377 1051 /**
1378 1052 * Auto-enable SSO module for new Jetpack Start connections
1379 1053 *
1380 1054 * @since 5.0.0
@@ -1422,14 +1096,11 @@
1422 1096 *
1423 1097 * ## EXAMPLES
1424 1098 *
1425 1099 * wp jetpack call_api --resource='/sites/%d'
1426 - *
1427 - * @param array $args Positional args.
1428 - * @param array $named_args Named args.
1429 1100 */
1430 1101 public function call_api( $args, $named_args ) {
1431 - if ( ! Jetpack::is_connection_ready() ) {
1102 + if ( ! Jetpack::is_active() ) {
1432 1103 WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
1433 1104 }
1434 1105
1435 1106 $consumed_args = array(
@@ -1443,44 +1114,40 @@
1443 1114 // Get args that should be passed to resource.
1444 1115 $other_args = array_diff_key( $named_args, array_flip( $consumed_args ) );
1445 1116
1446 1117 $decoded_body = ! empty( $named_args['body'] )
1447 - ? json_decode( $named_args['body'], true )
1118 + ? json_decode( $named_args['body'] )
1448 1119 : false;
1449 1120
1450 - $resource_url = ( ! str_contains( $named_args['resource'], '%d' ) )
1121 + $resource_url = ( false === strpos( $named_args['resource'], '%d' ) )
1451 1122 ? $named_args['resource']
1452 1123 : sprintf( $named_args['resource'], Jetpack_Options::get_option( 'id' ) );
1453 1124
1454 - $response = Client::wpcom_json_api_request_as_blog(
1125 + $response = Jetpack_Client::wpcom_json_api_request_as_blog(
1455 1126 $resource_url,
1456 - empty( $named_args['api_version'] ) ? Client::WPCOM_JSON_API_VERSION : $named_args['api_version'],
1127 + empty( $named_args['api_version'] ) ? Jetpack_Client::WPCOM_JSON_API_VERSION : $named_args['api_version'],
1457 1128 $other_args,
1458 1129 empty( $decoded_body ) ? null : $decoded_body,
1459 - empty( $named_args['base_api_path'] ) ? 'rest' : $named_args['base_api_path']
1130 + $named_args['base_api_path']
1460 1131 );
1461 1132
1462 1133 if ( is_wp_error( $response ) ) {
1463 - WP_CLI::error(
1464 - sprintf(
1465 - /* translators: %1$s is an endpoint route (ex. /sites/123456), %2$d is an error code, %3$s is an error message. */
1466 - __( 'Request to %1$s returned an error: (%2$d) %3$s.', 'jetpack' ),
1467 - $resource_url,
1468 - $response->get_error_code(),
1469 - $response->get_error_message()
1470 - )
1471 - );
1134 + WP_CLI::error( sprintf(
1135 + /* translators: %1$s is an endpoint route (ex. /sites/123456), %2$d is an error code, %3$s is an error message. */
1136 + __( 'Request to %1$s returned an error: (%2$d) %3$s.', 'jetpack' ),
1137 + $resource_url,
1138 + $response->get_error_code(),
1139 + $response->get_error_message()
1140 + ) );
1472 1141 }
1473 1142
1474 1143 if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
1475 - WP_CLI::error(
1476 - sprintf(
1477 - /* translators: %1$s is an endpoint route (ex. /sites/123456), %2$d is an HTTP status code. */
1478 - __( 'Request to %1$s returned a non-200 response code: %2$d.', 'jetpack' ),
1479 - $resource_url,
1480 - wp_remote_retrieve_response_code( $response )
1481 - )
1482 - );
1144 + WP_CLI::error( sprintf(
1145 + /* translators: %1$s is an endpoint route (ex. /sites/123456), %2$d is an HTTP status code. */
1146 + __( 'Request to %1$s returned a non-200 response code: %2$d.', 'jetpack' ),
1147 + $resource_url,
1148 + wp_remote_retrieve_response_code( $response )
1149 + ) );
1483 1150 }
1484 1151
1485 1152 $output = wp_remote_retrieve_body( $response );
1486 1153 if ( isset( $named_args['pretty'] ) ) {
@@ -1498,93 +1165,8 @@
1498 1165 WP_CLI::success( $output );
1499 1166 }
1500 1167
1501 1168 /**
1502 - * Allows uploading SSH Credentials to the current site for backups, restores, and security scanning.
1503 - *
1504 - * ## OPTIONS
1505 - *
1506 - * [--host=<host>]
1507 - * : The SSH server's address.
1508 - *
1509 - * [--ssh-user=<user>]
1510 - * : The username to use to log in to the SSH server.
1511 - *
1512 - * [--pass=<pass>]
1513 - * : The password used to log in, if using a password. (optional)
1514 - *
1515 - * [--kpri=<kpri>]
1516 - * : The private key used to log in, if using a private key. (optional)
1517 - *
1518 - * [--pretty]
1519 - * : Will pretty print the results of a successful API call. (optional)
1520 - *
1521 - * [--strip-success]
1522 - * : Will remove the green success label from successful API calls. (optional)
1523 - *
1524 - * ## EXAMPLES
1525 - *
1526 - * wp jetpack upload_ssh_creds --host=example.com --ssh-user=example --pass=password
1527 - * wp jetpack updload_ssh_creds --host=example.com --ssh-user=example --kpri=key
1528 - *
1529 - * @param array $args Positional args.
1530 - * @param array $named_args Named args.
1531 - */
1532 - public function upload_ssh_creds( $args, $named_args ) {
1533 - if ( ! Jetpack::is_connection_ready() ) {
1534 - WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
1535 - }
1536 -
1537 - $required_args = array(
1538 - 'host',
1539 - 'ssh-user',
1540 - );
1541 -
1542 - foreach ( $required_args as $arg ) {
1543 - if ( empty( $named_args[ $arg ] ) ) {
1544 - WP_CLI::error(
1545 - sprintf(
1546 - /* translators: %s is a slug, such as 'host'. */
1547 - __( '`%s` cannot be empty.', 'jetpack' ),
1548 - $arg
1549 - )
1550 - );
1551 - }
1552 - }
1553 -
1554 - if ( empty( $named_args['pass'] ) && empty( $named_args['kpri'] ) ) {
1555 - WP_CLI::error( __( 'Both `pass` and `kpri` fields cannot be blank.', 'jetpack' ) );
1556 - }
1557 -
1558 - $values = array(
1559 - 'credentials' => array(
1560 - 'site_url' => get_site_url(),
1561 - 'abspath' => ABSPATH,
1562 - 'protocol' => 'ssh',
1563 - 'port' => 22,
1564 - 'role' => 'main',
1565 - 'host' => $named_args['host'],
1566 - 'user' => $named_args['ssh-user'],
1567 - 'pass' => empty( $named_args['pass'] ) ? '' : $named_args['pass'],
1568 - 'kpri' => empty( $named_args['kpri'] ) ? '' : $named_args['kpri'],
1569 - ),
1570 - );
1571 -
1572 - $named_args = wp_parse_args(
1573 - array(
1574 - 'resource' => '/activity-log/%d/update-credentials',
1575 - 'method' => 'POST',
1576 - 'api_version' => '1.1',
1577 - 'body' => wp_json_encode( $values ),
1578 - 'timeout' => 30,
1579 - ),
1580 - $named_args
1581 - );
1582 -
1583 - self::call_api( $args, $named_args );
1584 - }
1585 -
1586 - /**
1587 1169 * API wrapper for getting stats from the WordPress.com API for the current site.
1588 1170 *
1589 1171 * ## OPTIONS
1590 1172 *
@@ -1616,21 +1198,16 @@
1616 1198 *
1617 1199 * ## EXAMPLES
1618 1200 *
1619 1201 * wp jetpack get_stats
1620 - *
1621 - * @param array $args Positional args.
1622 - * @param array $named_args Named args.
1623 1202 */
1624 1203 public function get_stats( $args, $named_args ) {
1625 1204 $selected_args = array_intersect_key(
1626 1205 $named_args,
1627 - array_flip(
1628 - array(
1629 - 'quantity',
1630 - 'date',
1631 - )
1632 - )
1206 + array_flip( array(
1207 + 'quantity',
1208 + 'date',
1209 + ) )
1633 1210 );
1634 1211
1635 1212 // The API expects unit, but period seems to be more correct.
1636 1213 $selected_args['unit'] = $named_args['period'];
@@ -1691,15 +1268,15 @@
1691 1268 * # List all publicize connections.
1692 1269 * $ wp jetpack publicize list
1693 1270 *
1694 1271 * # List publicize connections for a given service.
1695 - * $ wp jetpack publicize list linkedin
1272 + * $ wp jetpack publicize list twitter
1696 1273 *
1697 1274 * # List all publicize connections for a given user.
1698 1275 * $ wp --user=1 jetpack publicize list
1699 1276 *
1700 1277 * # List all publicize connections for a given user and service.
1701 - * $ wp --user=1 jetpack publicize list linkedin
1278 + * $ wp --user=1 jetpack publicize list twitter
1702 1279 *
1703 1280 * # Display details for a given connection.
1704 1281 * $ wp jetpack publicize list 123456
1705 1282 *
@@ -1709,37 +1286,33 @@
1709 1286 * # Disconnect all connections.
1710 1287 * $ wp jetpack publicize disconnect all
1711 1288 *
1712 1289 * # Disconnect all connections for a given service.
1713 - * $ wp jetpack publicize disconnect linkedin
1714 - *
1715 - * @param array $args Positional args.
1716 - * @param array $named_args Named args.
1290 + * $ wp jetpack publicize disconnect twitter
1717 1291 */
1718 1292 public function publicize( $args, $named_args ) {
1719 - if ( ! Jetpack::connection()->has_connected_owner() ) {
1720 - WP_CLI::error( __( 'Jetpack Social requires a user-level connection to WordPress.com', 'jetpack' ) );
1293 + if ( ! Jetpack::is_active() ) {
1294 + WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
1721 1295 }
1722 1296
1723 1297 if ( ! Jetpack::is_module_active( 'publicize' ) ) {
1724 - WP_CLI::error( __( 'The Jetpack Social module is not active.', 'jetpack' ) );
1298 + WP_CLI::error( __( 'The publicize module is not active.', 'jetpack' ) );
1725 1299 }
1726 1300
1727 - if ( ( new Status() )->is_offline_mode() ) {
1301 + if ( Jetpack::is_development_mode() ) {
1728 1302 if (
1729 1303 ! defined( 'JETPACK_DEV_DEBUG' ) &&
1730 1304 ! has_filter( 'jetpack_development_mode' ) &&
1731 - ! has_filter( 'jetpack_offline_mode' ) &&
1732 - ! str_contains( site_url(), '.' )
1305 + false === strpos( site_url(), '.' )
1733 1306 ) {
1734 - WP_CLI::error( __( "Jetpack is current in offline mode because the site url does not contain a '.', which often occurs when dynamically setting the WP_SITEURL constant. While in offline mode, the Jetpack Social module will not load.", 'jetpack' ) );
1307 + WP_CLI::error( __( "Jetpack is current in development mode because the site url does not contain a '.', which often occurs when dynamically setting the WP_SITEURL constant. While in development mode, the publicize module will not load.", 'jetpack' ) );
1735 1308 }
1736 1309
1737 - WP_CLI::error( __( 'Jetpack is currently in offline mode, so the Jetpack Social module will not load.', 'jetpack' ) );
1310 + WP_CLI::error( __( 'Jetpack is currently in development mode, so the publicize module will not load.', 'jetpack' ) );
1738 1311 }
1739 1312
1740 - if ( ! class_exists( Publicize::class ) ) {
1741 - WP_CLI::error( __( 'The Jetpack Social module is not loaded.', 'jetpack' ) );
1313 + if ( ! class_exists( 'Publicize' ) ) {
1314 + WP_CLI::error( __( 'The publicize module is not loaded.', 'jetpack' ) );
1742 1315 }
1743 1316
1744 1317 $action = $args[0];
1745 1318 $publicize = new Publicize();
@@ -1822,12 +1395,12 @@
1822 1395 // If the connection ID is 'all' then delete all connections. If the connection ID
1823 1396 // matches a service, delete all connections for that service.
1824 1397 if ( 'all' === $identifier || $id_is_service ) {
1825 1398 if ( 'all' === $identifier ) {
1826 - WP_CLI::log( __( "You're about to delete all Jetpack Social connections.", 'jetpack' ) );
1399 + WP_CLI::log( __( "You're about to delete all publicize connections.", 'jetpack' ) );
1827 1400 } else {
1828 1401 /* translators: %s is a lowercase string for a social network. */
1829 - WP_CLI::log( sprintf( __( "You're about to delete all Jetpack Social connections to %s.", 'jetpack' ), $identifier ) );
1402 + WP_CLI::log( sprintf( __( "You're about to delete all publicize connections to %s.", 'jetpack' ), $identifier ) );
1830 1403 }
1831 1404
1832 1405 jetpack_cli_are_you_sure();
1833 1406
@@ -1848,9 +1421,9 @@
1848 1421 $connections = $option_connections[ $service ];
1849 1422 }
1850 1423
1851 1424 if ( ! empty( $connections ) ) {
1852 - $count = is_countable( $connections ) ? count( $connections ) : 0;
1425 + $count = count( $connections );
1853 1426 $progress = \WP_CLI\Utils\make_progress_bar(
1854 1427 /* translators: %s is a lowercase string for a social network. */
1855 1428 sprintf( __( 'Disconnecting all connections to %s.', 'jetpack' ), $service ),
1856 1429 $count
@@ -1857,312 +1430,68 @@
1857 1430 );
1858 1431
1859 1432 foreach ( $connections as $id => $connection ) {
1860 1433 if ( false === $publicize->disconnect( false, $id ) ) {
1861 - WP_CLI::error(
1862 - sprintf(
1863 - /* translators: %1$d is a numeric ID and %2$s is a lowercase string for a social network. */
1864 - __( 'Jetpack Social connection %d could not be disconnected', 'jetpack' ),
1865 - $id
1866 - )
1867 - );
1434 + WP_CLI::error( sprintf(
1435 + /* translators: %1$d is a numeric ID and %2$s is a lowercase string for a social network. */
1436 + __( 'Publicize connection %d could not be disconnected', 'jetpack' ),
1437 + $id
1438 + ) );
1868 1439 }
1869 1440
1870 - // @phan-suppress-next-line PhanUndeclaredClassMethod - Class is missing from php-stubs/wp-cli-stubs 🤷
1871 1441 $progress->tick();
1872 1442 }
1873 1443
1874 - // @phan-suppress-next-line PhanUndeclaredClassMethod - Class is missing from php-stubs/wp-cli-stubs 🤷
1875 1444 $progress->finish();
1876 1445
1877 1446 if ( 'all' === $service ) {
1878 - WP_CLI::success( __( 'All Jetpack Social connections were successfully disconnected.', 'jetpack' ) );
1447 + WP_CLI::success( __( 'All publicize connections were successfully disconnected.', 'jetpack' ) );
1879 1448 } else {
1880 1449 /* translators: %s is a lowercase string for a social network. */
1881 - WP_CLI::success( __( 'All Jetpack Social connections to %s were successfully disconnected.', 'jetpack' ), $service );
1450 + WP_CLI::success( __( 'All publicize connections to %s were successfully disconnected.', 'jetpack' ), $service );
1882 1451 }
1883 1452 }
1884 - } elseif ( false !== $publicize->disconnect( false, $identifier ) ) {
1885 - /* translators: %d is a numeric ID. Example: 1234. */
1886 - WP_CLI::success( sprintf( __( 'Jetpack Social connection %d has been disconnected.', 'jetpack' ), $identifier ) );
1887 1453 } else {
1888 - /* translators: %d is a numeric ID. Example: 1234. */
1889 - WP_CLI::error( sprintf( __( 'Jetpack Social connection %d could not be disconnected.', 'jetpack' ), $identifier ) );
1454 + if ( false !== $publicize->disconnect( false, $identifier ) ) {
1455 + /* translators: %d is a numeric ID. Example: 1234. */
1456 + WP_CLI::success( sprintf( __( 'Publicize connection %d has been disconnected.', 'jetpack' ), $identifier ) );
1457 + } else {
1458 + /* translators: %d is a numeric ID. Example: 1234. */
1459 + WP_CLI::error( sprintf( __( 'Publicize connection %d could not be disconnected.', 'jetpack' ), $identifier ) );
1460 + }
1890 1461 }
1891 1462 break; // disconnect.
1892 1463 }
1893 1464 }
1894 1465
1895 - /**
1896 - * Get the API host.
1897 - *
1898 - * @return string URL.
1899 - */
1900 1466 private function get_api_host() {
1901 1467 $env_api_host = getenv( 'JETPACK_START_API_HOST', true );
1902 - return $env_api_host ? 'https://' . $env_api_host : JETPACK__WPCOM_JSON_API_BASE;
1468 + return $env_api_host ? $env_api_host : JETPACK__WPCOM_JSON_API_HOST;
1903 1469 }
1904 1470
1905 - /**
1906 - * Log and exit on a partner provision error.
1907 - *
1908 - * @param WP_Error $error Error.
1909 - * @return never
1910 - */
1911 1471 private function partner_provision_error( $error ) {
1912 - WP_CLI::log(
1913 - wp_json_encode(
1914 - array(
1915 - 'success' => false,
1916 - 'error_code' => $error->get_error_code(),
1917 - 'error_message' => $error->get_error_message(),
1918 - )
1919 - )
1920 - );
1472 + WP_CLI::log( json_encode( array(
1473 + 'success' => false,
1474 + 'error_code' => $error->get_error_code(),
1475 + 'error_message' => $error->get_error_message()
1476 + ) ) );
1921 1477 exit( 1 );
1922 1478 }
1923 -
1924 - /**
1925 - * Creates the essential files in Jetpack to start building a Gutenberg block or plugin.
1926 - *
1927 - * ## TYPES
1928 - *
1929 - * block: it creates a Jetpack block. All files will be created in a directory under extensions/blocks named based on the block title or a specific given slug.
1930 - *
1931 - * ## BLOCK TYPE OPTIONS
1932 - *
1933 - * The first parameter is the block title and it's not associative. Add it wrapped in quotes.
1934 - * The title is also used to create the slug and the edit PHP class name. If it's something like "Logo gallery", the slug will be 'logo-gallery' and the class name will be LogoGalleryEdit.
1935 - * --slug: Specific slug to identify the block that overrides the one generated based on the title.
1936 - * --description: Allows to provide a text description of the block.
1937 - * --keywords: Provide up to three keywords separated by comma so users can find this block when they search in Gutenberg's inserter.
1938 - * --variation: Allows to decide whether the block should be a production block, experimental, or beta. Defaults to Beta when arg not provided.
1939 - *
1940 - * ## BLOCK TYPE EXAMPLES
1941 - *
1942 - * wp jetpack scaffold block "Cool Block"
1943 - * wp jetpack scaffold block "Amazing Rock" --slug="good-music" --description="Rock the best music on your site"
1944 - * wp jetpack scaffold block "Jukebox" --keywords="music, audio, media"
1945 - * wp jetpack scaffold block "Jukebox" --variation="experimental"
1946 - *
1947 - * @subcommand scaffold block
1948 - * @synopsis <type> <title> [--slug] [--description] [--keywords] [--variation]
1949 - *
1950 - * @param array $args Positional parameters, when strings are passed, wrap them in quotes.
1951 - * @param array $assoc_args Associative parameters like --slug="nice-block".
1952 - */
1953 - public function scaffold( $args, $assoc_args ) {
1954 - // It's ok not to check if it's set, because otherwise WPCLI exits earlier.
1955 - switch ( $args[0] ) {
1956 - case 'block':
1957 - $this->block( $args, $assoc_args );
1958 - break;
1959 - default:
1960 - /* translators: %s is the subcommand */
1961 - WP_CLI::error( sprintf( esc_html__( 'Invalid subcommand %s.', 'jetpack' ), $args[0] ) . ' 👻' );
1962 - exit( 1 );
1963 - }
1964 - }
1965 -
1966 - /**
1967 - * Creates the essential files in Jetpack to build a Gutenberg block.
1968 - *
1969 - * @param array $args Positional parameters. Only one is used, that corresponds to the block title.
1970 - * @param array $assoc_args Associative parameters defined in the scaffold() method.
1971 - */
1972 - public function block( $args, $assoc_args ) {
1973 - if ( isset( $args[1] ) ) {
1974 - $title = ucwords( $args[1] );
1975 - } else {
1976 - WP_CLI::error( esc_html__( 'The title parameter is required.', 'jetpack' ) . ' 👻' );
1977 - exit( 1 );
1978 - }
1979 -
1980 - $slug = isset( $assoc_args['slug'] )
1981 - ? $assoc_args['slug']
1982 - : sanitize_title( $title );
1983 -
1984 - $next_version = "\x24\x24next-version$$"; // Escapes to hide the string from tools/replace-next-version-tag.sh
1985 -
1986 - $variation_options = array( 'production', 'experimental', 'beta' );
1987 - $variation = ( isset( $assoc_args['variation'] ) && in_array( $assoc_args['variation'], $variation_options, true ) )
1988 - ? $assoc_args['variation']
1989 - : 'beta';
1990 -
1991 - if ( preg_match( '#^jetpack/#', $slug ) ) {
1992 - $slug = preg_replace( '#^jetpack/#', '', $slug );
1993 - }
1994 -
1995 - if ( ! preg_match( '/^[a-z][a-z0-9\-]*$/', $slug ) ) {
1996 - WP_CLI::error( esc_html__( 'Invalid block slug. They can contain only lowercase alphanumeric characters or dashes, and start with a letter', 'jetpack' ) . ' 👻' );
1997 - }
1998 -
1999 - global $wp_filesystem;
2000 - if ( ! WP_Filesystem() ) {
2001 - WP_CLI::error( esc_html__( "Can't write files", 'jetpack' ) . ' 😱' );
2002 - }
2003 -
2004 - $path = JETPACK__PLUGIN_DIR . "extensions/blocks/$slug";
2005 -
2006 - if ( $wp_filesystem->exists( $path ) && $wp_filesystem->is_dir( $path ) ) {
2007 - /* translators: %s is path to the conflicting block */
2008 - WP_CLI::error( sprintf( esc_html__( 'Name conflicts with the existing block %s', 'jetpack' ), $path ) . ' ⛔️' );
2009 - exit( 1 );
2010 - }
2011 -
2012 - $wp_filesystem->mkdir( $path );
2013 -
2014 - $keywords = isset( $assoc_args['keywords'] )
2015 - ? array_map(
2016 - function ( $keyword ) {
2017 - return trim( $keyword );
2018 - },
2019 - array_slice( explode( ',', $assoc_args['keywords'] ), 0, 3 )
2020 - )
2021 - : array();
2022 -
2023 - $files = array(
2024 - "$path/block.json" => self::render_block_file(
2025 - 'block-block-json',
2026 - array(
2027 - 'slug' => $slug,
2028 - 'title' => wp_json_encode( $title, JSON_UNESCAPED_UNICODE ),
2029 - 'description' => isset( $assoc_args['description'] )
2030 - ? wp_json_encode( $assoc_args['description'], JSON_UNESCAPED_UNICODE )
2031 - : wp_json_encode( $title, JSON_UNESCAPED_UNICODE ),
2032 - 'nextVersion' => $next_version,
2033 - 'keywords' => wp_json_encode( $keywords, JSON_UNESCAPED_UNICODE ),
2034 - )
2035 - ),
2036 - "$path/$slug.php" => self::render_block_file(
2037 - 'block-register-php',
2038 - array(
2039 - 'nextVersion' => $next_version,
2040 - 'title' => $title,
2041 - 'underscoredTitle' => str_replace( ' ', '_', $title ),
2042 - )
2043 - ),
2044 - "$path/editor.js" => self::render_block_file( 'block-editor-js' ),
2045 - "$path/editor.scss" => self::render_block_file(
2046 - 'block-editor-scss',
2047 - array(
2048 - 'slug' => $slug,
2049 - 'title' => $title,
2050 - )
2051 - ),
2052 - "$path/edit.js" => self::render_block_file(
2053 - 'block-edit-js',
2054 - array(
2055 - 'title' => $title,
2056 - 'className' => str_replace( ' ', '', ucwords( str_replace( '-', ' ', $slug ) ) ),
2057 - )
2058 - ),
2059 - );
2060 -
2061 - $files_written = array();
2062 -
2063 - foreach ( $files as $filename => $contents ) {
2064 - if ( $wp_filesystem->put_contents( $filename, $contents ) ) {
2065 - $files_written[] = $filename;
2066 - } else {
2067 - /* translators: %s is a file name */
2068 - WP_CLI::error( sprintf( esc_html__( 'Error creating %s', 'jetpack' ), $filename ) );
2069 - }
2070 - }
2071 -
2072 - if ( empty( $files_written ) ) {
2073 - WP_CLI::log( esc_html__( 'No files were created', 'jetpack' ) );
2074 - } else {
2075 - // Load index.json and insert the slug of the new block in its block variation array.
2076 - $block_list_path = JETPACK__PLUGIN_DIR . 'extensions/index.json';
2077 - $block_list = $wp_filesystem->get_contents( $block_list_path );
2078 - if ( empty( $block_list ) ) {
2079 - /* translators: %s is the path to the file with the block list */
2080 - WP_CLI::error( sprintf( esc_html__( 'Error fetching contents of %s', 'jetpack' ), $block_list_path ) );
2081 - } elseif ( false === stripos( $block_list, $slug ) ) {
2082 - $new_block_list = json_decode( $block_list );
2083 - $new_block_list->{ $variation }[] = $slug;
2084 -
2085 - // Format the JSON to match our coding standards.
2086 - $new_block_list_formatted = wp_json_encode( $new_block_list, JSON_PRETTY_PRINT ) . "\n";
2087 - $new_block_list_formatted = preg_replace_callback(
2088 - // Find all occurrences of multiples of 4 spaces a the start of the line.
2089 - '/^((?: )+)/m',
2090 - function ( $matches ) {
2091 - // Replace each occurrence of 4 spaces with a tab character.
2092 - return str_repeat( "\t", substr_count( $matches[0], ' ' ) );
2093 - },
2094 - $new_block_list_formatted
2095 - );
2096 -
2097 - if ( ! $wp_filesystem->put_contents( $block_list_path, $new_block_list_formatted ) ) {
2098 - /* translators: %s is the path to the file with the block list */
2099 - WP_CLI::error( sprintf( esc_html__( 'Error writing new %s', 'jetpack' ), $block_list_path ) );
2100 - }
2101 - }
2102 -
2103 - if ( 'beta' === $variation || 'experimental' === $variation ) {
2104 - $block_constant = sprintf(
2105 - /* translators: the placeholder is a constant name */
2106 - esc_html__( 'To load the block, add the constant JETPACK_BLOCKS_VARIATION set to %1$s to your wp-config.php file', 'jetpack' ),
2107 - $variation
2108 - );
2109 - } else {
2110 - $block_constant = '';
2111 - }
2112 -
2113 - WP_CLI::success(
2114 - sprintf(
2115 - /* translators: the placeholders are a human readable title, and a series of words separated by dashes */
2116 - esc_html__( 'Successfully created block %1$s with slug %2$s', 'jetpack' ) . ' 🎉' . "\n" .
2117 - "--------------------------------------------------------------------------------------------------------------------\n" .
2118 - /* translators: the placeholder is a directory path */
2119 - esc_html__( 'The files were created at %3$s', 'jetpack' ) . "\n" .
2120 - esc_html__( 'To start using the block, build the blocks with pnpm run build-extensions', 'jetpack' ) . "\n" .
2121 - /* translators: the placeholder is a file path */
2122 - esc_html__( 'The block slug has been added to the %4$s list at %5$s', 'jetpack' ) . "\n" .
2123 - '%6$s' . "\n" .
2124 - /* translators: the placeholder is a URL */
2125 - "\n" . esc_html__( 'Read more at %7$s', 'jetpack' ) . "\n",
2126 - $title,
2127 - $slug,
2128 - $path,
2129 - $variation,
2130 - $block_list_path,
2131 - $block_constant,
2132 - 'https://github.com/Automattic/jetpack/blob/trunk/projects/plugins/jetpack/extensions/README.md#developing-block-editor-extensions-in-jetpack'
2133 - ) . '--------------------------------------------------------------------------------------------------------------------'
2134 - );
2135 - }
2136 - }
2137 -
2138 - /**
2139 - * Built the file replacing the placeholders in the template with the data supplied.
2140 - *
2141 - * @param string $template Template.
2142 - * @param array $data Data.
2143 - * @return string mixed
2144 - */
2145 - private static function render_block_file( $template, $data = array() ) {
2146 - return \WP_CLI\Utils\mustache_render( JETPACK__PLUGIN_DIR . "wp-cli-templates/$template.mustache", $data );
2147 - }
2148 1479 }
2149 1480
2150 -// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
2151 -
2152 -/**
1481 +/*
2153 1482 * Standard "ask for permission to continue" function.
2154 1483 * If action cancelled, ask if they need help.
2155 1484 *
2156 1485 * Written outside of the class so it's not listed as an executable command w/ 'wp jetpack'
2157 1486 *
2158 - * @param bool $flagged false = normal option | true = flagged by get_jetpack_options_for_reset().
2159 - * @param string $error_msg Error message.
1487 + * @param $flagged bool false = normal option | true = flagged by get_jetpack_options_for_reset()
1488 + * @param $error_msg string (optional)
2160 1489 */
2161 1490 function jetpack_cli_are_you_sure( $flagged = false, $error_msg = false ) {
2162 1491 $cli = new Jetpack_CLI();
2163 1492
2164 - // Default cancellation message.
1493 + // Default cancellation message
2165 1494 if ( ! $error_msg ) {
2166 1495 $error_msg =
2167 1496 __( 'Action cancelled. Have a question?', 'jetpack' )
2168 1497 . ' '
@@ -2167,20 +1496,20 @@
2167 1496 __( 'Action cancelled. Have a question?', 'jetpack' )
2168 1497 . ' '
2169 1498 . $cli->green_open
2170 1499 . 'jetpack.com/support'
2171 - . $cli->color_close;
1500 + . $cli->color_close;
2172 1501 }
2173 1502
2174 1503 if ( ! $flagged ) {
2175 1504 $prompt_message = _x( 'Are you sure? This cannot be undone. Type "yes" to continue:', '"yes" is a command - do not translate.', 'jetpack' );
2176 1505 } else {
2177 - $prompt_message = _x( 'Are you sure? Modifying this option may disrupt your Jetpack connection. Type "yes" to continue.', '"yes" is a command - do not translate.', 'jetpack' );
1506 + $prompt_message = _x( 'Are you sure? Modifying this option may disrupt your Jetpack connection. Type "yes" to continue.', '"yes" is a command - do not translate.', 'jetpack' );
2178 1507 }
2179 1508
2180 1509 WP_CLI::line( $prompt_message );
2181 - $handle = fopen( 'php://stdin', 'r' );
2182 - $line = fgets( $handle );
2183 - if ( 'yes' !== trim( $line ) ) {
1510 + $handle = fopen( "php://stdin", "r" );
1511 + $line = fgets( $handle );
1512 + if ( 'yes' != trim( $line ) ){
2184 1513 WP_CLI::error( $error_msg );
2185 1514 }
2186 1515 }