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