This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Weew\Console; |
||
4 | |||
5 | use Exception; |
||
6 | use Weew\Console\Commands\GlobalFormatCommand; |
||
7 | use Weew\Console\Commands\GlobalHelpCommand; |
||
8 | use Weew\Console\Commands\GlobalNoInteractionCommand; |
||
9 | use Weew\Console\Commands\GlobalPassthroughCommand; |
||
10 | use Weew\Console\Commands\GlobalSilentModeCommand; |
||
11 | use Weew\Console\Commands\GlobalVerbosityCommand; |
||
12 | use Weew\Console\Commands\HelpCommand; |
||
13 | use Weew\Console\Commands\ListCommand; |
||
14 | use Weew\Console\Commands\GlobalVersionCommand; |
||
15 | use Weew\Console\Exceptions\InvalidCommandException; |
||
16 | use Weew\Console\Widgets\ExceptionWidget; |
||
17 | use Weew\ConsoleArguments\ArgumentsMatcher; |
||
18 | use Weew\ConsoleArguments\ArgumentsParser; |
||
19 | use Weew\ConsoleArguments\Command; |
||
20 | use Weew\ConsoleArguments\Exceptions\MissingCommandNameException; |
||
21 | use Weew\ConsoleArguments\IArgumentsMatcher; |
||
22 | use Weew\ConsoleArguments\IArgumentsParser; |
||
23 | use Weew\ConsoleArguments\ICommand; |
||
24 | use Weew\ConsoleFormatter\ConsoleFormatter; |
||
25 | use Weew\ConsoleFormatter\IConsoleFormatter; |
||
26 | |||
27 | class Console implements IConsole { |
||
28 | /** |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $title; |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | protected $description; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $version = '1.0'; |
||
42 | |||
43 | /** |
||
44 | * @var bool |
||
45 | */ |
||
46 | protected $allowParallel = true; |
||
47 | |||
48 | /** |
||
49 | * @var bool |
||
50 | */ |
||
51 | protected $catchErrors = true; |
||
52 | |||
53 | /** |
||
54 | * @var object[] |
||
55 | */ |
||
56 | protected $commands = []; |
||
57 | |||
58 | /** |
||
59 | * @var string |
||
60 | */ |
||
61 | protected $defaultCommandName = 'list'; |
||
62 | |||
63 | /** |
||
64 | * @var ICommandInvoker |
||
65 | */ |
||
66 | protected $commandInvoker; |
||
67 | |||
68 | /** |
||
69 | * @var ICommandExecutionLock |
||
70 | */ |
||
71 | protected $commandExecutionLock; |
||
72 | |||
73 | /** |
||
74 | * @var IArgumentsParser |
||
75 | */ |
||
76 | protected $argumentsParser; |
||
77 | |||
78 | /** |
||
79 | * @var IArgumentsMatcher |
||
80 | */ |
||
81 | protected $argumentsMatcher; |
||
82 | |||
83 | /** |
||
84 | * @var IConsoleFormatter |
||
85 | */ |
||
86 | protected $consoleFormatter; |
||
87 | |||
88 | /** |
||
89 | * @var IOutput |
||
90 | */ |
||
91 | protected $output; |
||
92 | |||
93 | /** |
||
94 | * @var IInput |
||
95 | */ |
||
96 | protected $input; |
||
97 | |||
98 | /** |
||
99 | * Console constructor. |
||
100 | * |
||
101 | * @param ICommandInvoker $commandInvoker |
||
102 | * @param ICommandExecutionLock $commandExecutionLock |
||
103 | */ |
||
104 | public function __construct( |
||
105 | ICommandInvoker $commandInvoker = null, |
||
106 | ICommandExecutionLock $commandExecutionLock = null |
||
107 | ) { |
||
108 | if ( ! $commandInvoker instanceof ICommandInvoker) { |
||
109 | $commandInvoker = $this->createCommandInvoker(); |
||
110 | } |
||
111 | |||
112 | if ( ! $commandExecutionLock instanceof ICommandExecutionLock) { |
||
113 | $commandExecutionLock = $this->createCommandExecutionLock(); |
||
114 | } |
||
115 | |||
116 | $this->argumentsParser = new ArgumentsParser(); |
||
117 | $this->argumentsMatcher = new ArgumentsMatcher($this->argumentsParser); |
||
118 | |||
119 | $this->setCommandInvoker($commandInvoker); |
||
120 | $this->setCommandExecutionLock($commandExecutionLock); |
||
121 | $this->setConsoleFormatter(new ConsoleFormatter()); |
||
122 | $this->setOutput(new Output($this->consoleFormatter)); |
||
123 | $this->setInput(new Input()); |
||
124 | |||
125 | $this->addDefaultCommands(); |
||
126 | $this->addDefaultStyles(); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * @return string |
||
131 | */ |
||
132 | public function getTitle() { |
||
133 | return $this->title; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * @param string $title |
||
138 | * |
||
139 | * @return IConsole |
||
140 | */ |
||
141 | public function setTitle($title) { |
||
142 | $this->title = $title; |
||
143 | |||
144 | return $this; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * @return string |
||
149 | */ |
||
150 | public function getDescription() { |
||
151 | return $this->description; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * @param string $description |
||
156 | * |
||
157 | * @return IConsole |
||
158 | */ |
||
159 | public function setDescription($description) { |
||
160 | $this->description = $description; |
||
161 | |||
162 | return $this; |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * @return string |
||
167 | */ |
||
168 | public function getVersion() { |
||
169 | return $this->version; |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * @param string $version |
||
174 | * |
||
175 | * @return IConsole |
||
176 | */ |
||
177 | public function setVersion($version) { |
||
178 | $this->version = $version; |
||
179 | |||
180 | return $this; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * @return bool |
||
185 | */ |
||
186 | public function getAllowParallel() { |
||
187 | return $this->allowParallel; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * @param bool $allowParallel |
||
192 | * |
||
193 | * @return IConsole |
||
194 | */ |
||
195 | public function setAllowParallel($allowParallel) { |
||
196 | $this->allowParallel = $allowParallel; |
||
197 | |||
198 | return $this; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * @return bool |
||
203 | */ |
||
204 | public function getCatchErrors() { |
||
205 | return $this->catchErrors; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * @param bool $catchErrors |
||
210 | * |
||
211 | * @return IConsole |
||
212 | */ |
||
213 | public function setCatchErrors($catchErrors) { |
||
214 | $this->catchErrors = $catchErrors; |
||
215 | |||
216 | return $this; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * @return ICommand[] |
||
221 | */ |
||
222 | public function getCommands() { |
||
223 | return $this->commands; |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * @param object[] $commands |
||
228 | */ |
||
229 | public function setCommands(array $commands) { |
||
230 | $this->commands = []; |
||
231 | $this->addCommands($commands); |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * @param object[] $commands |
||
236 | */ |
||
237 | public function addCommands(array $commands) { |
||
238 | foreach ($commands as $command) { |
||
239 | $this->addCommand($command); |
||
240 | } |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * @param object $command |
||
245 | */ |
||
246 | public function addCommand($command) { |
||
247 | if ($command instanceof ICommand) { |
||
248 | $consoleCommand = $command; |
||
249 | $command = $consoleCommand->getHandler(); |
||
250 | } else { |
||
251 | $consoleCommand = new Command(); |
||
252 | } |
||
253 | |||
254 | $this->validateCommand($command); |
||
255 | |||
256 | if ( ! is_object($command)) { |
||
257 | $command = $this->commandInvoker->create($command); |
||
258 | } |
||
259 | |||
260 | $consoleCommand->setHandler($command); |
||
261 | |||
262 | $this->commandInvoker->setup($command, $consoleCommand); |
||
263 | $this->commands[] = $consoleCommand; |
||
264 | } |
||
265 | |||
266 | |||
267 | /** |
||
268 | * @return string |
||
269 | */ |
||
270 | public function getDefaultCommandName() { |
||
271 | return $this->defaultCommandName; |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * @param string $commandName |
||
276 | */ |
||
277 | public function setDefaultCommandName($commandName) { |
||
278 | $this->defaultCommandName = $commandName; |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * @param array $argv |
||
283 | */ |
||
284 | public function parseArgv(array $argv = null) { |
||
285 | if ( ! is_array($argv)) { |
||
286 | global $argv; |
||
0 ignored issues
–
show
|
|||
287 | } |
||
288 | |||
289 | $this->parseArgs(array_slice($argv, 1)); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * @param array $args |
||
294 | */ |
||
295 | public function parseArgs(array $args) { |
||
296 | $this->parseString(implode(' ', $args)); |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * @param $string |
||
301 | */ |
||
302 | public function parseString($string) { |
||
303 | $this->handleArgs($this->argumentsParser->parse($string)); |
||
304 | } |
||
305 | |||
306 | /** |
||
307 | * @return IConsoleFormatter |
||
308 | */ |
||
309 | public function getConsoleFormatter() { |
||
310 | return $this->consoleFormatter; |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * @param IConsoleFormatter $consoleFormatter |
||
315 | */ |
||
316 | public function setConsoleFormatter(IConsoleFormatter $consoleFormatter) { |
||
317 | $this->consoleFormatter = $consoleFormatter; |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @return IOutput |
||
322 | */ |
||
323 | public function getOutput() { |
||
324 | return $this->output; |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * @param IOutput $output |
||
329 | */ |
||
330 | public function setOutput(IOutput $output) { |
||
331 | $this->output = $output; |
||
332 | } |
||
333 | |||
334 | /** |
||
335 | * @return IInput |
||
336 | */ |
||
337 | public function getInput() { |
||
338 | return $this->input; |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * @param IInput $input |
||
343 | */ |
||
344 | public function setInput(IInput $input) { |
||
345 | $this->input = $input; |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * @return ICommandInvoker |
||
350 | */ |
||
351 | public function getCommandInvoker() { |
||
352 | return $this->commandInvoker; |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * @param ICommandInvoker $commandInvoker |
||
357 | */ |
||
358 | public function setCommandInvoker(ICommandInvoker $commandInvoker) { |
||
359 | $this->commandInvoker = $commandInvoker; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * @return ICommandExecutionLock |
||
364 | */ |
||
365 | public function getCommandExecutionLock() { |
||
366 | return $this->commandExecutionLock; |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * @param ICommandExecutionLock $commandExecutionLock |
||
371 | */ |
||
372 | public function setCommandExecutionLock(ICommandExecutionLock $commandExecutionLock) { |
||
373 | $this->commandExecutionLock = $commandExecutionLock; |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * @param array $args |
||
378 | * |
||
379 | * @throws Exception |
||
380 | */ |
||
381 | protected function handleArgs(array $args) { |
||
382 | $groupedArgs = $this->argumentsParser->group($args); |
||
383 | list($groupedArgs, $continue) = $this->runGlobalCommands($groupedArgs); |
||
384 | |||
385 | if ($continue === false) { |
||
386 | return; |
||
387 | } |
||
388 | |||
389 | try { |
||
390 | list($command, $groupedArgs) = $this->argumentsMatcher |
||
0 ignored issues
–
show
The assignment to
$groupedArgs is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
391 | ->matchCommands($this->getNotGlobalCommands(), $groupedArgs); |
||
392 | $command = clone $command; |
||
393 | $this->runCommand($command); |
||
394 | } catch (MissingCommandNameException $ex) { |
||
395 | array_unshift($args, $this->getDefaultCommandName()); |
||
396 | $this->parseArgs($args); |
||
397 | } catch (Exception $ex) { |
||
398 | View Code Duplication | if ($this->getCatchErrors()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
399 | $widget = new ExceptionWidget($this->input, $this->output); |
||
400 | $widget->render($ex); |
||
401 | } else { |
||
402 | throw $ex; |
||
403 | } |
||
404 | } |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * @param ICommand $command |
||
409 | * @param bool $isolate |
||
410 | * |
||
411 | * @return mixed |
||
412 | * @throws Exception |
||
413 | */ |
||
414 | protected function runCommand(ICommand $command, $isolate = true) { |
||
415 | try { |
||
416 | if ( ! $command->isGlobal()) { |
||
417 | $this->commandExecutionLock->lockCommand($command, $this->getAllowParallel()); |
||
418 | } |
||
419 | |||
420 | if ($isolate) { |
||
421 | $input = clone $this->input; |
||
422 | $output = clone $this->output; |
||
423 | } else { |
||
424 | $input = $this->input; |
||
425 | $output = $this->output; |
||
426 | } |
||
427 | |||
428 | $input->setCommand($command); |
||
429 | |||
430 | return $this->commandInvoker->run( |
||
431 | $command->getHandler(), $input, $output, $this |
||
432 | ); |
||
433 | } catch (Exception $ex) { |
||
434 | View Code Duplication | if ($this->getCatchErrors()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
435 | $widget = new ExceptionWidget($this->input, $this->output); |
||
436 | $widget->render($ex); |
||
437 | } else { |
||
438 | throw $ex; |
||
439 | } |
||
440 | } |
||
441 | } |
||
442 | |||
443 | /** |
||
444 | * @param array $groupedArgs |
||
445 | * |
||
446 | * @return bool |
||
447 | */ |
||
448 | protected function runGlobalCommands(array $groupedArgs) { |
||
449 | // run commands that are global but will for sure |
||
450 | // not generate any output or interrupt the flow |
||
451 | foreach ($this->getGlobalHiddenCommands() as $command) { |
||
452 | $command = clone $command; |
||
453 | $groupedArgs = $this->argumentsMatcher->matchCommand($command, $groupedArgs, false); |
||
454 | $this->runCommand($command, false); |
||
455 | } |
||
456 | |||
457 | // run commands that might generate output or |
||
458 | // try to interrupt the flow |
||
459 | foreach ($this->getGlobalNotHiddenCommands() as $command) { |
||
460 | $command = clone $command; |
||
461 | |||
462 | // dirty hack, fix later |
||
463 | // global commands should not steal arguments |
||
464 | $args = $groupedArgs['arguments']; |
||
465 | $groupedArgs = $this->argumentsMatcher->matchCommand($command, $groupedArgs, false); |
||
466 | $groupedArgs['arguments'] = $args; |
||
467 | $continue = $this->runCommand($command); |
||
468 | |||
469 | if ($continue === false) { |
||
470 | return [$groupedArgs, false]; |
||
471 | } |
||
472 | } |
||
473 | |||
474 | return [$groupedArgs, true]; |
||
475 | } |
||
476 | |||
477 | /** |
||
478 | * @param $command |
||
479 | * |
||
480 | * @throws InvalidCommandException |
||
481 | */ |
||
482 | protected function validateCommand($command) { |
||
483 | if ( ! is_string($command) && ! is_object($command)) { |
||
484 | throw new InvalidCommandException(s( |
||
485 | 'Command must be either a class name or an instance, "%s" given.', |
||
486 | get_type($command) |
||
487 | )); |
||
488 | } |
||
489 | |||
490 | if (is_string($command) && ! class_exists($command)) { |
||
491 | throw new InvalidCommandException(s( |
||
492 | 'Command "%s" does not exist.', |
||
493 | $command |
||
494 | )); |
||
495 | } |
||
496 | |||
497 | if ( ! method_exists($command, 'setup') || ! method_exists($command, 'run')) { |
||
498 | throw new InvalidCommandException(s( |
||
499 | 'Command "%s" must implement methods "setup" and "run".', |
||
500 | get_type($command) |
||
501 | )); |
||
502 | } |
||
503 | } |
||
504 | |||
505 | /** |
||
506 | * @return ICommandInvoker |
||
507 | */ |
||
508 | protected function createCommandInvoker() { |
||
509 | return new CommandInvoker(); |
||
510 | } |
||
511 | |||
512 | /** |
||
513 | * @return ICommandExecutionLock |
||
514 | */ |
||
515 | private function createCommandExecutionLock() { |
||
516 | return new CommandExecutionLock(); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * Register default command handlers. |
||
521 | */ |
||
522 | protected function addDefaultCommands() { |
||
523 | $this->addCommands([ |
||
524 | new GlobalVersionCommand(), |
||
525 | new GlobalFormatCommand(), |
||
526 | new GlobalSilentModeCommand(), |
||
527 | new GlobalNoInteractionCommand(), |
||
528 | new GlobalHelpCommand(), |
||
529 | new GlobalVerbosityCommand(), |
||
530 | new GlobalPassthroughCommand(), |
||
531 | new ListCommand(), |
||
532 | new HelpCommand(), |
||
533 | ]); |
||
534 | } |
||
535 | |||
536 | /** |
||
537 | * Register default formatter styles. |
||
538 | */ |
||
539 | protected function addDefaultStyles() { |
||
540 | $this->consoleFormatter->style('error')->parseStyle('clr=white bg=red'); |
||
541 | $this->consoleFormatter->style('warning')->parseStyle('clr=black bg=yellow'); |
||
542 | $this->consoleFormatter->style('success')->parseStyle('clr=black bg=green'); |
||
543 | |||
544 | $this->consoleFormatter->style('question')->parseStyle('clr=green'); |
||
545 | $this->consoleFormatter->style('header')->parseStyle('clr=yellow'); |
||
546 | $this->consoleFormatter->style('title')->parseStyle('clr=yellow'); |
||
547 | $this->consoleFormatter->style('keyword')->parseStyle('clr=green'); |
||
548 | |||
549 | $this->consoleFormatter->style('green')->parseStyle('clr=green'); |
||
550 | $this->consoleFormatter->style('yellow')->parseStyle('clr=yellow'); |
||
551 | $this->consoleFormatter->style('red')->parseStyle('clr=red'); |
||
552 | $this->consoleFormatter->style('white')->parseStyle('clr=white'); |
||
553 | $this->consoleFormatter->style('blue')->parseStyle('clr=blue'); |
||
554 | $this->consoleFormatter->style('gray')->parseStyle('clr=gray'); |
||
555 | $this->consoleFormatter->style('black')->parseStyle('clr=black'); |
||
556 | |||
557 | $this->consoleFormatter->style('bold')->parseStyle('fmt=bold'); |
||
558 | $this->consoleFormatter->style('italic')->parseStyle('fmt=italic'); |
||
559 | $this->consoleFormatter->style('underline')->parseStyle('fmt=underline'); |
||
560 | $this->consoleFormatter->style('strikethrough')->parseStyle('fmt=strikethrough'); |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * @return ICommand[] |
||
565 | */ |
||
566 | View Code Duplication | protected function getGlobalHiddenCommands() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
567 | $commands = []; |
||
568 | |||
569 | foreach ($this->getCommands() as $command) { |
||
570 | if ($command->isGlobal() && $command->isHidden()) { |
||
571 | $commands[] = $command; |
||
572 | } |
||
573 | } |
||
574 | |||
575 | return $commands; |
||
576 | } |
||
577 | |||
578 | /** |
||
579 | * @return ICommand[] |
||
580 | */ |
||
581 | View Code Duplication | protected function getGlobalNotHiddenCommands() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
582 | $commands = []; |
||
583 | |||
584 | foreach ($this->getCommands() as $command) { |
||
585 | if ($command->isGlobal() && ! $command->isHidden()) { |
||
586 | $commands[] = $command; |
||
587 | } |
||
588 | } |
||
589 | |||
590 | return $commands; |
||
591 | } |
||
592 | |||
593 | /** |
||
594 | * @return ICommand[] |
||
595 | */ |
||
596 | View Code Duplication | protected function getNotGlobalCommands() { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
597 | $commands = []; |
||
598 | |||
599 | foreach ($this->getCommands() as $command) { |
||
600 | if ( ! $command->isGlobal()) { |
||
601 | $commands[] = $command; |
||
602 | } |
||
603 | } |
||
604 | |||
605 | return $commands; |
||
606 | } |
||
607 | } |
||
608 |
Instead of relying on
global
state, we recommend one of these alternatives:1. Pass all data via parameters
2. Create a class that maintains your state