CLImate::setRouter()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 1
cts 1
cp 1
cc 1
nc 1
nop 1
crap 1
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\Dynamic\Spinner;
9
use League\CLImate\TerminalObject\Router\Router;
10
use League\CLImate\Util\Helper;
11
use League\CLImate\Util\Output;
12
use League\CLImate\Util\UtilFactory;
13
14
/**
15
 * @method CLImate black(string $str = null)
16
 * @method CLImate red(string $str = null)
17
 * @method CLImate green(string $str = null)
18
 * @method CLImate yellow(string $str = null)
19
 * @method CLImate blue(string $str = null)
20
 * @method CLImate magenta(string $str = null)
21
 * @method CLImate cyan(string $str = null)
22
 * @method CLImate lightGray(string $str = null)
23
 * @method CLImate darkGray(string $str = null)
24
 * @method CLImate lightRed(string $str = null)
25
 * @method CLImate lightGreen(string $str = null)
26
 * @method CLImate lightYellow(string $str = null)
27
 * @method CLImate lightBlue(string $str = null)
28
 * @method CLImate lightMagenta(string $str = null)
29
 * @method CLImate lightCyan(string $str = null)
30
 * @method CLImate white(string $str = null)
31
 *
32
 * @method CLImate backgroundBlack(string $str = null)
33
 * @method CLImate backgroundRed(string $str = null)
34
 * @method CLImate backgroundGreen(string $str = null)
35
 * @method CLImate backgroundYellow(string $str = null)
36
 * @method CLImate backgroundBlue(string $str = null)
37
 * @method CLImate backgroundMagenta(string $str = null)
38
 * @method CLImate backgroundCyan(string $str = null)
39
 * @method CLImate backgroundLightGray(string $str = null)
40
 * @method CLImate backgroundDarkGray(string $str = null)
41
 * @method CLImate backgroundLightRed(string $str = null)
42
 * @method CLImate backgroundLightGreen(string $str = null)
43
 * @method CLImate backgroundLightYellow(string $str = null)
44
 * @method CLImate backgroundLightBlue(string $str = null)
45
 * @method CLImate backgroundLightMagenta(string $str = null)
46
 * @method CLImate backgroundLightCyan(string $str = null)
47
 * @method CLImate backgroundWhite(string $str = null)
48
 *
49
 * @method CLImate bold(string $str = null)
50
 * @method CLImate dim(string $str = null)
51
 * @method CLImate underline(string $str = null)
52
 * @method CLImate blink(string $str = null)
53
 * @method CLImate invert(string $str = null)
54
 * @method CLImate hidden(string $str = null)
55
 *
56
 * @method CLImate info(string $str = null)
57
 * @method CLImate comment(string $str = null)
58
 * @method CLImate whisper(string $str = null)
59
 * @method CLImate shout(string $str = null)
60
 * @method CLImate error(string $str = null)
61
 *
62
 * @method mixed out(string $str)
63
 * @method mixed inline(string $str)
64
 * @method mixed table(array $data)
65
 * @method mixed json(mixed $var)
66
 * @method mixed br($count = 1)
67
 * @method mixed tab($count = 1)
68
 * @method mixed draw(string $art)
69
 * @method mixed border(string $char = null, integer $length = null)
70
 * @method mixed dump(mixed $var)
71
 * @method mixed flank(string $output, string $char = null, integer $length = null)
72
 * @method mixed progress(integer $total = null)
73
 * @method Spinner spinner(string $label = null, string ...$characters = null)
74
 * @method mixed padding(integer $length = 0, string $char = '.')
75
 * @method mixed input(string $prompt, Util\Reader\ReaderInterface $reader = null)
76
 * @method mixed confirm(string $prompt, Util\Reader\ReaderInterface $reader = null)
77
 * @method mixed password(string $prompt, Util\Reader\ReaderInterface $reader = null)
78
 * @method mixed checkboxes(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
79
 * @method mixed radio(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null)
80
 * @method mixed animation(string $art, TerminalObject\Helper\Sleeper $sleeper = null)
81
 * @method mixed columns(array $data, $column_count = null)
82
 * @method mixed clear()
83
 * @method CLImate clearLine()
84
 *
85
 * @method CLImate addArt(string $dir)
86
 */
87
class CLImate
88
{
89
    /**
90
     * An instance of the Style class
91
     *
92
     * @var \League\CLImate\Decorator\Style $style
93
     */
94
    public $style;
95
96
    /**
97
     * An instance of the Terminal Object Router class
98
     *
99
     * @var \League\CLImate\TerminalObject\Router\Router $router
100
     */
101
    protected $router;
102
103
    /**
104
     * An instance of the Settings Manager class
105
     *
106
     * @var \League\CLImate\Settings\Manager $settings
107
     */
108
    protected $settings;
109
110
    /**
111
     * An instance of the Argument Manager class
112
     *
113
     * @var \League\CLImate\Argument\Manager $arguments
114
     */
115
    public $arguments;
116
117
    /**
118
     * An instance of the Output class
119
     *
120
     * @var \League\CLImate\Util\Output $output
121
     */
122
    public $output;
123
124
    /**
125
     * An instance of the Util Factory
126
     *
127
     * @var \League\CLImate\Util\UtilFactory $util
128 948
     */
129
    protected $util;
130 948
131 948
    public function __construct()
132 948
    {
133 948
        $this->setStyle(new Style());
134 948
        $this->setRouter(new Router());
135 948
        $this->setSettingsManager(new SettingsManager());
136 948
        $this->setOutput(new Output());
137
        $this->setUtil(new UtilFactory());
138
        $this->setArgumentManager(new ArgumentManager());
139
    }
140
141
    /**
142
     * Set the style property
143 948
     *
144
     * @param \League\CLImate\Decorator\Style $style
145 948
     */
146 948
    public function setStyle(Style $style)
147
    {
148
        $this->style = $style;
149
    }
150
151
    /**
152
     * Set the router property
153 948
     *
154
     * @param \League\CLImate\TerminalObject\Router\Router $router
155 948
     */
156 948
    public function setRouter(Router $router)
157
    {
158
        $this->router = $router;
159
    }
160
161
    /**
162
     * Set the settings property
163 948
     *
164
     * @param \League\CLImate\Settings\Manager $manager
165 948
     */
166 948
    public function setSettingsManager(SettingsManager $manager)
167
    {
168
        $this->settings = $manager;
169
    }
170
171
    /**
172
     * Set the arguments property
173 948
     *
174
     * @param \League\CLImate\Argument\Manager $manager
175 948
     */
176 948
    public function setArgumentManager(ArgumentManager $manager)
177
    {
178
        $this->arguments = $manager;
179
    }
180
181
    /**
182
     * Set the output property
183 948
     *
184
     * @param \League\CLImate\Util\Output $output
185 948
     */
186 948
    public function setOutput(Output $output)
187
    {
188
        $this->output = $output;
189
    }
190
191
    /**
192
     * Set the util property
193 948
     *
194
     * @param \League\CLImate\Util\UtilFactory $util
195 948
     */
196 948
    public function setUtil(UtilFactory $util)
197
    {
198
        $this->util = $util;
199
    }
200
201
    /**
202
     * Extend CLImate with custom methods
203
     *
204
     * @param string|object|array $class
205
     * @param string $key Optional custom key instead of class name
206 36
     *
207
     * @return \League\CLImate\CLImate
208 36
     */
209
    public function extend($class, $key = null)
210 28
    {
211
        $this->router->addExtension($key, $class);
0 ignored issues
show
Bug introduced by Joe Tannenbaum
It seems like $class defined by parameter $class on line 209 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...
212
213
        return $this;
214
    }
215
216
    /**
217
     * Force ansi support on
218 4
     *
219
     * @return \League\CLImate\CLImate
220 4
     */
221
    public function forceAnsiOn()
222 4
    {
223
        $this->util->system->forceAnsi();
224
225
        return $this;
226
    }
227
228
    /**
229
     * Force ansi support off
230 4
     *
231
     * @return \League\CLImate\CLImate
232 4
     */
233
    public function forceAnsiOff()
234 4
    {
235
        $this->util->system->forceAnsi(false);
236
237
        return $this;
238
    }
239
240
    /**
241
     * Write line to writer once
242
     *
243
     * @param string|array $writer
244 4
     *
245
     * @return \League\CLImate\CLImate
246 4
     */
247
    public function to($writer)
248 4
    {
249
        $this->output->once($writer);
250
251
        return $this;
252
    }
253
254
    /**
255
     * Output the program's usage statement
256 4
     *
257
     * @param array $argv
258 4
     */
259
    public function usage(array $argv = null)
260
    {
261
        return $this->arguments->usage($this, $argv);
262
    }
263
264
    /**
265
     * Set the program's description
266
     *
267
     * @param string $description
268 4
     *
269
     * @return \League\CLImate\CLImate
270 4
     */
271
    public function description($description)
272 4
    {
273
        $this->arguments->description($description);
274
275
        return $this;
276
    }
277
278
    /**
279
     * Check if we have valid output
280
     *
281
     * @param  mixed   $output
282 76
     *
283
     * @return boolean
284 76
     */
285 48
    protected function hasOutput($output)
286
    {
287
        if (!empty($output)) {
288
            return true;
289 40
        }
290
291
        // Check for type first to avoid errors with objects/arrays/etc
292
        return ((is_string($output) || is_numeric($output)) && strlen($output) > 0);
293
    }
294
295
    /**
296
     * Search for the method within the string
297
     * and route it if we find one.
298
     *
299
     * @param  string $method
300
     * @param  string $name
301 568
     *
302
     * @return string The new string without the executed method.
303
     */
304 568
    protected function parseStyleMethod($method, $name)
305
    {
306 112
        // If the name starts with this method string...
307
        if (substr($name, 0, strlen($method)) == $method) {
308
            // ...remove the method name from the beginning of the string...
309 112
            $name = substr($name, strlen($method));
310
311 112
            // ...and trim off any of those underscores hanging around
312 112
            $name = ltrim($name, '_');
313
314 568
            $this->style->set($method);
315
        }
316
317
        return $name;
318
    }
319
320
    /**
321
     * Search for any style methods within the name and apply them
322
     *
323
     * @param  string $name
324
     * @param  array $method_search
325 568
     *
326
     * @return string Anything left over after applying styles
327
     */
328 568
    protected function applyStyleMethods($name, $method_search = null)
329
    {
330 568
        // Get all of the possible style attributes
331
        $method_search = $method_search ?: array_keys($this->style->all());
332
333
        $new_name = $this->searchForStyleMethods($name, $method_search);
334 568
335 36
        // While we still have a name left and we keep finding methods,
336
        // loop through the possibilities
337
        if (strlen($new_name) > 0 && $new_name != $name) {
338 568
            return $this->applyStyleMethods($new_name, $method_search);
339
        }
340
341
        return $new_name;
342
    }
343
344
    /**
345
     * Search for style methods in the current name
346
     *
347
     * @param string $name
348 568
     * @param array $search
349
     * @return string
350
     */
351 568
    protected function searchForStyleMethods($name, $search)
352
    {
353 568
        // Loop through the possible methods
354 568
        foreach ($search as $method) {
355
            // See if we found a valid method
356 568
            $name = $this->parseStyleMethod($method, $name);
357
        }
358
359
        return $name;
360
    }
361
362
    /**
363
     * Build up the terminal object and return it
364
     *
365
     * @param string $name
366
     * @param array $arguments
367 568
     *
368
     * @return object|null
369
     */
370 568
    protected function buildTerminalObject($name, $arguments)
371
    {
372
        // Retrieve the parser for the current set of styles
373 568
        $parser = $this->style->parser($this->util->system);
374
375
        // Reset the styles
376 568
        $this->style->reset();
377 568
378 568
        // Execute the terminal object
379 568
        $this->router->settings($this->settings);
380
        $this->router->parser($parser);
381 568
        $this->router->output($this->output);
382
        $this->router->util($this->util);
383
384
        return $this->router->execute($name, $arguments);
385
    }
386
387
    /**
388
     * Route anything leftover after styles were applied
389
     *
390
     * @param string $name
391
     * @param array $arguments
392 568
     *
393
     * @return object|null
394
     */
395 568
    protected function routeRemainingMethod($name, array $arguments)
396 568
    {
397
        // If we still have something left, let's figure out what it is
398
        if ($this->router->exists($name)) {
399 568
            $obj = $this->buildTerminalObject($name, $arguments);
400 224
401
            // If something was returned, return it
402 388
            if (is_object($obj)) {
403 44
                return $obj;
404
            }
405 44
        } elseif ($this->settings->exists($name)) {
406
            $this->settings->add($name, reset($arguments));
407 4
        // Handle passthroughs to the arguments manager.
408
        } else {
409 388
            // If we can't find it at this point, let's fail gracefully
410
            $this->out(reset($arguments));
411
        }
412
    }
413
414
    /**
415
     * Magic method for anything called that doesn't exist
416
     *
417
     * @param string $requested_method
418
     * @param array  $arguments
419
     *
420
     * @return \League\CLImate\CLImate|\League\CLImate\TerminalObject\Dynamic\DynamicTerminalObject
421
     *
422 568
     * List of many of the possible method being called here
423
     * documented at the top of this class.
424
     */
425 568
    public function __call($requested_method, $arguments)
426
    {
427
        // Apply any style methods that we can find first
428 568
        $name = $this->applyStyleMethods(Helper::snakeCase($requested_method));
429
430 568
        // The first argument is the string|array|object we want to echo out
431
        $output = reset($arguments);
432 568
433 224
        if (strlen($name)) {
434
            // If we have something left, let's try and route it to the appropriate place
435 388
            if ($result = $this->routeRemainingMethod($name, $arguments)) {
436
                return $result;
437 48
            }
438 48
        } elseif ($this->hasOutput($output)) {
439
            // If we have fulfilled all of the requested methods and we have output, output it
440 388
            $this->out($output);
441
        }
442
443
        return $this;
444
    }
445
}
446