CLImate   A
last analyzed

↳ Parent: Project

Coupling/Cohesion

Components 2
Dependencies 8

Complexity

Total Complexity 34

Size/Duplication

Total Lines 359
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 34
lcom 2
cbo 8
dl 0
loc 359
ccs 93
cts 93
cp 1
rs 9.2
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A forceAnsiOn() 0 6 1
A forceAnsiOff() 0 6 1
A parseStyleMethod() 0 15 2
A applyStyleMethods() 0 15 4
A searchForStyleMethods() 0 10 2
A __construct() 0 9 1
A setStyle() 0 4 1
A setRouter() 0 4 1
A setSettingsManager() 0 4 1
A setArgumentManager() 0 4 1
A setOutput() 0 4 1
A setUtil() 0 4 1
A extend() 0 6 1
A to() 0 6 1
A usage() 0 4 1
A description() 0 6 1
A hasOutput() 0 9 4
A buildTerminalObject() 0 16 1
A routeRemainingMethod() 0 18 4
A __call() 0 20 4
1
<?php
2
3
namespace League\CLImate;
4
5
use League\CLImate\Argument\Manager as ArgumentManager;
6
use League\CLImate\Decorator\Style;
7
use League\CLImate\Settings\Manager as SettingsManager;
8
use League\CLImate\TerminalObject\Router\Router;
9
use League\CLImate\Util\Helper;
10
use League\CLImate\Util\Output;
11
use League\CLImate\Util\UtilFactory;
12
13
/**
14
 * @method mixed black(string $str = null)
15
 * @method mixed red(string $str = null)
16
 * @method mixed green(string $str = null)
17
 * @method mixed yellow(string $str = null)
18
 * @method mixed blue(string $str = null)
19
 * @method mixed magenta(string $str = null)
20
 * @method mixed cyan(string $str = null)
21
 * @method mixed lightGray(string $str = null)
22
 * @method mixed darkGray(string $str = null)
23
 * @method mixed lightRed(string $str = null)
24
 * @method mixed lightGreen(string $str = null)
25
 * @method mixed lightYellow(string $str = null)
26
 * @method mixed lightBlue(string $str = null)
27
 * @method mixed lightMagenta(string $str = null)
28
 * @method mixed lightCyan(string $str = null)
29
 * @method mixed white(string $str = null)
30
 *
31
 * @method mixed backgroundBlack(string $str = null)
32
 * @method mixed backgroundRed(string $str = null)
33
 * @method mixed backgroundGreen(string $str = null)
34
 * @method mixed backgroundYellow(string $str = null)
35
 * @method mixed backgroundBlue(string $str = null)
36
 * @method mixed backgroundMagenta(string $str = null)
37
 * @method mixed backgroundCyan(string $str = null)
38
 * @method mixed backgroundLightGray(string $str = null)
39
 * @method mixed backgroundDarkGray(string $str = null)
40
 * @method mixed backgroundLightRed(string $str = null)
41
 * @method mixed backgroundLightGreen(string $str = null)
42
 * @method mixed backgroundLightYellow(string $str = null)
43
 * @method mixed backgroundLightBlue(string $str = null)
44
 * @method mixed backgroundLightMagenta(string $str = null)
45
 * @method mixed backgroundLightCyan(string $str = null)
46
 * @method mixed backgroundWhite(string $str = null)
47
 *
48
 * @method mixed bold(string $str = null)
49
 * @method mixed dim(string $str = null)
50
 * @method mixed underline(string $str = null)
51
 * @method mixed blink(string $str = null)
52
 * @method mixed invert(string $str = null)
53
 * @method mixed hidden(string $str = null)
54
 *
55
 * @method mixed info(string $str = null)
56
 * @method mixed comment(string $str = null)
57
 * @method mixed whisper(string $str = null)
58
 * @method mixed shout(string $str = null)
59
 * @method mixed error(string $str = null)
60
 *
61
 * @method mixed out(string $str)
62
 * @method mixed inline(string $str)
63
 * @method mixed table(array $data)
64
 * @method mixed json(mixed $var)
65
 * @method mixed br($count = 1)
66
 * @method mixed tab($count = 1)
67
 * @method mixed draw(string $art)
68
 * @method mixed border(string $char = null, integer $length = null)
69
 * @method mixed dump(mixed $var)
70
 * @method mixed flank(string $output, string $char = null, integer $length = null)
71
 * @method mixed progress(integer $total = null)
72
 * @method mixed padding(integer $length = 0, string $char = '.')
73
 * @method mixed input(string $prompt, Util\Reader\ReaderInterface $reader = null)
74
 * @method mixed confirm(string $prompt, Util\Reader\ReaderInterface $reader = null)
75
 * @method mixed password(string $prompt, Util\Reader\ReaderInterface $reader = null)
76
 * @method mixed checkboxes(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
77
 * @method mixed radio(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
78
 * @method mixed animation(string $art, TerminalObject\Helper\Sleeper $sleeper = null)
79
 * @method mixed columns(array $data, $column_count = null)
80
 * @method mixed clear()
81
 *
82
 * @method CLImate addArt(string $dir)
83
 */
84
class CLImate
85
{
86
    /**
87
     * An instance of the Style class
88
     *
89
     * @var \League\CLImate\Decorator\Style $style
90
     */
91
    public $style;
92
93
    /**
94
     * An instance of the Terminal Object Router class
95
     *
96
     * @var \League\CLImate\TerminalObject\Router\Router $router
97
     */
98
    protected $router;
99
100
    /**
101
     * An instance of the Settings Manager class
102
     *
103
     * @var \League\CLImate\Settings\Manager $settings
104
     */
105
    protected $settings;
106
107
    /**
108
     * An instance of the Argument Manager class
109
     *
110
     * @var \League\CLImate\Argument\Manager $arguments
111
     */
112
    public $arguments;
113
114
    /**
115
     * An instance of the Output class
116
     *
117
     * @var \League\CLImate\Util\Output $output
118
     */
119
    public $output;
120
121
    /**
122
     * An instance of the Util Factory
123
     *
124
     * @var \League\CLImate\Util\UtilFactory $util
125
     */
126
    protected $util;
127
128 932
    public function __construct()
129
    {
130 932
        $this->setStyle(new Style());
131 932
        $this->setRouter(new Router());
132 932
        $this->setSettingsManager(new SettingsManager());
133 932
        $this->setOutput(new Output());
134 932
        $this->setUtil(new UtilFactory());
135 932
        $this->setArgumentManager(new ArgumentManager());
136 932
    }
137
138
    /**
139
     * Set the style property
140
     *
141
     * @param \League\CLImate\Decorator\Style $style
142
     */
143 932
    public function setStyle(Style $style)
144
    {
145 932
        $this->style = $style;
146 932
    }
147
148
    /**
149
     * Set the router property
150
     *
151
     * @param \League\CLImate\TerminalObject\Router\Router $router
152
     */
153 932
    public function setRouter(Router $router)
154
    {
155 932
        $this->router = $router;
156 932
    }
157
158
    /**
159
     * Set the settings property
160
     *
161
     * @param \League\CLImate\Settings\Manager $manager
162
     */
163 932
    public function setSettingsManager(SettingsManager $manager)
164
    {
165 932
        $this->settings = $manager;
166 932
    }
167
168
    /**
169
     * Set the arguments property
170
     *
171
     * @param \League\CLImate\Argument\Manager $manager
172
     */
173 932
    public function setArgumentManager(ArgumentManager $manager)
174
    {
175 932
        $this->arguments = $manager;
176 932
    }
177
178
    /**
179
     * Set the output property
180
     *
181
     * @param \League\CLImate\Util\Output $output
182
     */
183 932
    public function setOutput(Output $output)
184
    {
185 932
        $this->output = $output;
186 932
    }
187
188
    /**
189
     * Set the util property
190
     *
191
     * @param \League\CLImate\Util\UtilFactory $util
192
     */
193 932
    public function setUtil(UtilFactory $util)
194
    {
195 932
        $this->util = $util;
196 932
    }
197
198
    /**
199
     * Extend CLImate with custom methods
200
     *
201
     * @param string|object|array $class
202
     * @param string $key Optional custom key instead of class name
203
     *
204
     * @return \League\CLImate\CLImate
205
     */
206 36
    public function extend($class, $key = null)
207
    {
208 36
        $this->router->addExtension($key, $class);
0 ignored issues
show
Bug introduced by Joe Tannenbaum
It seems like $class defined by parameter $class on line 206 can also be of type array or object; however, League\CLImate\TerminalO...\Router::addExtension() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
209
210 28
        return $this;
211
    }
212
213
    /**
214
     * Force ansi support on
215
     *
216
     * @return \League\CLImate\CLImate
217
     */
218 4
    public function forceAnsiOn()
219
    {
220 4
        $this->util->system->forceAnsi();
221
222 4
        return $this;
223
    }
224
225
    /**
226
     * Force ansi support off
227
     *
228
     * @return \League\CLImate\CLImate
229
     */
230 4
    public function forceAnsiOff()
231
    {
232 4
        $this->util->system->forceAnsi(false);
233
234 4
        return $this;
235
    }
236
237
    /**
238
     * Write line to writer once
239
     *
240
     * @param string|array $writer
241
     *
242
     * @return \League\CLImate\CLImate
243
     */
244 4
    public function to($writer)
245
    {
246 4
        $this->output->once($writer);
247
248 4
        return $this;
249
    }
250
251
    /**
252
     * Output the program's usage statement
253
     *
254
     * @param array $argv
255
     */
256 4
    public function usage(array $argv = null)
257
    {
258 4
        return $this->arguments->usage($this, $argv);
259
    }
260
261
    /**
262
     * Set the program's description
263
     *
264
     * @param string $description
265
     *
266
     * @return \League\CLImate\CLImate
267
     */
268 4
    public function description($description)
269
    {
270 4
        $this->arguments->description($description);
271
272 4
        return $this;
273
    }
274
275
    /**
276
     * Check if we have valid output
277
     *
278
     * @param  mixed   $output
279
     *
280
     * @return boolean
281
     */
282 76
    protected function hasOutput($output)
283
    {
284 76
        if (!empty($output)) {
285 48
            return true;
286
        }
287
288
        // Check for type first to avoid errors with objects/arrays/etc
289 40
        return ((is_string($output) || is_numeric($output)) && strlen($output) > 0);
290
    }
291
292
    /**
293
     * Search for the method within the string
294
     * and route it if we find one.
295
     *
296
     * @param  string $method
297
     * @param  string $name
298
     *
299
     * @return string The new string without the executed method.
300
     */
301 552
    protected function parseStyleMethod($method, $name)
302
    {
303
        // If the name starts with this method string...
304 552
        if (substr($name, 0, strlen($method)) == $method) {
305
            // ...remove the method name from the beginning of the string...
306 112
            $name = substr($name, strlen($method));
307
308
            // ...and trim off any of those underscores hanging around
309 112
            $name = ltrim($name, '_');
310
311 112
            $this->style->set($method);
312 112
        }
313
314 552
        return $name;
315
    }
316
317
    /**
318
     * Search for any style methods within the name and apply them
319
     *
320
     * @param  string $name
321
     * @param  array $method_search
322
     *
323
     * @return string Anything left over after applying styles
324
     */
325 552
    protected function applyStyleMethods($name, $method_search = null)
326
    {
327
        // Get all of the possible style attributes
328 552
        $method_search = $method_search ?: array_keys($this->style->all());
329
330 552
        $new_name = $this->searchForStyleMethods($name, $method_search);
331
332
        // While we still have a name left and we keep finding methods,
333
        // loop through the possibilities
334 552
        if (strlen($new_name) > 0 && $new_name != $name) {
335 36
            return $this->applyStyleMethods($new_name, $method_search);
336
        }
337
338 552
        return $new_name;
339
    }
340
341
    /**
342
     * Search for style methods in the current name
343
     *
344
     * @param string $name
345
     * @param array $search
346
     * @return string
347
     */
348 552
    protected function searchForStyleMethods($name, $search)
349
    {
350
        // Loop through the possible methods
351 552
        foreach ($search as $method) {
352
            // See if we found a valid method
353 552
            $name = $this->parseStyleMethod($method, $name);
354 552
        }
355
356 552
        return $name;
357
    }
358
359
    /**
360
     * Build up the terminal object and return it
361
     *
362
     * @param string $name
363
     * @param array $arguments
364
     *
365
     * @return object|null
366
     */
367 552
    protected function buildTerminalObject($name, $arguments)
368
    {
369
        // Retrieve the parser for the current set of styles
370 552
        $parser = $this->style->parser($this->util->system);
371
372
        // Reset the styles
373 552
        $this->style->reset();
374
375
        // Execute the terminal object
376 552
        $this->router->settings($this->settings);
377 552
        $this->router->parser($parser);
378 552
        $this->router->output($this->output);
379 552
        $this->router->util($this->util);
380
381 552
        return $this->router->execute($name, $arguments);
382
    }
383
384
    /**
385
     * Route anything leftover after styles were applied
386
     *
387
     * @param string $name
388
     * @param array $arguments
389
     *
390
     * @return object|null
391
     */
392 552
    protected function routeRemainingMethod($name, array $arguments)
393
    {
394
        // If we still have something left, let's figure out what it is
395 552
        if ($this->router->exists($name)) {
396 552
            $obj = $this->buildTerminalObject($name, $arguments);
397
398
            // If something was returned, return it
399 552
            if (is_object($obj)) {
400 208
                return $obj;
401
            }
402 388
        } elseif ($this->settings->exists($name)) {
403 44
            $this->settings->add($name, reset($arguments));
404
        // Handle passthroughs to the arguments manager.
405 44
        } else {
406
            // If we can't find it at this point, let's fail gracefully
407 4
            $this->out(reset($arguments));
408
        }
409 388
    }
410
411
    /**
412
     * Magic method for anything called that doesn't exist
413
     *
414
     * @param string $requested_method
415
     * @param array  $arguments
416
     *
417
     * @return \League\CLImate\CLImate|\League\CLImate\TerminalObject\Dynamic\DynamicTerminalObject
418
     *
419
     * List of many of the possible method being called here
420
     * documented at the top of this class.
421
     */
422 552
    public function __call($requested_method, $arguments)
423
    {
424
        // Apply any style methods that we can find first
425 552
        $name = $this->applyStyleMethods(Helper::snakeCase($requested_method));
426
427
        // The first argument is the string|array|object we want to echo out
428 552
        $output = reset($arguments);
429
430 552
        if (strlen($name)) {
431
            // If we have something left, let's try and route it to the appropriate place
432 552
            if ($result = $this->routeRemainingMethod($name, $arguments)) {
433 208
                return $result;
434
            }
435 388
        } elseif ($this->hasOutput($output)) {
436
            // If we have fulfilled all of the requested methods and we have output, output it
437 48
            $this->out($output);
438 48
        }
439
440 388
        return $this;
441
    }
442
}
443