GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AbstractCommander::execute()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
cc 2
eloc 4
c 3
b 1
f 1
nc 2
nop 0
dl 0
loc 6
rs 10
1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Kernel\Cli\Abstracts;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Kernel\Cli\Writers\Format;
19
use O2System\Kernel\Cli\Writers\Table;
20
21
/**
22
 * Class AbstractCommander
23
 *
24
 * @package O2System\Cli\Abstracts
25
 */
26
abstract class AbstractCommander
27
{
28
    /**
29
     * AbstractCommander::$commandName
30
     *
31
     * Command name.
32
     *
33
     * @var string
34
     */
35
    protected $commandName;
36
37
    /**
38
     * AbstractCommander::$commandVersion
39
     *
40
     * Command version.
41
     *
42
     * @var string
43
     */
44
    protected $commandVersion;
45
46
    /**
47
     * AbstractCommander::$commandDescription
48
     *
49
     * Command description.
50
     *
51
     * @var string
52
     */
53
    protected $commandDescription;
54
55
    /**
56
     * AbstractCommander::$commandOptions
57
     *
58
     * Command options.
59
     *
60
     * @var array
61
     */
62
    protected $commandOptions = [];
63
64
    /**
65
     * AbstractCommander::$commandOptionsShortcuts
66
     *
67
     * Command options.
68
     *
69
     * @var array
70
     */
71
    protected $commandOptionsShortcuts = [
72
        '-h'  => 'help',
73
        '-v'  => 'version',
74
        '-vv' => 'verbose',
75
    ];
76
77
    protected $actionsPool = [];
78
79
    /**
80
     * AbstractCommander::$verbose
81
     *
82
     * Command options.
83
     *
84
     * @var bool
85
     */
86
    protected $optionVerbose = false;
87
88
    // ------------------------------------------------------------------------
89
90
    /**
91
     * AbstractCommander::__construct
92
     *
93
     * Commander class constructor.
94
     *
95
     * @final   This method cannot be overwritten.
96
     */
97
    final public function __construct()
98
    {
99
        language()->loadFile('cli');
100
101
        $className = explode('Commanders\\', get_class($this));
102
        $className = str_replace('\\', '/', end($className));
103
        $this->commandName = implode('/', array_map('strtolower', explode('/', $className)));
104
105
        foreach ($this->commandOptions as $optionName => $optionConfig) {
106
            $shortcut = empty($optionConfig[ 'shortcut' ])
107
                ? '-' . substr($optionName, 0, 1)
108
                : '-' . rtrim($optionConfig[ 'shortcut' ]);
109
110
            if (array_key_exists($shortcut, $this->commandOptionsShortcuts)) {
111
                $shortcut = '-' . substr($optionName, 0, 2);
112
            }
113
114
            $this->commandOptions[ $optionName ][ 'shortcut' ] = $shortcut;
115
116
            $this->commandOptionsShortcuts[ $shortcut ] = $optionName;
117
        }
118
119
        if (array_key_exists('VERBOSE', $_ENV)) {
120
            $this->optionVerbose = true;
121
        }
122
    }
123
124
    // ------------------------------------------------------------------------
125
126
    /**
127
     * AbstractCommander::setCommandOptions
128
     *
129
     * Sets command options.
130
     *
131
     * @param array $commandOptions Array of commander options.
132
     *
133
     * @return static
134
     */
135
    public function setCommandOptions(array $commandOptions)
136
    {
137
        foreach ($commandOptions as $caller => $props) {
138
            call_user_func_array([&$this, 'addOption'], $props);
139
        }
140
141
        return $this;
142
    }
143
144
    // ------------------------------------------------------------------------
145
146
    /**
147
     * AbstractCommander::addCommandOption
148
     *
149
     * Add command option.
150
     *
151
     * @param string $optionName
152
     * @param string $optionDescription
153
     * @param string $optionShortcut
154
     */
155
    public function addCommandOption($optionName, $optionDescription, $optionShortcut = null)
156
    {
157
        $optionShortcut = empty($optionShortcut)
158
            ? '-' . substr($optionName, 0, 1)
159
            : '-' . rtrim($optionShortcut);
160
161
        $this->commandOptions[ $optionName ] = [
162
            'shortcut'    => $optionShortcut,
163
            'description' => $optionDescription,
164
        ];
165
    }
166
167
    // ------------------------------------------------------------------------
168
169
    /**
170
     * AbstractCommander::optionVersion
171
     *
172
     * Option version method, write commander version string.
173
     *
174
     * @return void
175
     */
176
    public function optionVersion()
177
    {
178
        if (property_exists($this, 'commandVersion')) {
179
            if ( ! empty($this->commandVersion)) {
180
                // Show Name & Version Line
181
                output()->write(
0 ignored issues
show
Bug introduced by
The method write() does not exist on O2System\Kernel\Http\Output. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
                output()->/** @scrutinizer ignore-call */ write(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
182
                    (new Format())
183
                        ->setContextualClass(Format::INFO)
184
                        ->setString(ucfirst($this->commandName) . ' v' . $this->commandVersion)
185
                        ->setNewLinesAfter(1)
186
                );
187
            }
188
        }
189
    }
190
191
    // ------------------------------------------------------------------------
192
193
    /**
194
     * AbstractCommander::optionVerbose
195
     *
196
     * Option verbose method, activate verbose output mode.
197
     *
198
     * @return void
199
     */
200
    public function optionVerbose()
201
    {
202
        $this->optionVerbose = true;
203
    }
204
205
    /**
206
     * AbstractCommander::__callOptions
207
     *
208
     * Options call executer.
209
     *
210
     * @return void
211
     * @throws \ReflectionException
212
     */
213
    protected function __callOptions()
214
    {
215
        if (false !== ($options = input()->get())) {
216
            if (count($options)) {
217
                $command = new \ReflectionClass($this);
218
219
                foreach ($options as $method => $arguments) {
220
221
                    if (array_key_exists('-' . $method, $this->commandOptionsShortcuts)) {
222
                        $method = $this->commandOptionsShortcuts[ '-' . $method ];
223
                    }
224
225
                    if ($command->hasMethod($commandMethodName = camelcase('option-' . $method))) {
226
                        $commandMethod = $command->getMethod($commandMethodName);
227
                    } elseif ($command->hasMethod($commandMethodName = camelcase($method))) {
228
                        $commandMethod = $command->getMethod($commandMethodName);
229
                    }
230
231
                    if ($commandMethod instanceof \ReflectionMethod) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $commandMethod does not seem to be defined for all execution paths leading up to this point.
Loading history...
232
                        if ($commandMethod->getNumberOfRequiredParameters() == 0) {
233
                            call_user_func([&$this, $commandMethodName]);
234
                        } elseif ($commandMethod->getNumberOfRequiredParameters() > 0 and empty($arguments)) {
235
                            if (isset($this->commandOptions[ $method ][ 'help' ])) {
236
                                output()->write(
237
                                    (new Format())
238
                                        ->setContextualClass(Format::INFO)
239
                                        ->setString(language()->getLine('CLI_USAGE') . ':')
240
                                        ->setNewLinesBefore(1)
241
                                        ->setNewLinesAfter(1)
242
                                );
243
244
                                output()->write(
245
                                    (new Format())
246
                                        ->setContextualClass(Format::INFO)
247
                                        ->setString(language()->getLine($this->commandOptions[ $method ][ 'help' ]))
248
                                        ->setNewLinesAfter(2)
249
                                );
250
                            }
251
                        } else {
252
                            $optionArguments = is_array($arguments)
253
                                ? $arguments
254
                                : [$arguments];
255
256
                            call_user_func_array([&$this, $commandMethodName], $optionArguments);
257
                        }
258
                    }
259
                }
260
            }
261
        }
262
    }
263
264
    // ------------------------------------------------------------------------
265
266
    /**
267
     * AbstractCommander::execute
268
     *
269
     * Default abstract commander execution to execute help option.
270
     *
271
     * @return void
272
     * @throws \ReflectionException
273
     */
274
    public function execute()
275
    {
276
        if (false !== ($options = input()->get())) {
0 ignored issues
show
Unused Code introduced by
The assignment to $options is dead and can be removed.
Loading history...
277
            $this->__callOptions();
278
        } else {
279
            $this->optionHelp();
280
        }
281
    }
282
283
    // ------------------------------------------------------------------------
284
285
    /**
286
     * AbstractCommander::optionHelp
287
     *
288
     * Option help method, write commander help.
289
     *
290
     * @return void
291
     * @throws \ReflectionException
292
     */
293
    final public function optionHelp()
294
    {
295
        // Show Usage
296
        output()->write(
297
            (new Format())
298
                ->setContextualClass(Format::INFO)
299
                ->setString(language()->getLine('CLI_USAGE') . ':')
300
                ->setNewLinesBefore(1)
301
                ->setNewLinesAfter(1)
302
        );
303
304
        // Show Actions
305
        $this->loadActions();
306
307
        if (count($this->actionsPool)) {
308
            output()->write(
309
                (new Format())
310
                    ->setContextualClass(Format::INFO)
311
                    ->setString($this->commandName . '/action --option=value')
312
            );
313
314
            output()->write(
315
                (new Format())
316
                    ->setString(language()->getLine('CLI_ACTIONS') . ':')
317
                    ->setNewLinesBefore(2)
318
                    ->setNewLinesAfter(1)
319
            );
320
321
            $table = new Table();
322
            $table->isShowBorder = false;
323
324
            foreach ($this->actionsPool as $action) {
325
326
                if ($action instanceof AbstractCommander) {
327
                    $table
328
                        ->addRow()
329
                        ->addColumn($action->getCommandName())
330
                        ->addColumn(language()->getLine($action->getCommandDescription()));
331
                }
332
            }
333
334
            output()->write(
335
                (new Format())
336
                    ->setString($table->render())
337
            );
338
        } else {
339
            output()->write(
340
                (new Format())
341
                    ->setContextualClass(Format::INFO)
342
                    ->setString($this->commandName . ' --option=value')
343
            );
344
        }
345
346
        // Show Options
347
        output()->write(
348
            (new Format())
349
                ->setString(language()->getLine('CLI_OPTIONS') . ':')
350
                ->setNewLinesBefore(2)
351
                ->setNewLinesAfter(1)
352
        );
353
354
        $table = new Table();
355
        $table->isShowBorder = false;
356
357
        foreach ($this->commandOptions as $optionCaller => $optionProps) {
358
            $table
359
                ->addRow()
360
                ->addColumn('--' . $optionCaller)
361
                ->addColumn($optionProps[ 'shortcut' ])
362
                ->addColumn(language()->getLine($optionProps[ 'description' ]));
363
        }
364
365
        output()->write(
366
            (new Format())
367
                ->setString($table->render())
368
                ->setNewLinesAfter(2)
369
        );
370
371
        exit(EXIT_SUCCESS);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
372
    }
373
374
    // ------------------------------------------------------------------------
375
376
    /**
377
     * AbstractCommander::loadActions
378
     *
379
     * Load all actions.
380
     *
381
     * @throws \ReflectionException
382
     */
383
    protected function loadActions()
384
    {
385
        $reflection = new \ReflectionClass($this);
386
        $actionNamespace = $reflection->name . '\\';
387
        $actionDirectory = get_class_name($reflection->name);
388
        $actionsPath = dirname($reflection->getFileName()) . DIRECTORY_SEPARATOR . $actionDirectory . DIRECTORY_SEPARATOR;
389
390
        foreach (glob($actionsPath . '*.php') as $filePath) {
391
            if (is_file($filePath)) {
392
                $commandClassName = $actionNamespace . pathinfo($filePath, PATHINFO_FILENAME);
393
                $this->addCommander(new $commandClassName);
394
            }
395
        }
396
    }
397
398
    // ------------------------------------------------------------------------
399
400
    /**
401
     * AbstractCommander::addCommander
402
     *
403
     * Add new commander to the pool.
404
     *
405
     * @param AbstractCommander $commander
406
     */
407
    public function addCommander(AbstractCommander $commander)
408
    {
409
        $this->actionsPool[ $commander->getCommandName() ] = $commander;
410
    }
411
412
    // ------------------------------------------------------------------------
413
414
    /**
415
     * AbstractCommander::getCommandName
416
     *
417
     * Gets command description.
418
     *
419
     * @return string
420
     */
421
    public function getCommandName()
422
    {
423
        return $this->commandName;
424
    }
425
426
    // ------------------------------------------------------------------------
427
428
    /**
429
     * AbstractCommander::getCommandDescription
430
     *
431
     * Gets command description.
432
     *
433
     * @return string
434
     */
435
    public function getCommandDescription()
436
    {
437
        return $this->commandDescription;
438
    }
439
440
    // ------------------------------------------------------------------------
441
442
    /**
443
     * AbstractCommander::setCommandDescription
444
     *
445
     * Sets command description.
446
     *
447
     * @param string $commandDescription
448
     *
449
     * @return static
450
     */
451
    public function setCommandDescription($commandDescription)
452
    {
453
        $this->commandDescription = trim($commandDescription);
454
455
        return $this;
456
    }
457
}