class.jetpack-cli.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. <?php
  2. WP_CLI::add_command( 'jetpack', 'Jetpack_CLI' );
  3. /**
  4. * Control your local Jetpack installation.
  5. */
  6. class Jetpack_CLI extends WP_CLI_Command {
  7. // Aesthetics
  8. public $green_open = "\033[32m";
  9. public $red_open = "\033[31m";
  10. public $yellow_open = "\033[33m";
  11. public $color_close = "\033[0m";
  12. /**
  13. * Get Jetpack Details
  14. *
  15. * ## OPTIONS
  16. *
  17. * empty: Leave it empty for basic stats
  18. *
  19. * full: View full stats. It's the data from the heartbeat
  20. *
  21. * ## EXAMPLES
  22. *
  23. * wp jetpack status
  24. * wp jetpack status full
  25. *
  26. */
  27. public function status( $args, $assoc_args ) {
  28. if ( ! Jetpack::is_active() ) {
  29. WP_CLI::error( __( 'Jetpack is not currently connected to WordPress.com', 'jetpack' ) );
  30. }
  31. if ( isset( $args[0] ) && 'full' !== $args[0] ) {
  32. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $args[0] ) );
  33. }
  34. /*
  35. * Are they asking for all data?
  36. *
  37. * Loop through heartbeat data and organize by priority.
  38. */
  39. $all_data = ( isset( $args[0] ) && 'full' == $args[0] ) ? 'full' : false;
  40. if ( $all_data ) {
  41. WP_CLI::success( __( 'Jetpack is currently connected to WordPress.com', 'jetpack' ) );
  42. WP_CLI::line( sprintf( __( "The Jetpack Version is %s", 'jetpack' ), JETPACK__VERSION ) );
  43. WP_CLI::line( sprintf( __( "The WordPress.com blog_id is %d", 'jetpack' ), Jetpack_Options::get_option( 'id' ) ) );
  44. // Heartbeat data
  45. WP_CLI::line( "\n" . __( 'Additional data: ', 'jetpack' ) );
  46. // Get the filtered heartbeat data.
  47. // Filtered so we can color/list by severity
  48. $stats = Jetpack::jetpack_check_heartbeat_data();
  49. // Display red flags first
  50. foreach ( $stats['bad'] as $stat => $value ) {
  51. printf( "$this->red_open%-'.16s %s $this->color_close\n", $stat, $value );
  52. }
  53. // Display caution warnings next
  54. foreach ( $stats['caution'] as $stat => $value ) {
  55. printf( "$this->yellow_open%-'.16s %s $this->color_close\n", $stat, $value );
  56. }
  57. // The rest of the results are good!
  58. foreach ( $stats['good'] as $stat => $value ) {
  59. // Modules should get special spacing for aestetics
  60. if ( strpos( $stat, 'odule-' ) ) {
  61. printf( "%-'.30s %s\n", $stat, $value );
  62. usleep( 4000 ); // For dramatic effect lolz
  63. continue;
  64. }
  65. printf( "%-'.16s %s\n", $stat, $value );
  66. usleep( 4000 ); // For dramatic effect lolz
  67. }
  68. } else {
  69. // Just the basics
  70. WP_CLI::success( __( 'Jetpack is currently connected to WordPress.com', 'jetpack' ) );
  71. WP_CLI::line( sprintf( __( 'The Jetpack Version is %s', 'jetpack' ), JETPACK__VERSION ) );
  72. WP_CLI::line( sprintf( __( 'The WordPress.com blog_id is %d', 'jetpack' ), Jetpack_Options::get_option( 'id' ) ) );
  73. WP_CLI::line( "\n" . _x( "View full status with 'wp jetpack status full'", '"wp jetpack status full" is a command - do not translate', 'jetpack' ) );
  74. }
  75. }
  76. /**
  77. * Disconnect Jetpack Blogs or Users
  78. *
  79. * ## OPTIONS
  80. *
  81. * blog: Disconnect the entire blog.
  82. *
  83. * user <user_identifier>: Disconnect a specific user from WordPress.com.
  84. *
  85. * Please note, the primary account that the blog is connected
  86. * to WordPress.com with cannot be disconnected without
  87. * disconnecting the entire blog.
  88. *
  89. * ## EXAMPLES
  90. *
  91. * wp jetpack disconnect blog
  92. * wp jetpack disconnect user 13
  93. * wp jetpack disconnect user username
  94. * wp jetpack disconnect user email@domain.com
  95. *
  96. * @synopsis <blog|user> [<user_identifier>]
  97. */
  98. public function disconnect( $args, $assoc_args ) {
  99. if ( ! Jetpack::is_active() ) {
  100. WP_CLI::error( __( 'You cannot disconnect, without having first connected.', 'jetpack' ) );
  101. }
  102. $action = isset( $args[0] ) ? $args[0] : 'prompt';
  103. if ( ! in_array( $action, array( 'blog', 'user', 'prompt' ) ) ) {
  104. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
  105. }
  106. if ( in_array( $action, array( 'user' ) ) ) {
  107. if ( isset( $args[1] ) ) {
  108. $user_id = $args[1];
  109. if ( ctype_digit( $user_id ) ) {
  110. $field = 'id';
  111. $user_id = (int) $user_id;
  112. } elseif ( is_email( $user_id ) ) {
  113. $field = 'email';
  114. $user_id = sanitize_user( $user_id, true );
  115. } else {
  116. $field = 'login';
  117. $user_id = sanitize_user( $user_id, true );
  118. }
  119. if ( ! $user = get_user_by( $field, $user_id ) ) {
  120. WP_CLI::error( __( 'Please specify a valid user.', 'jetpack' ) );
  121. }
  122. } else {
  123. WP_CLI::error( __( 'Please specify a user by either ID, username, or email.', 'jetpack' ) );
  124. }
  125. }
  126. switch ( $action ) {
  127. case 'blog':
  128. Jetpack::log( 'disconnect' );
  129. Jetpack::disconnect();
  130. WP_CLI::success( __( 'Jetpack has been successfully disconnected.', 'jetpack' ) );
  131. break;
  132. case 'user':
  133. if ( Jetpack::unlink_user( $user->ID ) ) {
  134. Jetpack::log( 'unlink', $user->ID );
  135. WP_CLI::success( sprintf( __( '%s has been successfully disconnected.', 'jetpack' ), $action ) );
  136. } else {
  137. WP_CLI::error( sprintf( __( '%s could not be disconnected. Are you sure they\'re connected currently?', 'jetpack' ), "{$user->login} <{$user->email}>" ) );
  138. }
  139. break;
  140. case 'prompt':
  141. WP_CLI::error( __( 'Please specify if you would like to disconnect a blog or user.', 'jetpack' ) );
  142. break;
  143. }
  144. }
  145. /**
  146. * Reset Jetpack options and settings to default
  147. *
  148. * ## OPTIONS
  149. *
  150. * modules: Resets modules to default state ( get_default_modules() )
  151. *
  152. * options: Resets all Jetpack options except:
  153. * - All private options (Blog token, user token, etc...)
  154. * - id (The Client ID/WP.com Blog ID of this site)
  155. * - master_user
  156. * - version
  157. * - activated
  158. *
  159. * ## EXAMPLES
  160. *
  161. * wp jetpack reset options
  162. * wp jetpack reset modules
  163. *
  164. * @synopsis <modules|options>
  165. */
  166. public function reset( $args, $assoc_args ) {
  167. $action = isset( $args[0] ) ? $args[0] : 'prompt';
  168. if ( ! in_array( $action, array( 'options', 'modules' ) ) ) {
  169. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
  170. }
  171. // Are you sure?
  172. jetpack_cli_are_you_sure();
  173. switch ( $action ) {
  174. case 'options':
  175. $options_to_reset = Jetpack::get_jetpack_options_for_reset();
  176. // Reset the Jetpack options
  177. _e( "Resetting Jetpack Options...\n", "jetpack" );
  178. sleep(1); // Take a breath
  179. foreach ( $options_to_reset['jp_options'] as $option_to_reset ) {
  180. Jetpack_Options::delete_option( $option_to_reset );
  181. usleep( 100000 );
  182. WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
  183. }
  184. // Reset the WP options
  185. _e( "Resetting the jetpack options stored in wp_options...\n", "jetpack" );
  186. usleep( 500000 ); // Take a breath
  187. foreach ( $options_to_reset['wp_options'] as $option_to_reset ) {
  188. delete_option( $option_to_reset );
  189. usleep( 100000 );
  190. WP_CLI::success( sprintf( __( '%s option reset', 'jetpack' ), $option_to_reset ) );
  191. }
  192. // Reset to default modules
  193. _e( "Resetting default modules...\n", "jetpack" );
  194. usleep( 500000 ); // Take a breath
  195. $default_modules = Jetpack::get_default_modules();
  196. Jetpack::update_active_modules( $default_modules );
  197. WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
  198. // Jumpstart option is special
  199. Jetpack_Options::update_option( 'jumpstart', 'new_connection' );
  200. WP_CLI::success( __( 'jumpstart option reset', 'jetpack' ) );
  201. break;
  202. case 'modules':
  203. $default_modules = Jetpack::get_default_modules();
  204. Jetpack::update_active_modules( $default_modules );
  205. WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
  206. break;
  207. case 'prompt':
  208. WP_CLI::error( __( 'Please specify if you would like to reset your options, or modules', 'jetpack' ) );
  209. break;
  210. }
  211. }
  212. /**
  213. * Manage Jetpack Modules
  214. *
  215. * ## OPTIONS
  216. *
  217. * list : View all available modules, and their status.
  218. * activate all : Activate all modules
  219. * deactivate all: Deactivate all modules
  220. *
  221. * activate <module_slug> : Activate a module.
  222. * deactivate <module_slug> : Deactivate a module.
  223. * toggle <module_slug> : Toggle a module on or off.
  224. *
  225. * ## EXAMPLES
  226. *
  227. * wp jetpack module list
  228. * wp jetpack module activate stats
  229. * wp jetpack module deactivate stats
  230. * wp jetpack module toggle stats
  231. *
  232. * wp jetpack module activate all
  233. * wp jetpack module deactivate all
  234. *
  235. * @synopsis <list|activate|deactivate|toggle> [<module_name>]
  236. */
  237. public function module( $args, $assoc_args ) {
  238. $action = isset( $args[0] ) ? $args[0] : 'list';
  239. if ( ! in_array( $action, array( 'list', 'activate', 'deactivate', 'toggle' ) ) ) {
  240. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
  241. }
  242. if ( in_array( $action, array( 'activate', 'deactivate', 'toggle' ) ) ) {
  243. if ( isset( $args[1] ) ) {
  244. $module_slug = $args[1];
  245. if ( 'all' !== $module_slug && ! Jetpack::is_module( $module_slug ) ) {
  246. WP_CLI::error( sprintf( __( '%s is not a valid module.', 'jetpack' ), $module_slug ) );
  247. }
  248. if ( 'toggle' == $action ) {
  249. $action = Jetpack::is_module_active( $module_slug ) ? 'deactivate' : 'activate';
  250. }
  251. // Bulk actions
  252. if ( 'all' == $args[1] ) {
  253. $action = ( 'deactivate' == $action ) ? 'deactivate_all' : 'activate_all';
  254. }
  255. // VaultPress needs to be handled elsewhere.
  256. if ( in_array( $action, array( 'activate', 'deactivate', 'toggle' ) ) && 'vaultpress' == $args[1] ) {
  257. WP_CLI::error( sprintf( _x( 'Please visit %s to configure your VaultPress subscription.', '%s is a website', 'jetpack' ), esc_url( 'https://vaultpress.com/jetpack/' ) ) );
  258. }
  259. } else {
  260. WP_CLI::line( __( 'Please specify a valid module.', 'jetpack' ) );
  261. $action = 'list';
  262. }
  263. }
  264. switch ( $action ) {
  265. case 'list':
  266. WP_CLI::line( __( 'Available Modules:', 'jetpack' ) );
  267. $modules = Jetpack::get_available_modules();
  268. sort( $modules );
  269. foreach( $modules as $module_slug ) {
  270. if ( 'vaultpress' == $module_slug ) {
  271. continue;
  272. }
  273. $active = Jetpack::is_module_active( $module_slug ) ? __( 'Active', 'jetpack' ) : __( 'Inactive', 'jetpack' );
  274. WP_CLI::line( "\t" . str_pad( $module_slug, 24 ) . $active );
  275. }
  276. break;
  277. case 'activate':
  278. $module = Jetpack::get_module( $module_slug );
  279. Jetpack::log( 'activate', $module_slug );
  280. Jetpack::activate_module( $module_slug, false, false );
  281. WP_CLI::success( sprintf( __( '%s has been activated.', 'jetpack' ), $module['name'] ) );
  282. break;
  283. case 'activate_all':
  284. $modules = Jetpack::get_available_modules();
  285. Jetpack::update_active_modules( $modules );
  286. WP_CLI::success( __( 'All modules activated!', 'jetpack' ) );
  287. break;
  288. case 'deactivate':
  289. $module = Jetpack::get_module( $module_slug );
  290. Jetpack::log( 'deactivate', $module_slug );
  291. Jetpack::deactivate_module( $module_slug );
  292. WP_CLI::success( sprintf( __( '%s has been deactivated.', 'jetpack' ), $module['name'] ) );
  293. break;
  294. case 'deactivate_all':
  295. Jetpack::delete_active_modules();
  296. WP_CLI::success( __( 'All modules deactivated!', 'jetpack' ) );
  297. break;
  298. case 'toggle':
  299. // Will never happen, should have been handled above and changed to activate or deactivate.
  300. break;
  301. }
  302. }
  303. /**
  304. * Manage Protect Settings
  305. *
  306. * ## OPTIONS
  307. *
  308. * whitelist: Whitelist an IP address. You can also read or clear the whitelist.
  309. *
  310. *
  311. * ## EXAMPLES
  312. *
  313. * wp jetpack protect whitelist <ip address>
  314. * wp jetpack protect whitelist list
  315. * wp jetpack protect whitelist clear
  316. *
  317. * @synopsis <whitelist> [<ip|ip_low-ip_high|list|clear>]
  318. */
  319. public function protect( $args, $assoc_args ) {
  320. $action = isset( $args[0] ) ? $args[0] : 'prompt';
  321. if ( ! in_array( $action, array( 'whitelist' ) ) ) {
  322. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
  323. }
  324. // Check if module is active
  325. if ( ! Jetpack::is_module_active( __FUNCTION__ ) ) {
  326. 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__ ) );
  327. }
  328. if ( in_array( $action, array( 'whitelist' ) ) ) {
  329. if ( isset( $args[1] ) ) {
  330. $action = 'whitelist';
  331. } else {
  332. $action = 'prompt';
  333. }
  334. }
  335. switch ( $action ) {
  336. case 'whitelist':
  337. $whitelist = array();
  338. $new_ip = $args[1];
  339. $current_whitelist = get_site_option( 'jetpack_protect_whitelist' );
  340. // Build array of IPs that are already whitelisted.
  341. // Re-build manually instead of using jetpack_protect_format_whitelist() so we can easily get
  342. // low & high range params for jetpack_protect_ip_address_is_in_range();
  343. foreach( $current_whitelist as $whitelisted ) {
  344. // IP ranges
  345. if ( $whitelisted->range ) {
  346. // Is it already whitelisted?
  347. if ( jetpack_protect_ip_address_is_in_range( $new_ip, $whitelisted->range_low, $whitelisted->range_high ) ) {
  348. WP_CLI::error( sprintf( __( "%s has already been whitelisted", 'jetpack' ), $new_ip ) );
  349. break;
  350. }
  351. $whitelist[] = $whitelisted->range_low . " - " . $whitelisted->range_high;
  352. } else { // Individual IPs
  353. // Check if the IP is already whitelisted (single IP only)
  354. if ( $new_ip == $whitelisted->ip_address ) {
  355. WP_CLI::error( sprintf( __( "%s has already been whitelisted", 'jetpack' ), $new_ip ) );
  356. break;
  357. }
  358. $whitelist[] = $whitelisted->ip_address;
  359. }
  360. }
  361. /*
  362. * List the whitelist
  363. * Done here because it's easier to read the $whitelist array after it's been rebuilt
  364. */
  365. if ( isset( $args[1] ) && 'list' == $args[1] ) {
  366. if ( ! empty( $whitelist ) ) {
  367. WP_CLI::success( __( 'Here are your whitelisted IPs:', 'jetpack' ) );
  368. foreach ( $whitelist as $ip ) {
  369. WP_CLI::line( "\t" . str_pad( $ip, 24 ) ) ;
  370. }
  371. } else {
  372. WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
  373. }
  374. break;
  375. }
  376. /*
  377. * Clear the whitelist
  378. */
  379. if ( isset( $args[1] ) && 'clear' == $args[1] ) {
  380. if ( ! empty( $whitelist ) ) {
  381. $whitelist = array();
  382. jetpack_protect_save_whitelist( $whitelist );
  383. WP_CLI::success( __( 'Cleared all whitelisted IPs', 'jetpack' ) );
  384. } else {
  385. WP_CLI::line( __( 'Whitelist is empty.', "jetpack" ) ) ;
  386. }
  387. break;
  388. }
  389. // Append new IP to whitelist array
  390. array_push( $whitelist, $new_ip );
  391. // Save whitelist if there are no errors
  392. $result = jetpack_protect_save_whitelist( $whitelist );
  393. if ( is_wp_error( $result ) ) {
  394. WP_CLI::error( __( $result, 'jetpack' ) );
  395. }
  396. WP_CLI::success( sprintf( __( '%s has been whitelisted.', 'jetpack' ), $new_ip ) );
  397. break;
  398. case 'prompt':
  399. WP_CLI::error(
  400. __( 'No command found.', 'jetpack' ) . "\n" .
  401. __( 'Please enter the IP address you want to whitelist.', 'jetpack' ) . "\n" .
  402. _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" .
  403. _x( "You can also 'list' or 'clear' the whitelist.", "'list' and 'clear' are commands and should not be translated", 'jetpack' ) . "\n"
  404. );
  405. break;
  406. }
  407. }
  408. /**
  409. * Manage Jetpack Options
  410. *
  411. * ## OPTIONS
  412. *
  413. * list : List all jetpack options and their values
  414. * delete : Delete an option
  415. * - can only delete options that are white listed.
  416. * update : update an option
  417. * - can only update option strings
  418. * get : get the value of an option
  419. *
  420. * ## EXAMPLES
  421. *
  422. * wp jetpack options list
  423. * wp jetpack options get <option_name>
  424. * wp jetpack options delete <option_name>
  425. * wp jetpack options update <option_name> [<option_value>]
  426. *
  427. * @synopsis <list|get|delete|update> [<option_name>] [<option_value>]
  428. */
  429. public function options( $args, $assoc_args ) {
  430. $action = isset( $args[0] ) ? $args[0] : 'list';
  431. $safe_to_modify = Jetpack::get_jetpack_options_for_reset();
  432. // Jumpstart is special
  433. array_push( $safe_to_modify, 'jumpstart' );
  434. // Is the option flagged as unsafe?
  435. $flagged = ! in_array( $args[1], $safe_to_modify );
  436. if ( ! in_array( $action, array( 'list', 'get', 'delete', 'update' ) ) ) {
  437. WP_CLI::error( sprintf( __( '%s is not a valid command.', 'jetpack' ), $action ) );
  438. }
  439. if ( isset( $args[0] ) ) {
  440. if ( 'get' == $args[0] && isset( $args[1] ) ) {
  441. $action = 'get';
  442. } else if ( 'delete' == $args[0] && isset( $args[1] ) ) {
  443. $action = 'delete';
  444. } else if ( 'update' == $args[0] && isset( $args[1] ) ) {
  445. $action = 'update';
  446. } else {
  447. $action = 'list';
  448. }
  449. }
  450. // Bail if the option isn't found
  451. $option = isset( $args[1] ) ? Jetpack_Options::get_option( $args[1] ) : false;
  452. if ( isset( $args[1] ) && ! $option && 'update' !== $args[0] ) {
  453. WP_CLI::error( __( 'Option not found or is empty. Use "list" to list option names', 'jetpack' ) );
  454. }
  455. // Let's print_r the option if it's an array
  456. // Used in the 'get' and 'list' actions
  457. $option = is_array( $option ) ? print_r( $option ) : $option;
  458. switch ( $action ) {
  459. case 'get':
  460. WP_CLI::success( "\t" . $option );
  461. break;
  462. case 'delete':
  463. jetpack_cli_are_you_sure( $flagged );
  464. Jetpack_Options::delete_option( $args[1] );
  465. WP_CLI::success( sprintf( __( 'Deleted option: %s', 'jetpack' ), $args[1] ) );
  466. break;
  467. case 'update':
  468. jetpack_cli_are_you_sure( $flagged );
  469. // Updating arrays would get pretty tricky...
  470. $value = Jetpack_Options::get_option( $args[1] );
  471. if ( $value && is_array( $value ) ) {
  472. WP_CLI::error( __( 'Sorry, no updating arrays at this time', 'jetpack' ) );
  473. }
  474. Jetpack_Options::update_option( $args[1], $args[2] );
  475. WP_CLI::success( sprintf( _x( 'Updated option: %s to "%s"', 'Updating an option from "this" to "that".', 'jetpack' ), $args[1], $args[2] ) );
  476. break;
  477. case 'list':
  478. $options_compact = Jetpack_Options::get_option_names();
  479. $options_non_compact = Jetpack_Options::get_option_names( 'non_compact' );
  480. $options_private = Jetpack_Options::get_option_names( 'private' );
  481. $options = array_merge( $options_compact, $options_non_compact, $options_private );
  482. // Table headers
  483. WP_CLI::line( "\t" . str_pad( __( 'Option', 'jetpack' ), 30 ) . __( 'Value', 'jetpack' ) );
  484. // List out the options and their values
  485. // Tell them if the value is empty or not
  486. // Tell them if it's an array
  487. foreach ( $options as $option ) {
  488. $value = Jetpack_Options::get_option( $option );
  489. if ( ! $value ) {
  490. WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Empty' );
  491. continue;
  492. }
  493. if ( ! is_array( $value ) ) {
  494. WP_CLI::line( "\t" . str_pad( $option, 30 ) . $value );
  495. } else if ( is_array( $value ) ) {
  496. WP_CLI::line( "\t" . str_pad( $option, 30 ) . 'Array - Use "get <option>" to read option array.' );
  497. }
  498. }
  499. $option_text = '{' . _x( 'option', 'a variable command that a user can write, provided in the printed instructions', 'jetpack' ) . '}';
  500. $value_text = '{' . _x( 'value', 'the value that they want to update the option to', 'jetpack' ) . '}';
  501. WP_CLI::success(
  502. _x( "Above are your options. You may 'get', 'delete', and 'update' them.", "'get', 'delete', and 'update' are commands - do not translate.", 'jetpack' ) . "\n" .
  503. str_pad( 'wp jetpack options get', 26 ) . $option_text . "\n" .
  504. str_pad( 'wp jetpack options delete', 26 ) . $option_text . "\n" .
  505. str_pad( 'wp jetpack options update', 26 ) . "$option_text $value_text" . "\n" .
  506. _x( "Type 'wp jetpack options' for more info.", "'wp jetpack options' is a command - do not translate.", 'jetpack' ) . "\n"
  507. );
  508. break;
  509. }
  510. }
  511. }
  512. /*
  513. * Standard "ask for permission to continue" function.
  514. * If action cancelled, ask if they need help.
  515. *
  516. * Written outside of the class so it's not listed as an executable command w/ 'wp jetpack'
  517. *
  518. * @param $flagged bool false = normal option | true = flagged by get_jetpack_options_for_reset()
  519. * @param $error_msg string (optional)
  520. */
  521. function jetpack_cli_are_you_sure( $flagged = false, $error_msg = false ) {
  522. $cli = new Jetpack_CLI();
  523. // Default cancellation message
  524. if ( ! $error_msg ) {
  525. $error_msg =
  526. __( 'Action cancelled. Have a question?', 'jetpack' )
  527. . ' '
  528. . $cli->green_open
  529. . 'jetpack.com/support'
  530. . $cli->color_close;
  531. }
  532. if ( ! $flagged ) {
  533. $prompt_message = __( 'Are you sure? This cannot be undone. Type "yes" to continue:', '"yes" is a command. Do not translate that.', 'jetpack' );
  534. } else {
  535. /* translators: Don't translate the word yes here. */
  536. $prompt_message = __( 'Are you sure? Modifying this option may disrupt your Jetpack connection. Type "yes" to continue.', 'jetpack' );
  537. }
  538. WP_CLI::line( $prompt_message );
  539. $handle = fopen( "php://stdin", "r" );
  540. $line = fgets( $handle );
  541. if ( 'yes' != trim( $line ) ){
  542. WP_CLI::error( $error_msg );
  543. }
  544. }