comparison vendor/symfony/console/Application.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 1fec387a4317
children af1871eacc83
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
9 * file that was distributed with this source code. 9 * file that was distributed with this source code.
10 */ 10 */
11 11
12 namespace Symfony\Component\Console; 12 namespace Symfony\Component\Console;
13 13
14 use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
15 use Symfony\Component\Console\Exception\ExceptionInterface;
16 use Symfony\Component\Console\Formatter\OutputFormatter;
17 use Symfony\Component\Console\Helper\DebugFormatterHelper;
18 use Symfony\Component\Console\Helper\Helper;
19 use Symfony\Component\Console\Helper\ProcessHelper;
20 use Symfony\Component\Console\Helper\QuestionHelper;
21 use Symfony\Component\Console\Input\InputInterface;
22 use Symfony\Component\Console\Input\StreamableInputInterface;
23 use Symfony\Component\Console\Input\ArgvInput;
24 use Symfony\Component\Console\Input\ArrayInput;
25 use Symfony\Component\Console\Input\InputDefinition;
26 use Symfony\Component\Console\Input\InputOption;
27 use Symfony\Component\Console\Input\InputArgument;
28 use Symfony\Component\Console\Input\InputAwareInterface;
29 use Symfony\Component\Console\Output\OutputInterface;
30 use Symfony\Component\Console\Output\ConsoleOutput;
31 use Symfony\Component\Console\Output\ConsoleOutputInterface;
32 use Symfony\Component\Console\Command\Command; 14 use Symfony\Component\Console\Command\Command;
33 use Symfony\Component\Console\Command\HelpCommand; 15 use Symfony\Component\Console\Command\HelpCommand;
34 use Symfony\Component\Console\Command\ListCommand; 16 use Symfony\Component\Console\Command\ListCommand;
35 use Symfony\Component\Console\Helper\HelperSet; 17 use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
36 use Symfony\Component\Console\Helper\FormatterHelper;
37 use Symfony\Component\Console\Event\ConsoleCommandEvent; 18 use Symfony\Component\Console\Event\ConsoleCommandEvent;
38 use Symfony\Component\Console\Event\ConsoleErrorEvent; 19 use Symfony\Component\Console\Event\ConsoleErrorEvent;
39 use Symfony\Component\Console\Event\ConsoleExceptionEvent; 20 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
40 use Symfony\Component\Console\Event\ConsoleTerminateEvent; 21 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
41 use Symfony\Component\Console\Exception\CommandNotFoundException; 22 use Symfony\Component\Console\Exception\CommandNotFoundException;
23 use Symfony\Component\Console\Exception\ExceptionInterface;
42 use Symfony\Component\Console\Exception\LogicException; 24 use Symfony\Component\Console\Exception\LogicException;
25 use Symfony\Component\Console\Formatter\OutputFormatter;
26 use Symfony\Component\Console\Helper\DebugFormatterHelper;
27 use Symfony\Component\Console\Helper\FormatterHelper;
28 use Symfony\Component\Console\Helper\Helper;
29 use Symfony\Component\Console\Helper\HelperSet;
30 use Symfony\Component\Console\Helper\ProcessHelper;
31 use Symfony\Component\Console\Helper\QuestionHelper;
32 use Symfony\Component\Console\Input\ArgvInput;
33 use Symfony\Component\Console\Input\ArrayInput;
34 use Symfony\Component\Console\Input\InputArgument;
35 use Symfony\Component\Console\Input\InputAwareInterface;
36 use Symfony\Component\Console\Input\InputDefinition;
37 use Symfony\Component\Console\Input\InputInterface;
38 use Symfony\Component\Console\Input\InputOption;
39 use Symfony\Component\Console\Input\StreamableInputInterface;
40 use Symfony\Component\Console\Output\ConsoleOutput;
41 use Symfony\Component\Console\Output\ConsoleOutputInterface;
42 use Symfony\Component\Console\Output\OutputInterface;
43 use Symfony\Component\Debug\ErrorHandler; 43 use Symfony\Component\Debug\ErrorHandler;
44 use Symfony\Component\Debug\Exception\FatalThrowableError; 44 use Symfony\Component\Debug\Exception\FatalThrowableError;
45 use Symfony\Component\EventDispatcher\EventDispatcherInterface; 45 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46 46
47 /** 47 /**
59 * 59 *
60 * @author Fabien Potencier <fabien@symfony.com> 60 * @author Fabien Potencier <fabien@symfony.com>
61 */ 61 */
62 class Application 62 class Application
63 { 63 {
64 private $commands = array(); 64 private $commands = [];
65 private $wantHelps = false; 65 private $wantHelps = false;
66 private $runningCommand; 66 private $runningCommand;
67 private $name; 67 private $name;
68 private $version; 68 private $version;
69 private $commandLoader; 69 private $commandLoader;
72 private $definition; 72 private $definition;
73 private $helperSet; 73 private $helperSet;
74 private $dispatcher; 74 private $dispatcher;
75 private $terminal; 75 private $terminal;
76 private $defaultCommand; 76 private $defaultCommand;
77 private $singleCommand; 77 private $singleCommand = false;
78 private $initialized; 78 private $initialized;
79 79
80 /** 80 /**
81 * @param string $name The name of the application 81 * @param string $name The name of the application
82 * @param string $version The version of the application 82 * @param string $version The version of the application
129 $this->renderException($e, $output); 129 $this->renderException($e, $output);
130 } 130 }
131 }; 131 };
132 if ($phpHandler = set_exception_handler($renderException)) { 132 if ($phpHandler = set_exception_handler($renderException)) {
133 restore_exception_handler(); 133 restore_exception_handler();
134 if (!is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { 134 if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
135 $debugHandler = true; 135 $debugHandler = true;
136 } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) { 136 } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
137 $phpHandler[0]->setExceptionHandler($debugHandler); 137 $phpHandler[0]->setExceptionHandler($debugHandler);
138 } 138 }
139 } 139 }
194 * 194 *
195 * @return int 0 if everything went fine, or an error code 195 * @return int 0 if everything went fine, or an error code
196 */ 196 */
197 public function doRun(InputInterface $input, OutputInterface $output) 197 public function doRun(InputInterface $input, OutputInterface $output)
198 { 198 {
199 if (true === $input->hasParameterOption(array('--version', '-V'), true)) { 199 if (true === $input->hasParameterOption(['--version', '-V'], true)) {
200 $output->writeln($this->getLongVersion()); 200 $output->writeln($this->getLongVersion());
201 201
202 return 0; 202 return 0;
203 } 203 }
204 204
205 $name = $this->getCommandName($input); 205 $name = $this->getCommandName($input);
206 if (true === $input->hasParameterOption(array('--help', '-h'), true)) { 206 if (true === $input->hasParameterOption(['--help', '-h'], true)) {
207 if (!$name) { 207 if (!$name) {
208 $name = 'help'; 208 $name = 'help';
209 $input = new ArrayInput(array('command_name' => $this->defaultCommand)); 209 $input = new ArrayInput(['command_name' => $this->defaultCommand]);
210 } else { 210 } else {
211 $this->wantHelps = true; 211 $this->wantHelps = true;
212 } 212 }
213 } 213 }
214 214
215 if (!$name) { 215 if (!$name) {
216 $name = $this->defaultCommand; 216 $name = $this->defaultCommand;
217 $definition = $this->getDefinition(); 217 $definition = $this->getDefinition();
218 $definition->setArguments(array_merge( 218 $definition->setArguments(array_merge(
219 $definition->getArguments(), 219 $definition->getArguments(),
220 array( 220 [
221 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), 221 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
222 ) 222 ]
223 )); 223 ));
224 } 224 }
225 225
226 try { 226 try {
227 $e = $this->runningCommand = null; 227 $e = $this->runningCommand = null;
449 449
450 return; 450 return;
451 } 451 }
452 452
453 if (null === $command->getDefinition()) { 453 if (null === $command->getDefinition()) {
454 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); 454 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command)));
455 } 455 }
456 456
457 if (!$command->getName()) { 457 if (!$command->getName()) {
458 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command))); 458 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command)));
459 } 459 }
460 460
461 $this->commands[$command->getName()] = $command; 461 $this->commands[$command->getName()] = $command;
462 462
463 foreach ($command->getAliases() as $alias) { 463 foreach ($command->getAliases() as $alias) {
519 * 519 *
520 * @return string[] An array of namespaces 520 * @return string[] An array of namespaces
521 */ 521 */
522 public function getNamespaces() 522 public function getNamespaces()
523 { 523 {
524 $namespaces = array(); 524 $namespaces = [];
525 foreach ($this->all() as $command) { 525 foreach ($this->all() as $command) {
526 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); 526 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
527 527
528 foreach ($command->getAliases() as $alias) { 528 foreach ($command->getAliases() as $alias) {
529 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); 529 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
550 550
551 if (empty($namespaces)) { 551 if (empty($namespaces)) {
552 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); 552 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
553 553
554 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { 554 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
555 if (1 == count($alternatives)) { 555 if (1 == \count($alternatives)) {
556 $message .= "\n\nDid you mean this?\n "; 556 $message .= "\n\nDid you mean this?\n ";
557 } else { 557 } else {
558 $message .= "\n\nDid you mean one of these?\n "; 558 $message .= "\n\nDid you mean one of these?\n ";
559 } 559 }
560 560
562 } 562 }
563 563
564 throw new CommandNotFoundException($message, $alternatives); 564 throw new CommandNotFoundException($message, $alternatives);
565 } 565 }
566 566
567 $exact = in_array($namespace, $namespaces, true); 567 $exact = \in_array($namespace, $namespaces, true);
568 if (count($namespaces) > 1 && !$exact) { 568 if (\count($namespaces) > 1 && !$exact) {
569 throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); 569 throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
570 } 570 }
571 571
572 return $exact ? $namespace : reset($namespaces); 572 return $exact ? $namespace : reset($namespaces);
573 } 573 }
586 */ 586 */
587 public function find($name) 587 public function find($name)
588 { 588 {
589 $this->init(); 589 $this->init();
590 590
591 $aliases = array(); 591 $aliases = [];
592 $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); 592 $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
593 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); 593 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
594 $commands = preg_grep('{^'.$expr.'}', $allCommands); 594 $commands = preg_grep('{^'.$expr.'}', $allCommands);
595 595
596 if (empty($commands)) { 596 if (empty($commands)) {
597 $commands = preg_grep('{^'.$expr.'}i', $allCommands); 597 $commands = preg_grep('{^'.$expr.'}i', $allCommands);
598 } 598 }
599 599
600 // if no commands matched or we just matched namespaces 600 // if no commands matched or we just matched namespaces
601 if (empty($commands) || count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { 601 if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
602 if (false !== $pos = strrpos($name, ':')) { 602 if (false !== $pos = strrpos($name, ':')) {
603 // check if a namespace exists and contains commands 603 // check if a namespace exists and contains commands
604 $this->findNamespace(substr($name, 0, $pos)); 604 $this->findNamespace(substr($name, 0, $pos));
605 } 605 }
606 606
607 $message = sprintf('Command "%s" is not defined.', $name); 607 $message = sprintf('Command "%s" is not defined.', $name);
608 608
609 if ($alternatives = $this->findAlternatives($name, $allCommands)) { 609 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
610 if (1 == count($alternatives)) { 610 if (1 == \count($alternatives)) {
611 $message .= "\n\nDid you mean this?\n "; 611 $message .= "\n\nDid you mean this?\n ";
612 } else { 612 } else {
613 $message .= "\n\nDid you mean one of these?\n "; 613 $message .= "\n\nDid you mean one of these?\n ";
614 } 614 }
615 $message .= implode("\n ", $alternatives); 615 $message .= implode("\n ", $alternatives);
617 617
618 throw new CommandNotFoundException($message, $alternatives); 618 throw new CommandNotFoundException($message, $alternatives);
619 } 619 }
620 620
621 // filter out aliases for commands which are already on the list 621 // filter out aliases for commands which are already on the list
622 if (count($commands) > 1) { 622 if (\count($commands) > 1) {
623 $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; 623 $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
624 $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { 624 $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
625 $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; 625 $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
626 $aliases[$nameOrAlias] = $commandName; 626 $aliases[$nameOrAlias] = $commandName;
627 627
628 return $commandName === $nameOrAlias || !in_array($commandName, $commands); 628 return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
629 })); 629 }));
630 } 630 }
631 631
632 $exact = in_array($name, $commands, true) || isset($aliases[$name]); 632 $exact = \in_array($name, $commands, true) || isset($aliases[$name]);
633 if (count($commands) > 1 && !$exact) { 633 if (\count($commands) > 1 && !$exact) {
634 $usableWidth = $this->terminal->getWidth() - 10; 634 $usableWidth = $this->terminal->getWidth() - 10;
635 $abbrevs = array_values($commands); 635 $abbrevs = array_values($commands);
636 $maxLen = 0; 636 $maxLen = 0;
637 foreach ($abbrevs as $abbrev) { 637 foreach ($abbrevs as $abbrev) {
638 $maxLen = max(Helper::strlen($abbrev), $maxLen); 638 $maxLen = max(Helper::strlen($abbrev), $maxLen);
679 } 679 }
680 680
681 return $commands; 681 return $commands;
682 } 682 }
683 683
684 $commands = array(); 684 $commands = [];
685 foreach ($this->commands as $name => $command) { 685 foreach ($this->commands as $name => $command) {
686 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { 686 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
687 $commands[$name] = $command; 687 $commands[$name] = $command;
688 } 688 }
689 } 689 }
706 * 706 *
707 * @return array An array of abbreviations 707 * @return array An array of abbreviations
708 */ 708 */
709 public static function getAbbreviations($names) 709 public static function getAbbreviations($names)
710 { 710 {
711 $abbrevs = array(); 711 $abbrevs = [];
712 foreach ($names as $name) { 712 foreach ($names as $name) {
713 for ($len = strlen($name); $len > 0; --$len) { 713 for ($len = \strlen($name); $len > 0; --$len) {
714 $abbrev = substr($name, 0, $len); 714 $abbrev = substr($name, 0, $len);
715 $abbrevs[$abbrev][] = $name; 715 $abbrevs[$abbrev][] = $name;
716 } 716 }
717 } 717 }
718 718
737 protected function doRenderException(\Exception $e, OutputInterface $output) 737 protected function doRenderException(\Exception $e, OutputInterface $output)
738 { 738 {
739 do { 739 do {
740 $message = trim($e->getMessage()); 740 $message = trim($e->getMessage());
741 if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { 741 if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
742 $title = sprintf(' [%s%s] ', get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); 742 $title = sprintf(' [%s%s] ', \get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
743 $len = Helper::strlen($title); 743 $len = Helper::strlen($title);
744 } else { 744 } else {
745 $len = 0; 745 $len = 0;
746 } 746 }
747 747
748 $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; 748 $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
749 // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 749 // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
750 if (defined('HHVM_VERSION') && $width > 1 << 31) { 750 if (\defined('HHVM_VERSION') && $width > 1 << 31) {
751 $width = 1 << 31; 751 $width = 1 << 31;
752 } 752 }
753 $lines = array(); 753 $lines = [];
754 foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) { 754 foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) {
755 foreach ($this->splitStringByWidth($line, $width - 4) as $line) { 755 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
756 // pre-format lines to get the right string length 756 // pre-format lines to get the right string length
757 $lineLength = Helper::strlen($line) + 4; 757 $lineLength = Helper::strlen($line) + 4;
758 $lines[] = array($line, $lineLength); 758 $lines[] = [$line, $lineLength];
759 759
760 $len = max($lineLength, $len); 760 $len = max($lineLength, $len);
761 } 761 }
762 } 762 }
763 763
764 $messages = array(); 764 $messages = [];
765 if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { 765 if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
766 $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); 766 $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
767 } 767 }
768 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len)); 768 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
769 if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { 769 if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
781 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET); 781 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
782 782
783 // exception related properties 783 // exception related properties
784 $trace = $e->getTrace(); 784 $trace = $e->getTrace();
785 785
786 for ($i = 0, $count = count($trace); $i < $count; ++$i) { 786 array_unshift($trace, [
787 'function' => '',
788 'file' => $e->getFile() ?: 'n/a',
789 'line' => $e->getLine() ?: 'n/a',
790 'args' => [],
791 ]);
792
793 for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
787 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; 794 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
788 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; 795 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
789 $function = $trace[$i]['function']; 796 $function = $trace[$i]['function'];
790 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; 797 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
791 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; 798 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
805 * 812 *
806 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. 813 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
807 */ 814 */
808 protected function getTerminalWidth() 815 protected function getTerminalWidth()
809 { 816 {
810 @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); 817 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
811 818
812 return $this->terminal->getWidth(); 819 return $this->terminal->getWidth();
813 } 820 }
814 821
815 /** 822 /**
819 * 826 *
820 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. 827 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
821 */ 828 */
822 protected function getTerminalHeight() 829 protected function getTerminalHeight()
823 { 830 {
824 @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); 831 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
825 832
826 return $this->terminal->getHeight(); 833 return $this->terminal->getHeight();
827 } 834 }
828 835
829 /** 836 /**
833 * 840 *
834 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. 841 * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
835 */ 842 */
836 public function getTerminalDimensions() 843 public function getTerminalDimensions()
837 { 844 {
838 @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); 845 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);
839 846
840 return array($this->terminal->getWidth(), $this->terminal->getHeight()); 847 return [$this->terminal->getWidth(), $this->terminal->getHeight()];
841 } 848 }
842 849
843 /** 850 /**
844 * Sets terminal dimensions. 851 * Sets terminal dimensions.
845 * 852 *
852 * 859 *
853 * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. 860 * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead.
854 */ 861 */
855 public function setTerminalDimensions($width, $height) 862 public function setTerminalDimensions($width, $height)
856 { 863 {
857 @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED); 864 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED);
858 865
859 putenv('COLUMNS='.$width); 866 putenv('COLUMNS='.$width);
860 putenv('LINES='.$height); 867 putenv('LINES='.$height);
861 868
862 return $this; 869 return $this;
865 /** 872 /**
866 * Configures the input and output instances based on the user arguments and options. 873 * Configures the input and output instances based on the user arguments and options.
867 */ 874 */
868 protected function configureIO(InputInterface $input, OutputInterface $output) 875 protected function configureIO(InputInterface $input, OutputInterface $output)
869 { 876 {
870 if (true === $input->hasParameterOption(array('--ansi'), true)) { 877 if (true === $input->hasParameterOption(['--ansi'], true)) {
871 $output->setDecorated(true); 878 $output->setDecorated(true);
872 } elseif (true === $input->hasParameterOption(array('--no-ansi'), true)) { 879 } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) {
873 $output->setDecorated(false); 880 $output->setDecorated(false);
874 } 881 }
875 882
876 if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) { 883 if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) {
877 $input->setInteractive(false); 884 $input->setInteractive(false);
878 } elseif (function_exists('posix_isatty')) { 885 } elseif (\function_exists('posix_isatty')) {
879 $inputStream = null; 886 $inputStream = null;
880 887
881 if ($input instanceof StreamableInputInterface) { 888 if ($input instanceof StreamableInputInterface) {
882 $inputStream = $input->getStream(); 889 $inputStream = $input->getStream();
883 } 890 }
899 case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; 906 case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break;
900 case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; 907 case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break;
901 default: $shellVerbosity = 0; break; 908 default: $shellVerbosity = 0; break;
902 } 909 }
903 910
904 if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) { 911 if (true === $input->hasParameterOption(['--quiet', '-q'], true)) {
905 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); 912 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
906 $shellVerbosity = -1; 913 $shellVerbosity = -1;
907 } else { 914 } else {
908 if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { 915 if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
909 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); 916 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
1012 * 1019 *
1013 * @return InputDefinition An InputDefinition instance 1020 * @return InputDefinition An InputDefinition instance
1014 */ 1021 */
1015 protected function getDefaultInputDefinition() 1022 protected function getDefaultInputDefinition()
1016 { 1023 {
1017 return new InputDefinition(array( 1024 return new InputDefinition([
1018 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), 1025 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
1019 1026
1020 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), 1027 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
1021 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), 1028 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
1022 new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), 1029 new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
1023 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), 1030 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
1024 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), 1031 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
1025 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), 1032 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
1026 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), 1033 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
1027 )); 1034 ]);
1028 } 1035 }
1029 1036
1030 /** 1037 /**
1031 * Gets the default commands that should always be available. 1038 * Gets the default commands that should always be available.
1032 * 1039 *
1033 * @return Command[] An array of default Command instances 1040 * @return Command[] An array of default Command instances
1034 */ 1041 */
1035 protected function getDefaultCommands() 1042 protected function getDefaultCommands()
1036 { 1043 {
1037 return array(new HelpCommand(), new ListCommand()); 1044 return [new HelpCommand(), new ListCommand()];
1038 } 1045 }
1039 1046
1040 /** 1047 /**
1041 * Gets the default helper set with the helpers that should always be available. 1048 * Gets the default helper set with the helpers that should always be available.
1042 * 1049 *
1043 * @return HelperSet A HelperSet instance 1050 * @return HelperSet A HelperSet instance
1044 */ 1051 */
1045 protected function getDefaultHelperSet() 1052 protected function getDefaultHelperSet()
1046 { 1053 {
1047 return new HelperSet(array( 1054 return new HelperSet([
1048 new FormatterHelper(), 1055 new FormatterHelper(),
1049 new DebugFormatterHelper(), 1056 new DebugFormatterHelper(),
1050 new ProcessHelper(), 1057 new ProcessHelper(),
1051 new QuestionHelper(), 1058 new QuestionHelper(),
1052 )); 1059 ]);
1053 } 1060 }
1054 1061
1055 /** 1062 /**
1056 * Returns abbreviated suggestions in string format. 1063 * Returns abbreviated suggestions in string format.
1057 * 1064 *
1077 public function extractNamespace($name, $limit = null) 1084 public function extractNamespace($name, $limit = null)
1078 { 1085 {
1079 $parts = explode(':', $name); 1086 $parts = explode(':', $name);
1080 array_pop($parts); 1087 array_pop($parts);
1081 1088
1082 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); 1089 return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
1083 } 1090 }
1084 1091
1085 /** 1092 /**
1086 * Finds alternative of $name among $collection, 1093 * Finds alternative of $name among $collection,
1087 * if nothing is found in $collection, try in $abbrevs. 1094 * if nothing is found in $collection, try in $abbrevs.
1092 * @return string[] A sorted array of similar string 1099 * @return string[] A sorted array of similar string
1093 */ 1100 */
1094 private function findAlternatives($name, $collection) 1101 private function findAlternatives($name, $collection)
1095 { 1102 {
1096 $threshold = 1e3; 1103 $threshold = 1e3;
1097 $alternatives = array(); 1104 $alternatives = [];
1098 1105
1099 $collectionParts = array(); 1106 $collectionParts = [];
1100 foreach ($collection as $item) { 1107 foreach ($collection as $item) {
1101 $collectionParts[$item] = explode(':', $item); 1108 $collectionParts[$item] = explode(':', $item);
1102 } 1109 }
1103 1110
1104 foreach (explode(':', $name) as $i => $subname) { 1111 foreach (explode(':', $name) as $i => $subname) {
1110 } elseif (!isset($parts[$i])) { 1117 } elseif (!isset($parts[$i])) {
1111 continue; 1118 continue;
1112 } 1119 }
1113 1120
1114 $lev = levenshtein($subname, $parts[$i]); 1121 $lev = levenshtein($subname, $parts[$i]);
1115 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { 1122 if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
1116 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; 1123 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
1117 } elseif ($exists) { 1124 } elseif ($exists) {
1118 $alternatives[$collectionName] += $threshold; 1125 $alternatives[$collectionName] += $threshold;
1119 } 1126 }
1120 } 1127 }
1121 } 1128 }
1122 1129
1123 foreach ($collection as $item) { 1130 foreach ($collection as $item) {
1124 $lev = levenshtein($name, $item); 1131 $lev = levenshtein($name, $item);
1125 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { 1132 if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
1126 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; 1133 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
1127 } 1134 }
1128 } 1135 }
1129 1136
1130 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); 1137 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
1151 1158
1152 $this->singleCommand = true; 1159 $this->singleCommand = true;
1153 } 1160 }
1154 1161
1155 return $this; 1162 return $this;
1163 }
1164
1165 /**
1166 * @internal
1167 */
1168 public function isSingleCommand()
1169 {
1170 return $this->singleCommand;
1156 } 1171 }
1157 1172
1158 private function splitStringByWidth($string, $width) 1173 private function splitStringByWidth($string, $width)
1159 { 1174 {
1160 // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. 1175 // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
1163 if (false === $encoding = mb_detect_encoding($string, null, true)) { 1178 if (false === $encoding = mb_detect_encoding($string, null, true)) {
1164 return str_split($string, $width); 1179 return str_split($string, $width);
1165 } 1180 }
1166 1181
1167 $utf8String = mb_convert_encoding($string, 'utf8', $encoding); 1182 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
1168 $lines = array(); 1183 $lines = [];
1169 $line = ''; 1184 $line = '';
1170 foreach (preg_split('//u', $utf8String) as $char) { 1185 foreach (preg_split('//u', $utf8String) as $char) {
1171 // test if $char could be appended to current line 1186 // test if $char could be appended to current line
1172 if (mb_strwidth($line.$char, 'utf8') <= $width) { 1187 if (mb_strwidth($line.$char, 'utf8') <= $width) {
1173 $line .= $char; 1188 $line .= $char;
1176 // if not, push current line to array and make new line 1191 // if not, push current line to array and make new line
1177 $lines[] = str_pad($line, $width); 1192 $lines[] = str_pad($line, $width);
1178 $line = $char; 1193 $line = $char;
1179 } 1194 }
1180 1195
1181 $lines[] = count($lines) ? str_pad($line, $width) : $line; 1196 $lines[] = \count($lines) ? str_pad($line, $width) : $line;
1182 1197
1183 mb_convert_variables($encoding, 'utf8', $lines); 1198 mb_convert_variables($encoding, 'utf8', $lines);
1184 1199
1185 return $lines; 1200 return $lines;
1186 } 1201 }
1194 */ 1209 */
1195 private function extractAllNamespaces($name) 1210 private function extractAllNamespaces($name)
1196 { 1211 {
1197 // -1 as third argument is needed to skip the command short name when exploding 1212 // -1 as third argument is needed to skip the command short name when exploding
1198 $parts = explode(':', $name, -1); 1213 $parts = explode(':', $name, -1);
1199 $namespaces = array(); 1214 $namespaces = [];
1200 1215
1201 foreach ($parts as $part) { 1216 foreach ($parts as $part) {
1202 if (count($namespaces)) { 1217 if (\count($namespaces)) {
1203 $namespaces[] = end($namespaces).':'.$part; 1218 $namespaces[] = end($namespaces).':'.$part;
1204 } else { 1219 } else {
1205 $namespaces[] = $part; 1220 $namespaces[] = $part;
1206 } 1221 }
1207 } 1222 }