PluginProbe
OPcache Manager / trunk
OPcache Manager vtrunk
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.2.0 1.3.0 1.3.1 1.3.2 2.0.0 2.1.0 2.10.0 2.11.0 2.12.0 2.13.0 2.13.1 2.14.0 2.2.0 2.3.0 2.3.1 2.3.2 2.4.0 2.5.0 2.6.0 All 36 releases
opcache-manager / includes / features / class-wpcli.php

class-wpcli.php in OPcache Manager trunk, at includes/features/class-wpcli.php

496 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP-CLI for OPcache Manager.
4 *
5 * Adds WP-CLI commands to OPcache Manager
6 *
7 * @package Features
8 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
9 * @since 2.0.0
10 */
11
12 namespace OPcacheManager\Plugin\Feature;
13
14 use OPcacheManager\System\OPcache;
15 use OPcacheManager\System\Environment;
16 use OPcacheManager\System\Option;
17 use OPcacheManager\Plugin\Feature\Analytics;
18 use OPcacheManager\System\Markdown;
19 use OPcacheManager\Plugin\Opcache_Manager_Admin;
20 use Spyc;
21
22 /**
23 * Manages OPcache and get analytics about its use.
24 *
25 * @package Features
26 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
27 * @since 2.0.0
28 */
29 class Wpcli {
30
31 /**
32 * List of exit codes.
33 *
34 * @since 2.0.0
35 * @var array $exit_codes Exit codes.
36 */
37 private $exit_codes = [
38 0 => 'operation successful.',
39 1 => 'unrecognized setting.',
40 2 => 'unrecognized action.',
41 3 => 'analytics are disabled.',
42 4 => 'invalidation or warmup already scheduled.',
43 255 => 'unknown error.',
44 ];
45
46 /**
47 * Write ids as clean stdout.
48 *
49 * @param array $ids The ids.
50 * @param string $field Optional. The field to output.
51 * @since 2.0.0
52 */
53 private function write_ids( $ids, $field = '' ) {
54 $result = '';
55 $last = end( $ids );
56 foreach ( $ids as $key => $id ) {
57 if ( '' === $field ) {
58 $result .= $key;
59 } else {
60 $result .= $id[ $field ];
61 }
62 if ( $id !== $last ) {
63 $result .= ' ';
64 }
65 }
66 // phpcs:ignore
67 fwrite( STDOUT, $result );
68 }
69
70 /**
71 * Write an error.
72 *
73 * @param integer $code Optional. The error code.
74 * @param boolean $stdout Optional. Clean stdout output.
75 * @since 2.0.0
76 */
77 private function error( $code = 255, $stdout = false ) {
78 $msg = '[' . OPCM_PRODUCT_NAME . '] ' . ucfirst( $this->exit_codes[ $code ] );
79 if ( \WP_CLI\Utils\isPiped() ) {
80 // phpcs:ignore
81 fwrite( STDOUT, '' );
82 // phpcs:ignore
83 exit( $code );
84 } elseif ( $stdout ) {
85 // phpcs:ignore
86 fwrite( STDERR, $msg );
87 // phpcs:ignore
88 exit( $code );
89 } else {
90 \WP_CLI::error( $msg );
91 }
92 }
93
94 /**
95 * Write a warning.
96 *
97 * @param string $msg The message.
98 * @param string $result Optional. The result.
99 * @param boolean $stdout Optional. Clean stdout output.
100 * @since 2.0.0
101 */
102 private function warning( $msg, $result = '', $stdout = false ) {
103 $msg = '[' . OPCM_PRODUCT_NAME . '] ' . ucfirst( $msg );
104 if ( \WP_CLI\Utils\isPiped() || $stdout ) {
105 // phpcs:ignore
106 fwrite( STDOUT, $result );
107 } else {
108 \WP_CLI::warning( $msg );
109 }
110 }
111
112 /**
113 * Write a success.
114 *
115 * @param string $msg The message.
116 * @param string $result Optional. The result.
117 * @param boolean $stdout Optional. Clean stdout output.
118 * @since 2.0.0
119 */
120 private function success( $msg, $result = '', $stdout = false ) {
121 $msg = '[' . OPCM_PRODUCT_NAME . '] ' . ucfirst( $msg );
122 if ( \WP_CLI\Utils\isPiped() || $stdout ) {
123 // phpcs:ignore
124 fwrite( STDOUT, $result );
125 } else {
126 \WP_CLI::success( $msg );
127 }
128 }
129
130 /**
131 * Write a wimple line.
132 *
133 * @param string $msg The message.
134 * @param string $result Optional. The result.
135 * @param boolean $stdout Optional. Clean stdout output.
136 * @since 2.0.0
137 */
138 private function line( $msg, $result = '', $stdout = false ) {
139 if ( \WP_CLI\Utils\isPiped() || $stdout ) {
140 // phpcs:ignore
141 fwrite( STDOUT, $result );
142 } else {
143 \WP_CLI::line( $msg );
144 }
145 }
146
147 /**
148 * Write a wimple log line.
149 *
150 * @param string $msg The message.
151 * @param boolean $stdout Optional. Clean stdout output.
152 * @since 2.0.0
153 */
154 private function log( $msg, $stdout = false ) {
155 if ( ! \WP_CLI\Utils\isPiped() && ! $stdout ) {
156 \WP_CLI::log( $msg );
157 }
158 }
159
160 /**
161 * Get params from command line.
162 *
163 * @param array $args The command line parameters.
164 * @return array The true parameters.
165 * @since 2.0.0
166 */
167 private function get_params( $args ) {
168 $result = '';
169 if ( array_key_exists( 'settings', $args ) ) {
170 $result = \json_decode( $args['settings'], true );
171 }
172 if ( ! $result || ! is_array( $result ) ) {
173 $result = [];
174 }
175 return $result;
176 }
177
178 /**
179 * Get OPcache Manager details and operation modes.
180 *
181 * ## EXAMPLES
182 *
183 * wp opcache status
184 *
185 *
186 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-opcache-manager/blob/master/WP-CLI.md ===
187 *
188 */
189 public function status( $args, $assoc_args ) {
190 \WP_CLI::line( sprintf( '%s is running.', Environment::plugin_version_text() ) );
191 $name = OPcache::name();
192 if ( '' === $name ) {
193 \WP_CLI::line( 'OPcache is not activated for command-line.' );
194 } else {
195 \WP_CLI::line( sprintf( '%s is activated for command-line.', $name ) );
196 }
197
198 if ( 'reset' === Option::network_get( 'reset_frequency' ) ) {
199 \WP_CLI::line( 'Site invalidation: disabled.' );
200 } else {
201 $message = 'Site invalidation: ';
202 foreach ( Opcache_Manager_Admin::get_frequencies() as $f ) {
203 if ( $f[0] === Option::network_get( 'reset_frequency' ) ) {
204 $message .= $f[1];
205 }
206 }
207 if ( Option::network_get( 'warmup' ) ) {
208 $message .= ' - followed by site warm-up';
209 }
210 \WP_CLI::line( $message . '.' );
211 }
212 if ( Option::network_get( 'analytics' ) ) {
213 \WP_CLI::line( 'Analytics: enabled.' );
214 } else {
215 \WP_CLI::line( 'Analytics: disabled.' );
216 }
217 if ( Option::network_get( 'metrics' ) ) {
218 \WP_CLI::line( 'Metrics collation: enabled.' );
219 } else {
220 \WP_CLI::line( 'Metrics collation: disabled.' );
221 }
222 if ( \DecaLog\Engine::isDecalogActivated() ) {
223 \WP_CLI::line( 'Logging support: ' . \DecaLog\Engine::getVersionString() . '.' );
224 } else {
225 \WP_CLI::line( 'Logging support: no.' );
226 }
227 }
228
229 /**
230 * Modify OPcache Manager main settings.
231 *
232 * ## OPTIONS
233 *
234 * <enable|disable>
235 * : The action to take.
236 *
237 * <analytics|metrics>
238 * : The setting to change.
239 *
240 * [--yes]
241 * : Answer yes to the confirmation message, if any.
242 *
243 * [--stdout]
244 * : Use clean STDOUT output to use results in scripts. Unnecessary when piping commands because piping is detected by OPcache Manager.
245 *
246 * ## EXAMPLES
247 *
248 * wp opcache settings enable analytics
249 *
250 *
251 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-opcache-manager/blob/master/WP-CLI.md ===
252 *
253 */
254 public function settings( $args, $assoc_args ) {
255 $stdout = \WP_CLI\Utils\get_flag_value( $assoc_args, 'stdout', false );
256 $action = isset( $args[0] ) ? (string) $args[0] : '';
257 $setting = isset( $args[1] ) ? (string) $args[1] : '';
258 switch ( $action ) {
259 case 'enable':
260 switch ( $setting ) {
261 case 'analytics':
262 Option::network_set( 'analytics', true );
263 $this->success( 'analytics are now activated.', '', $stdout );
264 break;
265 case 'metrics':
266 Option::network_set( 'metrics', true );
267 $this->success( 'metrics collation is now activated.', '', $stdout );
268 break;
269 default:
270 $this->error( 1, $stdout );
271 }
272 break;
273 case 'disable':
274 switch ( $setting ) {
275 case 'analytics':
276 \WP_CLI::confirm( 'Are you sure you want to deactivate analytics?', $assoc_args );
277 Option::network_set( 'analytics', false );
278 $this->success( 'analytics are now deactivated.', '', $stdout );
279 break;
280 case 'metrics':
281 \WP_CLI::confirm( 'Are you sure you want to deactivate metrics collation?', $assoc_args );
282 Option::network_set( 'metrics', false );
283 $this->success( 'metrics collation is now deactivated.', '', $stdout );
284 break;
285 default:
286 $this->error( 1, $stdout );
287 }
288 break;
289 default:
290 $this->error( 2, $stdout );
291 }
292 }
293
294 /**
295 * Get OPcache analytics for today.
296 *
297 * ## OPTIONS
298 *
299 * [--format=<format>]
300 * : Set the output format. Note if json or yaml is chosen: full metadata is outputted too.
301 * ---
302 * default: table
303 * options:
304 * - table
305 * - json
306 * - csv
307 * - yaml
308 * - count
309 * ---
310 *
311 * [--stdout]
312 * : Use clean STDOUT output to use results in scripts. Unnecessary when piping commands because piping is detected by OPcache Manager.
313 *
314 * ## EXAMPLES
315 *
316 * wp opcache analytics
317 *
318 *
319 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-opcache-manager/blob/master/WP-CLI.md ===
320 *
321 */
322 public function analytics( $args, $assoc_args ) {
323 $stdout = \WP_CLI\Utils\get_flag_value( $assoc_args, 'stdout', false );
324 if ( ! Option::network_get( 'analytics' ) ) {
325 $this->error( 3, $stdout );
326 }
327 $analytics = Analytics::get_status_kpi_collection();
328 $result = [];
329 if ( array_key_exists( 'data', $analytics ) ) {
330 foreach ( $analytics['data'] as $kpi ) {
331 $item = [];
332 $item['kpi'] = $kpi['name'];
333 $item['description'] = $kpi['description'];
334 $item['value'] = $kpi['value']['human'];
335 if ( array_key_exists( 'ratio', $kpi ) && isset( $kpi['ratio'] ) ) {
336 $item['ratio'] = $kpi['ratio']['percent'] . '%';
337 } else {
338 $item['ratio'] = '-';
339 }
340 $item['variation'] = ( 0 < $kpi['variation']['percent'] ? '+' : '' ) . (string) $kpi['variation']['percent'] . '%';
341 $result[] = $item;
342 }
343 }
344 $format = \WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );
345 if ( 'json' === $format ) {
346 $detail = wp_json_encode( $analytics );
347 $this->line( $detail, $detail, $stdout );
348 } elseif ( 'yaml' === $format ) {
349 unset( $analytics['assets'] );
350 $detail = Spyc::YAMLDump( $analytics, true, true, true );
351 $this->line( $detail, $detail, $stdout );
352 } else {
353 \WP_CLI\Utils\format_items( $assoc_args['format'], $result, [ 'kpi', 'description', 'value', 'ratio', 'variation' ] );
354 }
355 }
356
357 /**
358 * Get information on exit codes.
359 *
360 * ## OPTIONS
361 *
362 * <list>
363 * : The action to take.
364 * ---
365 * options:
366 * - list
367 * ---
368 *
369 * [--format=<format>]
370 * : Allows overriding the output of the command when listing exit codes.
371 * ---
372 * default: table
373 * options:
374 * - table
375 * - json
376 * - csv
377 * - yaml
378 * - ids
379 * - count
380 * ---
381 *
382 * ## EXAMPLES
383 *
384 * Lists available exit codes:
385 * + wp opcache exitcode list
386 * + wp opcache exitcode list --format=json
387 *
388 *
389 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-traffic/blob/master/WP-CLI.md ===
390 *
391 */
392 public function exitcode( $args, $assoc_args ) {
393 $stdout = \WP_CLI\Utils\get_flag_value( $assoc_args, 'stdout', false );
394 $format = \WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );
395 $action = isset( $args[0] ) ? $args[0] : 'list';
396 $codes = [];
397 foreach ( $this->exit_codes as $key => $msg ) {
398 $codes[ $key ] = [
399 'code' => $key,
400 'meaning' => ucfirst( $msg ),
401 ];
402 }
403 switch ( $action ) {
404 case 'list':
405 if ( 'ids' === $format ) {
406 $this->write_ids( $codes );
407 } else {
408 \WP_CLI\Utils\format_items( $format, $codes, [ 'code', 'meaning' ] );
409 }
410 break;
411 }
412 }
413
414 /**
415 * Schedules an immediate invalidation.
416 *
417 * [--yes]
418 * : Answer yes to the confirmation message, if any.
419 *
420 * [--stdout]
421 * : Use clean STDOUT output to use results in scripts. Unnecessary when piping commands because piping is detected by OPcache Manager.
422 *
423 * ## EXAMPLES
424 *
425 * Invalidate all site/network files:
426 * + wp opcache invalidate
427 *
428 *
429 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-traffic/blob/master/WP-CLI.md ===
430 *
431 */
432 public function invalidate( $args, $assoc_args ) {
433 $stdout = \WP_CLI\Utils\get_flag_value( $assoc_args, 'stdout', false );
434 $invalidate = Option::network_get( 'flash_invalidate' );
435 $warmup = Option::network_get( 'flash_warmup' );
436 if ( $invalidate || $warmup ) {
437 $this->error( 4, $stdout );
438 } else {
439 \WP_CLI::confirm( 'Are you sure you want to schedule a full invalidation?', $assoc_args );
440 Option::network_set( 'flash_invalidate', true );
441 $this->success( 'invalidation scheduled to start in less than 5 minutes.', '', $stdout );
442 }
443 }
444
445 /**
446 * Schedules an immediate invalidation followed by a warmup.
447 *
448 * [--yes]
449 * : Answer yes to the confirmation message, if any.
450 *
451 * [--stdout]
452 * : Use clean STDOUT output to use results in scripts. Unnecessary when piping commands because piping is detected by OPcache Manager.
453 *
454 * ## EXAMPLES
455 *
456 * Invalidate and warmup all site/network files:
457 * + wp opcache warmup
458 *
459 *
460 * === For other examples and recipes, visit https://github.com/Pierre-Lannoy/wp-traffic/blob/master/WP-CLI.md ===
461 *
462 */
463 public function warmup( $args, $assoc_args ) {
464 $stdout = \WP_CLI\Utils\get_flag_value( $assoc_args, 'stdout', false );
465 $invalidate = Option::network_get( 'flash_invalidate' );
466 $warmup = Option::network_get( 'flash_warmup' );
467 if ( $invalidate || $warmup ) {
468 $this->error( 4, $stdout );
469 } else {
470 \WP_CLI::confirm( 'Are you sure you want to schedule a full invalidation followed by a warmup?', $assoc_args );
471 Option::network_set( 'flash_warmup', true );
472 $this->success( 'invalidation and warmup scheduled to start in less than 5 minutes.', '', $stdout );
473 }
474 }
475
476 /**
477 * Get the WP-CLI help file.
478 *
479 * @param array $attributes 'style' => 'markdown', 'html'.
480 * 'mode' => 'raw', 'clean'.
481 * @return string The output of the shortcode, ready to print.
482 * @since 1.0.0
483 */
484 public static function sc_get_helpfile( $attributes ) {
485 $md = new Markdown();
486 return $md->get_shortcode( 'WP-CLI.md', $attributes );
487 }
488
489 }
490
491 add_shortcode( 'opcm-wpcli', [ 'OPcacheManager\Plugin\Feature\Wpcli', 'sc_get_helpfile' ] );
492
493 if ( defined( 'WP_CLI' ) && WP_CLI ) {
494 \WP_CLI::add_command( 'opcache', 'OPcacheManager\Plugin\Feature\Wpcli' );
495 }
496