Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 133
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
FeaturesCLI
0.00% covered (danger)
0.00%
0 / 133
0.00% covered (danger)
0.00%
0 / 16
2970
0.00% covered (danger)
0.00%
0 / 1
 __invoke
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
72
 list
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 isEnabled
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 enable
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 disable
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 render
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
90
 table
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 bold_heading
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 success
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 info
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 warning
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 error
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 colorize_log
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
 new_line
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 log_to_json
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 confirm
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace NewfoldLabs\WP\Module\Features;
4
5/**
6 * Class for Features CLI commands
7 */
8class FeaturesCLI extends \WP_CLI_Command {
9
10    /**
11     * Used internally to interface with features.
12     *
13     * @param array $args       Command arguments
14     * @param array $assoc_args Associative command arguments.
15     *
16     * @throws \WP_CLI\ExitException On CLI failure.
17     */
18    public function __invoke( $args, $assoc_args ) {
19
20        if ( ! is_array( $args ) || ! isset( $args[0] ) ) {
21            $this->error( __( 'No sub-command provided', 'wp-module-features' ) );
22        }
23
24        switch ( $args[0] ) {
25
26            case 'list':
27                $this->list();
28                break;
29
30            case 'isEnabled':
31                $this->isEnabled( $args[1] );
32                break;
33
34            case 'enable':
35                $this->enable( $args[1] );
36                break;
37
38            case 'disable':
39                $this->disable( $args[1] );
40                break;
41
42            default:
43                $this->error( __( 'Invalid action', 'wp-module-features' ) );
44
45        }
46    }
47
48    /**
49     * List command - lists features
50     */
51    protected function list() {
52        $features = Features::getInstance()->getFeatureList();
53        $response = array(
54            'status'  => 'success',
55            'message' => implode( ',', $features ),
56        );
57        $this->render( $response );
58    }
59
60    /**
61     * Is Enabled command - checks if feature is enabled
62     *
63     * @param string $name the feature name.
64     */
65    protected function isEnabled( $name ) {
66        $feature = Features::getInstance()->getFeature( $name );
67        if ( $feature ) {
68            $response = array(
69                'status'  => 'success',
70                'message' => $feature->isEnabled() ? 'true' : 'false',
71            );
72        } else {
73            $response = array(
74                'status'  => 'error',
75                'message' => __( 'Invalid feature name: ', 'wp-module-features' ) . $name,
76            );
77        }
78        $this->render( $response );
79    }
80
81    /**
82     * Enable command - enables a feature
83     *
84     * @param string $name the feature name.
85     */
86    protected function enable( $name ) {
87        $feature = Features::getInstance()->getFeature( $name );
88        if ( $feature ) {
89            $response = array(
90                'status'  => 'success',
91                'message' => $feature->enable(),
92            );
93        } else {
94            $response = array(
95                'status'  => 'error',
96                'message' => __( 'Invalid feature name: ', 'wp-module-features' ) . $name,
97            );
98        }
99        $this->render( $response );
100    }
101
102    /**
103     * Disable command - disables a feature
104     *
105     * @param string $name the feature name.
106     */
107    protected function disable( $name ) {
108        $feature = Features::getInstance()->getFeature( $name );
109        if ( $feature ) {
110            $response = array(
111                'status'  => 'success',
112                'message' => $feature->disable(),
113            );
114        } else {
115            $response = array(
116                'status'  => 'error',
117                'message' => __( 'Invalid feature name: ', 'wp-module-features' ) . $name,
118            );
119        }
120        $this->render( $response );
121    }
122
123    /**
124     * Render a success or error message based on provided data.
125     *
126     * @param mixed $data The data from which to fetch the message.
127     */
128    protected function render( $data ) {
129        $response = array(
130            'status'  => 'error',
131            'message' => __( 'Invalid JSON response', 'wp-module-features' ),
132        );
133
134        switch ( gettype( $data ) ) {
135            case 'boolean':
136                $response = array(
137                    'status'  => 'success',
138                    'message' => __( 'Invalid JSON response', 'wp-module-features' ),
139                );
140                break;
141            case 'string':
142                $decoded = json_decode( $data );
143                if ( $decoded && isset( $decoded['message'] ) ) {
144                    $response = $decoded;
145                }
146                break;
147            case 'array':
148                $response = $data;
149                break;
150            case 'object':
151                if ( is_wp_error( $data ) ) {
152                    $response['message'] = $data->get_error_message();
153                }
154                break;
155        }
156
157        if ( 'success' === $response['status'] ) {
158            $this->success( $response['message'] );
159        } else {
160            $this->error( $response['message'] );
161        }
162    }
163
164    /**
165     * Helper to format data into tables.
166     *
167     * By default, the method creates simple $key => $value tables.
168     * Set $type to 'adv' and the table inherits keys from $data. DATA MUST BE UNIFORM & MATCH FIRST ROW.
169     *
170     * 1. Provide $data as an array or object
171     * 2. Provide $keys as two strings -- by default 'DETAIL' and 'VALUE' are used.
172     * 3. Prints ASCII Table
173     *
174     * @param array  $data the data
175     * @param array  $keys the keys
176     * @param string $type table type
177     */
178    protected function table( $data, $keys = array( 'DETAIL', 'VALUE' ), $type = 'simple' ) {
179        if ( empty( $data ) ) {
180            return;
181        }
182
183        if ( 'adv' === $type ) {
184            $items = $data;
185            $keys  = array_keys( array_shift( $data ) );
186        } else {
187            $items = array();
188            foreach ( $data as $detail => $value ) {
189                $items[] = array(
190                    $keys[0] => $detail,
191                    $keys[1] => $value,
192                );
193            }
194        }
195
196        Utils\format_items( 'table', $items, $keys );
197    }
198
199    /**
200     * Creates Heading with Blue background and Grey text.
201     *
202     * @param string $message the message
203     * @param string $emoji optional emoji
204     */
205    protected function bold_heading( $message, $emoji = '' ) {
206        $this->colorize_log( $message, '4', 'W', $emoji );
207    }
208
209    /**
210     * Formatted Success message.
211     *
212     * @param string $message the message
213     * @param bool   $silent if the success should be silent
214     */
215    protected function success( $message, $silent = false ) {
216        $pre_ = $silent ? '' : 'Success: ';
217        $this->colorize_log( $pre_ . $message, '2', 'k', '✅' );
218    }
219
220    /**
221     * Formatted Info message.
222     *
223     * @param string $message the message
224     */
225    protected function info( $message ) {
226        $this->colorize_log( $message, '4', 'W', 'ℹ️' );
227    }
228
229    /**
230     * Formatted Warning message.
231     *
232     * @param string $message the message
233     */
234    protected function warning( $message ) {
235        $this->colorize_log( $message, '3', 'k', '⚠️' );
236    }
237
238    /**
239     * Formatted Error message. Halts by default.
240     *
241     * @param string $message the message
242     * @param bool   $silent if the error should be silent
243     * @param bool   $halt if the error should stop execution
244     * @param int    $code error code
245     *
246     * @throws \WP_CLI\ExitException Exception.
247     */
248    protected function error( $message, $silent = false, $halt = true, $code = 400 ) {
249        $pre_ = $silent ? '' : 'Error: ';
250        $this->colorize_log( $pre_ . $message, '1', 'W', '🛑️' );
251        if ( $halt ) {
252            \WP_CLI::halt( $code );
253        }
254    }
255
256    /**
257     * Formatting helper for colorized messages.
258     *
259     * @param string $message the message
260     * @param string $background background color
261     * @param string $text_color text color
262     * @param string $emoji_prefix emojoi prefix
263     */
264    protected function colorize_log( $message = '', $background = '', $text_color = '%_', $emoji_prefix = '' ) {
265        if ( ! empty( $background ) ) {
266            $background = '%' . $background;
267        }
268
269        if ( ! empty( $text_color ) && false === strpos( $text_color, '%' ) ) {
270            $text_color = '%' . $text_color;
271        }
272
273        if ( ! empty( $emoji_prefix ) ) {
274            $message = $emoji_prefix . '  ' . $message;
275        }
276
277        \WP_CLI::log( \WP_CLI::colorize( $background . $text_color . $message . '%n' ) );
278    }
279
280    /**
281     * Empty linebreak
282     */
283    protected function new_line() {
284        \WP_CLI::log( __return_empty_string() );
285    }
286
287    /**
288     * Helper function for returning clean JSON response.
289     *
290     * @param array|string $data - Provide well-formed array or existing JSON string.
291     */
292    protected function log_to_json( $data ) {
293        if ( is_array( $data ) ) {
294            \WP_CLI::log( wp_json_encode( $data ) );
295        } elseif ( is_array( json_decode( $data, true ) ) ) {
296            \WP_CLI::log( $data );
297        } else {
298            $this->error( __( 'Provided $data wasn\'t valid array or JSON string.', 'wp-module-features' ) );
299        }
300    }
301
302    /**
303     * Formatted Confirm Dialog. A 'n' response breaks the thread.
304     *
305     * @param string $question the question
306     * @param string $type level
307     *
308     * @throws \WP_CLI\ExitException Exception.
309     */
310    protected function confirm( $question, $type = 'normal' ) {
311        switch ( $type ) {
312            case 'omg':
313                \WP_CLI::confirm( $this->warning( '☢ 🙊 🙈 🙊 ☢️  ' . $question ) );
314                break;
315            case 'red':
316                \WP_CLI::confirm( $this->error( $question, true ) );
317                break;
318            case 'yellow':
319                \WP_CLI::confirm( $this->warning( $question ) );
320                break;
321            case 'green':
322                \WP_CLI::confirm( $this->success( $question ) );
323                break;
324            case 'underline':
325                \WP_CLI::confirm( $this->colorize_log( $question, '', 'U' ) );
326                break;
327            case 'normal':
328            default:
329                \WP_CLI::confirm( $question );
330                break;
331        }
332    }
333}