From a1b3df8a0a0f883244a843ee806dd9cabc5441d7 Mon Sep 17 00:00:00 2001 From: Kev Date: Fri, 12 Apr 2024 10:46:21 +0200 Subject: [PATCH 01/31] [Console] Better error handling when misuse of `ArgvInput` with arrays --- Input/ArgvInput.php | 6 ++++++ Tests/Input/ArgvInputTest.php | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index 95703ba5f..2ebbdf086 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -49,6 +49,12 @@ public function __construct(?array $argv = null, ?InputDefinition $definition = { $argv ??= $_SERVER['argv'] ?? []; + foreach ($argv as $arg) { + if (!\is_scalar($arg) && !$arg instanceof \Stringable) { + throw new RuntimeException(sprintf('Argument values expected to be all scalars, got "%s".', get_debug_type($arg))); + } + } + // strip the application name array_shift($argv); diff --git a/Tests/Input/ArgvInputTest.php b/Tests/Input/ArgvInputTest.php index 80ea06d67..31b4b03dd 100644 --- a/Tests/Input/ArgvInputTest.php +++ b/Tests/Input/ArgvInputTest.php @@ -324,6 +324,11 @@ public static function provideInvalidInput(): array new InputDefinition([new InputArgument('name', InputArgument::REQUIRED)]), 'Too many arguments, expected arguments "name".', ], + [ + ['cli.php', ['array']], + new InputDefinition(), + 'Argument values expected to be all scalars, got "array".', + ], ]; } From d4f689163104d1f2fbbdd78923b36e6ca8c501de Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 20 Jun 2024 17:52:34 +0200 Subject: [PATCH 02/31] Prefix all sprintf() calls --- Application.php | 36 +++++++++---------- CI/GithubActionReporter.php | 4 +-- Color.php | 8 ++--- Command/Command.php | 10 +++--- Command/CompleteCommand.php | 4 +-- Command/DumpCompletionCommand.php | 4 +-- CommandLoader/ContainerCommandLoader.php | 2 +- CommandLoader/FactoryCommandLoader.php | 2 +- Cursor.php | 14 ++++---- DataCollector/CommandDataCollector.php | 6 ++-- DependencyInjection/AddConsoleCommandPass.php | 8 ++--- Descriptor/ApplicationDescription.php | 2 +- Descriptor/Descriptor.php | 2 +- Descriptor/MarkdownDescriptor.php | 4 +-- Descriptor/ReStructuredTextDescriptor.php | 4 +-- Descriptor/TextDescriptor.php | 20 +++++------ Formatter/OutputFormatter.php | 2 +- Helper/DebugFormatterHelper.php | 16 ++++----- Helper/DescriptorHelper.php | 2 +- Helper/FormatterHelper.php | 6 ++-- Helper/Helper.php | 8 ++--- Helper/HelperSet.php | 2 +- Helper/OutputWrapper.php | 4 +-- Helper/ProcessHelper.php | 6 ++-- Helper/ProgressBar.php | 2 +- Helper/QuestionHelper.php | 2 +- Helper/SymfonyQuestionHelper.php | 12 +++---- Helper/Table.php | 32 ++++++++--------- Helper/TableCell.php | 2 +- Helper/TableCellStyle.php | 4 +-- Input/ArgvInput.php | 22 ++++++------ Input/ArrayInput.php | 8 ++--- Input/Input.php | 10 +++--- Input/InputArgument.php | 4 +-- Input/InputDefinition.php | 30 ++++++++-------- Input/InputOption.php | 4 +-- Input/StringInput.php | 2 +- Logger/ConsoleLogger.php | 4 +-- Messenger/RunCommandMessageHandler.php | 2 +- Output/AnsiColorMode.php | 4 +-- Output/ConsoleSectionOutput.php | 2 +- Output/TrimmedBufferOutput.php | 2 +- Question/ChoiceQuestion.php | 6 ++-- Style/SymfonyStyle.php | 16 ++++----- Tester/Constraint/CommandIsSuccessful.php | 2 +- Tests/ApplicationTest.php | 8 ++--- Tests/Command/CommandTest.php | 2 +- .../Descriptor/AbstractDescriptorTestCase.php | 2 +- Tests/Helper/ProgressIndicatorTest.php | 2 +- Tests/Input/InputDefinitionTest.php | 2 +- Tests/Output/ConsoleSectionOutputTest.php | 6 ++-- Tests/Question/ConfirmationQuestionTest.php | 2 +- 52 files changed, 186 insertions(+), 186 deletions(-) diff --git a/Application.php b/Application.php index 87eb7a6c2..aa4af5c58 100644 --- a/Application.php +++ b/Application.php @@ -262,9 +262,9 @@ public function doRun(InputInterface $input, OutputInterface $output): int $style = new SymfonyStyle($input, $output); $output->writeln(''); - $formattedBlock = (new FormatterHelper())->formatBlock(sprintf('Command "%s" is not defined.', $name), 'error', true); + $formattedBlock = (new FormatterHelper())->formatBlock(\sprintf('Command "%s" is not defined.', $name), 'error', true); $output->writeln($formattedBlock); - if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { + if (!$style->confirm(\sprintf('Do you want to run "%s" instead? ', $alternative), false)) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); @@ -475,7 +475,7 @@ public function getLongVersion(): string { if ('UNKNOWN' !== $this->getName()) { if ('UNKNOWN' !== $this->getVersion()) { - return sprintf('%s %s', $this->getName(), $this->getVersion()); + return \sprintf('%s %s', $this->getName(), $this->getVersion()); } return $this->getName(); @@ -530,7 +530,7 @@ public function add(Command $command): ?Command } if (!$command->getName()) { - throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command))); + throw new LogicException(\sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command))); } $this->commands[$command->getName()] = $command; @@ -552,12 +552,12 @@ public function get(string $name): Command $this->init(); if (!$this->has($name)) { - throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name)); } // When the command has a different name than the one used at the command loader level if (!isset($this->commands[$name])) { - throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); + throw new CommandNotFoundException(\sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); } $command = $this->commands[$name]; @@ -621,7 +621,7 @@ public function findNamespace(string $namespace): string $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); if (!$namespaces) { - $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); + $message = \sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { if (1 == \count($alternatives)) { @@ -638,7 +638,7 @@ public function findNamespace(string $namespace): string $exact = \in_array($namespace, $namespaces, true); if (\count($namespaces) > 1 && !$exact) { - throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + throw new NamespaceNotFoundException(\sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); } return $exact ? $namespace : reset($namespaces); @@ -685,7 +685,7 @@ public function find(string $name): Command $this->findNamespace(substr($name, 0, $pos)); } - $message = sprintf('Command "%s" is not defined.', $name); + $message = \sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { // remove hidden commands @@ -740,14 +740,14 @@ public function find(string $name): Command if (\count($commands) > 1) { $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); - throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); + throw new CommandNotFoundException(\sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); } } $command = $this->get(reset($commands)); if ($command->isHidden()) { - throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name)); } return $command; @@ -822,7 +822,7 @@ public function renderThrowable(\Throwable $e, OutputInterface $output): void $this->doRenderThrowable($e, $output); if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET); + $output->writeln(\sprintf('%s', OutputFormatter::escape(\sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET); $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } @@ -833,7 +833,7 @@ protected function doRenderThrowable(\Throwable $e, OutputInterface $output): vo $message = trim($e->getMessage()); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $class = get_debug_type($e); - $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $title = \sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); $len = Helper::width($title); } else { $len = 0; @@ -857,14 +857,14 @@ protected function doRenderThrowable(\Throwable $e, OutputInterface $output): vo $messages = []; if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + $messages[] = \sprintf('%s', OutputFormatter::escape(\sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); } - $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); + $messages[] = $emptyLine = \sprintf('%s', str_repeat(' ', $len)); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::width($title)))); + $messages[] = \sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::width($title)))); } foreach ($lines as $line) { - $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); + $messages[] = \sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); } $messages[] = $emptyLine; $messages[] = ''; @@ -891,7 +891,7 @@ protected function doRenderThrowable(\Throwable $e, OutputInterface $output): vo $file = $trace[$i]['file'] ?? 'n/a'; $line = $trace[$i]['line'] ?? 'n/a'; - $output->writeln(sprintf(' %s%s at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); + $output->writeln(\sprintf(' %s%s at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); } $output->writeln('', OutputInterface::VERBOSITY_QUIET); diff --git a/CI/GithubActionReporter.php b/CI/GithubActionReporter.php index 2cae6fd8b..28112c2a2 100644 --- a/CI/GithubActionReporter.php +++ b/CI/GithubActionReporter.php @@ -89,11 +89,11 @@ private function log(string $type, string $message, ?string $file = null, ?int $ if (!$file) { // No file provided, output the message solely: - $this->output->writeln(sprintf('::%s::%s', $type, $message)); + $this->output->writeln(\sprintf('::%s::%s', $type, $message)); return; } - $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); + $this->output->writeln(\sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); } } diff --git a/Color.php b/Color.php index 60ed046a6..b1914c19a 100644 --- a/Color.php +++ b/Color.php @@ -60,7 +60,7 @@ public function __construct(string $foreground = '', string $background = '', ar foreach ($options as $option) { if (!isset(self::AVAILABLE_OPTIONS[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS)))); + throw new InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS)))); } $this->options[$option] = self::AVAILABLE_OPTIONS[$option]; @@ -88,7 +88,7 @@ public function set(): string return ''; } - return sprintf("\033[%sm", implode(';', $setCodes)); + return \sprintf("\033[%sm", implode(';', $setCodes)); } public function unset(): string @@ -107,7 +107,7 @@ public function unset(): string return ''; } - return sprintf("\033[%sm", implode(';', $unsetCodes)); + return \sprintf("\033[%sm", implode(';', $unsetCodes)); } private function parseColor(string $color, bool $background = false): string @@ -128,6 +128,6 @@ private function parseColor(string $color, bool $background = false): string return ($background ? '10' : '9').self::BRIGHT_COLORS[$color]; } - throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS))))); + throw new InvalidArgumentException(\sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS))))); } } diff --git a/Command/Command.php b/Command/Command.php index 03da6db43..244a419f2 100644 --- a/Command/Command.php +++ b/Command/Command.php @@ -395,7 +395,7 @@ public function getDefinition(): InputDefinition */ public function getNativeDefinition(): InputDefinition { - return $this->definition ?? throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); + return $this->definition ?? throw new LogicException(\sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); } /** @@ -603,7 +603,7 @@ public function getSynopsis(bool $short = false): string $key = $short ? 'short' : 'long'; if (!isset($this->synopsis[$key])) { - $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); + $this->synopsis[$key] = trim(\sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); } return $this->synopsis[$key]; @@ -617,7 +617,7 @@ public function getSynopsis(bool $short = false): string public function addUsage(string $usage): static { if (!str_starts_with($usage, $this->name)) { - $usage = sprintf('%s %s', $this->name, $usage); + $usage = \sprintf('%s %s', $this->name, $usage); } $this->usages[] = $usage; @@ -642,7 +642,7 @@ public function getUsages(): array public function getHelper(string $name): HelperInterface { if (null === $this->helperSet) { - throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); + throw new LogicException(\sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); } return $this->helperSet->get($name); @@ -658,7 +658,7 @@ public function getHelper(string $name): HelperInterface private function validateName(string $name): void { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { - throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); + throw new InvalidArgumentException(\sprintf('Command name "%s" is invalid.', $name)); } } } diff --git a/Command/CompleteCommand.php b/Command/CompleteCommand.php index 38aa737f0..df0cddabb 100644 --- a/Command/CompleteCommand.php +++ b/Command/CompleteCommand.php @@ -74,7 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int // "symfony" must be kept for compat with the shell scripts generated by Symfony Console 5.4 - 6.1 $version = $input->getOption('symfony') ? '1' : $input->getOption('api-version'); if ($version && version_compare($version, self::COMPLETION_API_VERSION, '<')) { - $message = sprintf('Completion script version is not supported ("%s" given, ">=%s" required).', $version, self::COMPLETION_API_VERSION); + $message = \sprintf('Completion script version is not supported ("%s" given, ">=%s" required).', $version, self::COMPLETION_API_VERSION); $this->log($message); $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.'); @@ -88,7 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if (!$completionOutput = $this->completionOutputs[$shell] ?? false) { - throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); + throw new \RuntimeException(\sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); } $completionInput = $this->createCompletionInput($input); diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index be6f54592..daf3553ab 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -98,9 +98,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output = $output->getErrorOutput(); } if ($shell) { - $output->writeln(sprintf('Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").', $shell, implode('", "', $supportedShells))); + $output->writeln(\sprintf('Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").', $shell, implode('", "', $supportedShells))); } else { - $output->writeln(sprintf('Shell not detected, Symfony shell completion only supports "%s").', implode('", "', $supportedShells))); + $output->writeln(\sprintf('Shell not detected, Symfony shell completion only supports "%s").', implode('", "', $supportedShells))); } return 2; diff --git a/CommandLoader/ContainerCommandLoader.php b/CommandLoader/ContainerCommandLoader.php index 84e25be76..eb4945135 100644 --- a/CommandLoader/ContainerCommandLoader.php +++ b/CommandLoader/ContainerCommandLoader.php @@ -34,7 +34,7 @@ public function __construct( public function get(string $name): Command { if (!$this->has($name)) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } return $this->container->get($this->commandMap[$name]); diff --git a/CommandLoader/FactoryCommandLoader.php b/CommandLoader/FactoryCommandLoader.php index ae16bf6f1..2d13139c2 100644 --- a/CommandLoader/FactoryCommandLoader.php +++ b/CommandLoader/FactoryCommandLoader.php @@ -37,7 +37,7 @@ public function has(string $name): bool public function get(string $name): Command { if (!isset($this->factories[$name])) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } $factory = $this->factories[$name]; diff --git a/Cursor.php b/Cursor.php index 965f996e0..e2618cf1d 100644 --- a/Cursor.php +++ b/Cursor.php @@ -36,7 +36,7 @@ public function __construct( */ public function moveUp(int $lines = 1): static { - $this->output->write(sprintf("\x1b[%dA", $lines)); + $this->output->write(\sprintf("\x1b[%dA", $lines)); return $this; } @@ -46,7 +46,7 @@ public function moveUp(int $lines = 1): static */ public function moveDown(int $lines = 1): static { - $this->output->write(sprintf("\x1b[%dB", $lines)); + $this->output->write(\sprintf("\x1b[%dB", $lines)); return $this; } @@ -56,7 +56,7 @@ public function moveDown(int $lines = 1): static */ public function moveRight(int $columns = 1): static { - $this->output->write(sprintf("\x1b[%dC", $columns)); + $this->output->write(\sprintf("\x1b[%dC", $columns)); return $this; } @@ -66,7 +66,7 @@ public function moveRight(int $columns = 1): static */ public function moveLeft(int $columns = 1): static { - $this->output->write(sprintf("\x1b[%dD", $columns)); + $this->output->write(\sprintf("\x1b[%dD", $columns)); return $this; } @@ -76,7 +76,7 @@ public function moveLeft(int $columns = 1): static */ public function moveToColumn(int $column): static { - $this->output->write(sprintf("\x1b[%dG", $column)); + $this->output->write(\sprintf("\x1b[%dG", $column)); return $this; } @@ -86,7 +86,7 @@ public function moveToColumn(int $column): static */ public function moveToPosition(int $column, int $row): static { - $this->output->write(sprintf("\x1b[%d;%dH", $row + 1, $column)); + $this->output->write(\sprintf("\x1b[%d;%dH", $row + 1, $column)); return $this; } @@ -195,7 +195,7 @@ public function getCurrentPosition(): array $code = trim(fread($this->input, 1024)); - shell_exec(sprintf('stty %s', $sttyMode)); + shell_exec(\sprintf('stty %s', $sttyMode)); sscanf($code, "\033[%d;%dR", $row, $col); diff --git a/DataCollector/CommandDataCollector.php b/DataCollector/CommandDataCollector.php index 45138c7dc..3cbe72b59 100644 --- a/DataCollector/CommandDataCollector.php +++ b/DataCollector/CommandDataCollector.php @@ -118,7 +118,7 @@ public function getCommand(): array public function getInterruptedBySignal(): ?string { if (isset($this->data['interrupted_by_signal'])) { - return sprintf('%s (%d)', SignalMap::getSignalName($this->data['interrupted_by_signal']), $this->data['interrupted_by_signal']); + return \sprintf('%s (%d)', SignalMap::getSignalName($this->data['interrupted_by_signal']), $this->data['interrupted_by_signal']); } return null; @@ -204,7 +204,7 @@ public function getInteractiveInputs(): array public function getSignalable(): array { return array_map( - static fn (int $signal): string => sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), + static fn (int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), $this->data['signalable'] ); } @@ -212,7 +212,7 @@ public function getSignalable(): array public function getHandledSignals(): array { $keys = array_map( - static fn (int $signal): string => sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), + static fn (int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal), array_keys($this->data['handled_signals']) ); diff --git a/DependencyInjection/AddConsoleCommandPass.php b/DependencyInjection/AddConsoleCommandPass.php index f712c614a..642247e3f 100644 --- a/DependencyInjection/AddConsoleCommandPass.php +++ b/DependencyInjection/AddConsoleCommandPass.php @@ -45,10 +45,10 @@ public function process(ContainerBuilder $container): void $aliases = $tags[0]['command']; } else { if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(Command::class)) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); + throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); } $aliases = str_replace('%', '%%', $class::getDefaultName() ?? ''); } @@ -102,10 +102,10 @@ public function process(ContainerBuilder $container): void if (!$description) { if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(Command::class)) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); + throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, 'console.command', Command::class)); } $description = str_replace('%', '%%', $class::getDefaultDescription() ?? ''); } diff --git a/Descriptor/ApplicationDescription.php b/Descriptor/ApplicationDescription.php index 5149fde4c..802d68560 100644 --- a/Descriptor/ApplicationDescription.php +++ b/Descriptor/ApplicationDescription.php @@ -70,7 +70,7 @@ public function getCommands(): array public function getCommand(string $name): Command { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } return $this->commands[$name] ?? $this->aliases[$name]; diff --git a/Descriptor/Descriptor.php b/Descriptor/Descriptor.php index 7b2509c60..2143a17c3 100644 --- a/Descriptor/Descriptor.php +++ b/Descriptor/Descriptor.php @@ -38,7 +38,7 @@ public function describe(OutputInterface $output, object $object, array $options $object instanceof InputDefinition => $this->describeInputDefinition($object, $options), $object instanceof Command => $this->describeCommand($object, $options), $object instanceof Application => $this->describeApplication($object, $options), - default => throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))), + default => throw new InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', get_debug_type($object))), }; } diff --git a/Descriptor/MarkdownDescriptor.php b/Descriptor/MarkdownDescriptor.php index b3f16ee90..8b7075943 100644 --- a/Descriptor/MarkdownDescriptor.php +++ b/Descriptor/MarkdownDescriptor.php @@ -149,7 +149,7 @@ protected function describeApplication(Application $application, array $options } $this->write("\n\n"); - $this->write(implode("\n", array_map(fn ($commandName) => sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())), $namespace['commands']))); + $this->write(implode("\n", array_map(fn ($commandName) => \sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())), $namespace['commands']))); } foreach ($description->getCommands() as $command) { @@ -162,7 +162,7 @@ private function getApplicationTitle(Application $application): string { if ('UNKNOWN' !== $application->getName()) { if ('UNKNOWN' !== $application->getVersion()) { - return sprintf('%s %s', $application->getName(), $application->getVersion()); + return \sprintf('%s %s', $application->getName(), $application->getVersion()); } return $application->getName(); diff --git a/Descriptor/ReStructuredTextDescriptor.php b/Descriptor/ReStructuredTextDescriptor.php index f12fecb67..462b9bb0b 100644 --- a/Descriptor/ReStructuredTextDescriptor.php +++ b/Descriptor/ReStructuredTextDescriptor.php @@ -167,7 +167,7 @@ private function getApplicationTitle(Application $application): string return 'Console Tool'; } if ('UNKNOWN' !== $application->getVersion()) { - return sprintf('%s %s', $application->getName(), $application->getVersion()); + return \sprintf('%s %s', $application->getName(), $application->getVersion()); } return $application->getName(); @@ -209,7 +209,7 @@ private function createTableOfContents(ApplicationDescription $description, Appl $commands = $this->removeAliasesAndHiddenCommands($commands); $this->write("\n\n"); - $this->write(implode("\n", array_map(static fn ($commandName) => sprintf('- `%s`_', $commandName), array_keys($commands)))); + $this->write(implode("\n", array_map(static fn ($commandName) => \sprintf('- `%s`_', $commandName), array_keys($commands)))); } } diff --git a/Descriptor/TextDescriptor.php b/Descriptor/TextDescriptor.php index d04d10238..51c411f46 100644 --- a/Descriptor/TextDescriptor.php +++ b/Descriptor/TextDescriptor.php @@ -31,7 +31,7 @@ class TextDescriptor extends Descriptor protected function describeInputArgument(InputArgument $argument, array $options = []): void { if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { - $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); + $default = \sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } @@ -39,7 +39,7 @@ protected function describeInputArgument(InputArgument $argument, array $options $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); $spacingWidth = $totalWidth - \strlen($argument->getName()); - $this->writeText(sprintf(' %s %s%s%s', + $this->writeText(\sprintf(' %s %s%s%s', $argument->getName(), str_repeat(' ', $spacingWidth), // + 4 = 2 spaces before , 2 spaces after @@ -51,7 +51,7 @@ protected function describeInputArgument(InputArgument $argument, array $options protected function describeInputOption(InputOption $option, array $options = []): void { if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { - $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); + $default = \sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } @@ -66,14 +66,14 @@ protected function describeInputOption(InputOption $option, array $options = []) } $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); - $synopsis = sprintf('%s%s', - $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', - sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) + $synopsis = \sprintf('%s%s', + $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : ' ', + \sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) ); $spacingWidth = $totalWidth - Helper::width($synopsis); - $this->writeText(sprintf(' %s %s%s%s%s', + $this->writeText(\sprintf(' %s %s%s%s%s', $synopsis, str_repeat(' ', $spacingWidth), // + 4 = 2 spaces before , 2 spaces after @@ -166,7 +166,7 @@ protected function describeApplication(Application $application, array $options $width = $this->getColumnWidth($description->getCommands()); foreach ($description->getCommands() as $command) { - $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); + $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); $this->writeText("\n"); } } else { @@ -196,7 +196,7 @@ protected function describeApplication(Application $application, array $options $width = $this->getColumnWidth(array_merge(...array_values(array_map(fn ($namespace) => array_intersect($namespace['commands'], array_keys($commands)), array_values($namespaces))))); if ($describedNamespace) { - $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); + $this->writeText(\sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); } else { $this->writeText('Available commands:', $options); } @@ -218,7 +218,7 @@ protected function describeApplication(Application $application, array $options $spacingWidth = $width - Helper::width($name); $command = $commands[$name]; $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; - $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); + $this->writeText(\sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); } } diff --git a/Formatter/OutputFormatter.php b/Formatter/OutputFormatter.php index 8e81e5900..1f3d04a2e 100644 --- a/Formatter/OutputFormatter.php +++ b/Formatter/OutputFormatter.php @@ -106,7 +106,7 @@ public function hasStyle(string $name): bool public function getStyle(string $name): OutputFormatterStyleInterface { if (!$this->hasStyle($name)) { - throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); + throw new InvalidArgumentException(\sprintf('Undefined style: "%s".', $name)); } return $this->styles[strtolower($name)]; diff --git a/Helper/DebugFormatterHelper.php b/Helper/DebugFormatterHelper.php index 9ea7fb914..dfdb8a82c 100644 --- a/Helper/DebugFormatterHelper.php +++ b/Helper/DebugFormatterHelper.php @@ -31,7 +31,7 @@ public function start(string $id, string $message, string $prefix = 'RUN'): stri { $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)]; - return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); + return \sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); } /** @@ -47,22 +47,22 @@ public function progress(string $id, string $buffer, bool $error = false, string unset($this->started[$id]['out']); } if (!isset($this->started[$id]['err'])) { - $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); + $message .= \sprintf('%s %s ', $this->getBorder($id), $errorPrefix); $this->started[$id]['err'] = true; } - $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); + $message .= str_replace("\n", \sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); } else { if (isset($this->started[$id]['err'])) { $message .= "\n"; unset($this->started[$id]['err']); } if (!isset($this->started[$id]['out'])) { - $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); + $message .= \sprintf('%s %s ', $this->getBorder($id), $prefix); $this->started[$id]['out'] = true; } - $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); + $message .= str_replace("\n", \sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); } return $message; @@ -76,10 +76,10 @@ public function stop(string $id, string $message, bool $successful, string $pref $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; if ($successful) { - return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + return \sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); } - $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + $message = \sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); unset($this->started[$id]['out'], $this->started[$id]['err']); @@ -88,7 +88,7 @@ public function stop(string $id, string $message, bool $successful, string $pref private function getBorder(string $id): string { - return sprintf(' ', self::COLORS[$this->started[$id]['border']]); + return \sprintf(' ', self::COLORS[$this->started[$id]['border']]); } public function getName(): string diff --git a/Helper/DescriptorHelper.php b/Helper/DescriptorHelper.php index 300c7b102..9422271fb 100644 --- a/Helper/DescriptorHelper.php +++ b/Helper/DescriptorHelper.php @@ -60,7 +60,7 @@ public function describe(OutputInterface $output, ?object $object, array $option ], $options); if (!isset($this->descriptors[$options['format']])) { - throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); + throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; diff --git a/Helper/FormatterHelper.php b/Helper/FormatterHelper.php index 279e4c799..3646b3d6f 100644 --- a/Helper/FormatterHelper.php +++ b/Helper/FormatterHelper.php @@ -25,7 +25,7 @@ class FormatterHelper extends Helper */ public function formatSection(string $section, string $message, string $style = 'info'): string { - return sprintf('<%s>[%s] %s', $style, $section, $style, $message); + return \sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** @@ -41,7 +41,7 @@ public function formatBlock(string|array $messages, string $style, bool $large = $lines = []; foreach ($messages as $message) { $message = OutputFormatter::escape($message); - $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); + $lines[] = \sprintf($large ? ' %s ' : ' %s ', $message); $len = max(self::width($message) + ($large ? 4 : 2), $len); } @@ -54,7 +54,7 @@ public function formatBlock(string|array $messages, string $style, bool $large = } for ($i = 0; isset($messages[$i]); ++$i) { - $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); + $messages[$i] = \sprintf('<%s>%s', $style, $messages[$i], $style); } return implode("\n", $messages); diff --git a/Helper/Helper.php b/Helper/Helper.php index de090063a..3981bbf3a 100644 --- a/Helper/Helper.php +++ b/Helper/Helper.php @@ -128,18 +128,18 @@ public static function formatTime(int|float $secs, int $precision = 1): string public static function formatMemory(int $memory): string { if ($memory >= 1024 * 1024 * 1024) { - return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); + return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); } if ($memory >= 1024 * 1024) { - return sprintf('%.1f MiB', $memory / 1024 / 1024); + return \sprintf('%.1f MiB', $memory / 1024 / 1024); } if ($memory >= 1024) { - return sprintf('%d KiB', $memory / 1024); + return \sprintf('%d KiB', $memory / 1024); } - return sprintf('%d B', $memory); + return \sprintf('%d B', $memory); } public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string): string diff --git a/Helper/HelperSet.php b/Helper/HelperSet.php index 30df9f958..ffe756c9d 100644 --- a/Helper/HelperSet.php +++ b/Helper/HelperSet.php @@ -61,7 +61,7 @@ public function has(string $name): bool public function get(string $name): HelperInterface { if (!$this->has($name)) { - throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + throw new InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; diff --git a/Helper/OutputWrapper.php b/Helper/OutputWrapper.php index 0ea2b7056..a615ed2f9 100644 --- a/Helper/OutputWrapper.php +++ b/Helper/OutputWrapper.php @@ -59,7 +59,7 @@ public function wrap(string $text, int $width, string $break = "\n"): string return $text; } - $tagPattern = sprintf('<(?:(?:%s)|/(?:%s)?)>', self::TAG_OPEN_REGEX_SEGMENT, self::TAG_CLOSE_REGEX_SEGMENT); + $tagPattern = \sprintf('<(?:(?:%s)|/(?:%s)?)>', self::TAG_OPEN_REGEX_SEGMENT, self::TAG_CLOSE_REGEX_SEGMENT); $limitPattern = "{1,$width}"; $patternBlocks = [$tagPattern]; if (!$this->allowCutUrls) { @@ -68,7 +68,7 @@ public function wrap(string $text, int $width, string $break = "\n"): string $patternBlocks[] = '.'; $blocks = implode('|', $patternBlocks); $rowPattern = "(?:$blocks)$limitPattern"; - $pattern = sprintf('#(?:((?>(%1$s)((?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|(%1$s))(?:\r?\n)?|(?:\r?\n|$))#imux', $rowPattern); + $pattern = \sprintf('#(?:((?>(%1$s)((?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|(%1$s))(?:\r?\n)?|(?:\r?\n|$))#imux', $rowPattern); $output = rtrim(preg_replace($pattern, '\\1'.$break, $text), $break); return str_replace(' '.$break, $break, $output); diff --git a/Helper/ProcessHelper.php b/Helper/ProcessHelper.php index 3ef6f71f7..ae55a83c2 100644 --- a/Helper/ProcessHelper.php +++ b/Helper/ProcessHelper.php @@ -55,7 +55,7 @@ public function run(OutputInterface $output, array|Process $cmd, ?string $error $process = $cmd[0]; unset($cmd[0]); } else { - throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); + throw new \InvalidArgumentException(\sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); } if ($verbosity <= $output->getVerbosity()) { @@ -69,12 +69,12 @@ public function run(OutputInterface $output, array|Process $cmd, ?string $error $process->run($callback, $cmd); if ($verbosity <= $output->getVerbosity()) { - $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); + $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode()); $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); } if (!$process->isSuccessful() && null !== $error) { - $output->writeln(sprintf('%s', $this->escapeString($error))); + $output->writeln(\sprintf('%s', $this->escapeString($error))); } return $process; diff --git a/Helper/ProgressBar.php b/Helper/ProgressBar.php index 7c22b7d55..5f1a32bc9 100644 --- a/Helper/ProgressBar.php +++ b/Helper/ProgressBar.php @@ -621,7 +621,7 @@ private function buildLine(): string } if (isset($matches[2])) { - $text = sprintf('%'.$matches[2], $text); + $text = \sprintf('%'.$matches[2], $text); } return $text; diff --git a/Helper/QuestionHelper.php b/Helper/QuestionHelper.php index 54825c6cd..69afc2a67 100644 --- a/Helper/QuestionHelper.php +++ b/Helper/QuestionHelper.php @@ -211,7 +211,7 @@ protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string foreach ($choices as $key => $value) { $padding = str_repeat(' ', $maxWidth - self::width($key)); - $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); + $messages[] = \sprintf(" [<$tag>%s$padding] %s", $key, $value); } return $messages; diff --git a/Helper/SymfonyQuestionHelper.php b/Helper/SymfonyQuestionHelper.php index 48d947b75..b452bf047 100644 --- a/Helper/SymfonyQuestionHelper.php +++ b/Helper/SymfonyQuestionHelper.php @@ -31,17 +31,17 @@ protected function writePrompt(OutputInterface $output, Question $question): voi $default = $question->getDefault(); if ($question->isMultiline()) { - $text .= sprintf(' (press %s to continue)', $this->getEofShortcut()); + $text .= \sprintf(' (press %s to continue)', $this->getEofShortcut()); } switch (true) { case null === $default: - $text = sprintf(' %s:', $text); + $text = \sprintf(' %s:', $text); break; case $question instanceof ConfirmationQuestion: - $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); + $text = \sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); break; @@ -53,18 +53,18 @@ protected function writePrompt(OutputInterface $output, Question $question): voi $default[$key] = $choices[trim($value)]; } - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); + $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); break; case $question instanceof ChoiceQuestion: $choices = $question->getChoices(); - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); + $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); break; default: - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); + $text = \sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); } $output->writeln($text); diff --git a/Helper/Table.php b/Helper/Table.php index 09709a28e..9ff73d2cc 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -79,7 +79,7 @@ public static function getStyleDefinition(string $name): TableStyle { self::$styles ??= self::initStyles(); - return self::$styles[$name] ?? throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name)); } /** @@ -164,7 +164,7 @@ public function setColumnWidths(array $widths): static public function setColumnMaxWidth(int $columnIndex, int $width): static { if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { - throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); + throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); } $this->columnMaxWidths[$columnIndex] = $width; @@ -233,7 +233,7 @@ public function addRow(TableSeparator|array $row): static public function appendRow(TableSeparator|array $row): static { if (!$this->output instanceof ConsoleSectionOutput) { - throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); + throw new RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); } if ($this->rendered) { @@ -364,14 +364,14 @@ public function render(): void foreach ($parts as $idx => $part) { if ($headers && !$containsColspan) { if (0 === $idx) { - $rows[] = [sprintf( + $rows[] = [\sprintf( '%s%s: %s', str_repeat(' ', $maxHeaderLength - Helper::width(Helper::removeDecoration($formatter, $headers[$i] ?? ''))), $headers[$i] ?? '', $part )]; } else { - $rows[] = [sprintf( + $rows[] = [\sprintf( '%s %s', str_pad('', $maxHeaderLength, ' ', \STR_PAD_LEFT), $part @@ -491,12 +491,12 @@ private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $ti } if (null !== $title) { - $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title))); + $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title))); $markupLength = Helper::width($markup); if ($titleLength > $limit = $markupLength - 4) { $titleLength = $limit; - $formatLength = Helper::width(Helper::removeDecoration($formatter, sprintf($titleFormat, ''))); - $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); + $formatLength = Helper::width(Helper::removeDecoration($formatter, \sprintf($titleFormat, ''))); + $formattedTitle = \sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); } $titleStart = intdiv($markupLength - $titleLength, 2); @@ -507,7 +507,7 @@ private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $ti } } - $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); + $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup)); } /** @@ -517,7 +517,7 @@ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string { $borders = $this->style->getBorderChars(); - return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); + return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); } /** @@ -565,11 +565,11 @@ private function renderCell(array $row, int $column, string $cellFormat): string $style = $this->getColumnStyle($column); if ($cell instanceof TableSeparator) { - return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); + return \sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); } $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell)); - $content = sprintf($style->getCellRowContentFormat(), $cell); + $content = \sprintf($style->getCellRowContentFormat(), $cell); $padType = $style->getPadType(); if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) { @@ -594,7 +594,7 @@ private function renderCell(array $row, int $column, string $cellFormat): string $padType = $cell->getStyle()->getPadByAlign(); } - return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType)); + return \sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType)); } /** @@ -691,7 +691,7 @@ private function fillNextRows(array $rows, int $line): array $unmergedRows = []; foreach ($rows[$line] as $column => $cell) { if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !$cell instanceof \Stringable) { - throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); + throw new InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); } if ($cell instanceof TableCell && $cell->getRowspan() > 1) { $nbLines = $cell->getRowspan() - 1; @@ -836,7 +836,7 @@ private function calculateColumnsWidth(iterable $groups): void private function getColumnSeparatorWidth(): int { - return Helper::width(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); + return Helper::width(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); } private function getCellWidth(array $row, int $column): int @@ -919,6 +919,6 @@ private function resolveStyle(TableStyle|string $name): TableStyle return $name; } - return self::$styles[$name] ?? throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name)); } } diff --git a/Helper/TableCell.php b/Helper/TableCell.php index 1c4eeea20..ab8339204 100644 --- a/Helper/TableCell.php +++ b/Helper/TableCell.php @@ -30,7 +30,7 @@ public function __construct( ) { // check option names if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); + throw new InvalidArgumentException(\sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); } if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) { diff --git a/Helper/TableCellStyle.php b/Helper/TableCellStyle.php index 49b97f853..af1a17e96 100644 --- a/Helper/TableCellStyle.php +++ b/Helper/TableCellStyle.php @@ -43,11 +43,11 @@ class TableCellStyle public function __construct(array $options = []) { if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff))); + throw new InvalidArgumentException(\sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff))); } if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) { - throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP)))); + throw new InvalidArgumentException(\sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP)))); } $this->options = array_merge($this->options, $options); diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index 2ebbdf086..e0f426510 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -51,7 +51,7 @@ public function __construct(?array $argv = null, ?InputDefinition $definition = foreach ($argv as $arg) { if (!\is_scalar($arg) && !$arg instanceof \Stringable) { - throw new RuntimeException(sprintf('Argument values expected to be all scalars, got "%s".', get_debug_type($arg))); + throw new RuntimeException(\sprintf('Argument values expected to be all scalars, got "%s".', get_debug_type($arg))); } } @@ -125,7 +125,7 @@ private function parseShortOptionSet(string $name): void for ($i = 0; $i < $len; ++$i) { if (!$this->definition->hasShortcut($name[$i])) { $encoding = mb_detect_encoding($name, null, true); - throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); + throw new RuntimeException(\sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); } $option = $this->definition->getOptionForShortcut($name[$i]); @@ -186,14 +186,14 @@ private function parseArgument(string $token): void if (\count($all)) { if ($symfonyCommandName) { - $message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all))); + $message = \sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all))); } else { - $message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))); + $message = \sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))); } } elseif ($symfonyCommandName) { - $message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token); + $message = \sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token); } else { - $message = sprintf('No arguments expected, got "%s".', $token); + $message = \sprintf('No arguments expected, got "%s".', $token); } throw new RuntimeException($message); @@ -208,7 +208,7 @@ private function parseArgument(string $token): void private function addShortOption(string $shortcut, mixed $value): void { if (!$this->definition->hasShortcut($shortcut)) { - throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); + throw new RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); @@ -223,12 +223,12 @@ private function addLongOption(string $name, mixed $value): void { if (!$this->definition->hasOption($name)) { if (!$this->definition->hasNegation($name)) { - throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + throw new RuntimeException(\sprintf('The "--%s" option does not exist.', $name)); } $optionName = $this->definition->negationToName($name); if (null !== $value) { - throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name)); } $this->options[$optionName] = false; @@ -238,7 +238,7 @@ private function addLongOption(string $name, mixed $value): void $option = $this->definition->getOption($name); if (null !== $value && !$option->acceptValue()) { - throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name)); } if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { @@ -254,7 +254,7 @@ private function addLongOption(string $name, mixed $value): void if (null === $value) { if ($option->isValueRequired()) { - throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + throw new RuntimeException(\sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray() && !$option->isValueOptional()) { diff --git a/Input/ArrayInput.php b/Input/ArrayInput.php index d27ff411e..7335632bf 100644 --- a/Input/ArrayInput.php +++ b/Input/ArrayInput.php @@ -135,7 +135,7 @@ protected function parse(): void private function addShortOption(string $shortcut, mixed $value): void { if (!$this->definition->hasShortcut($shortcut)) { - throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); + throw new InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); @@ -151,7 +151,7 @@ private function addLongOption(string $name, mixed $value): void { if (!$this->definition->hasOption($name)) { if (!$this->definition->hasNegation($name)) { - throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + throw new InvalidOptionException(\sprintf('The "--%s" option does not exist.', $name)); } $optionName = $this->definition->negationToName($name); @@ -164,7 +164,7 @@ private function addLongOption(string $name, mixed $value): void if (null === $value) { if ($option->isValueRequired()) { - throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); + throw new InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isValueOptional()) { @@ -183,7 +183,7 @@ private function addLongOption(string $name, mixed $value): void private function addArgument(string|int $name, mixed $value): void { if (!$this->definition->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; diff --git a/Input/Input.php b/Input/Input.php index 5a8b9a27a..d2881c60f 100644 --- a/Input/Input.php +++ b/Input/Input.php @@ -66,7 +66,7 @@ public function validate(): void $missingArguments = array_filter(array_keys($definition->getArguments()), fn ($argument) => !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired()); if (\count($missingArguments) > 0) { - throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); + throw new RuntimeException(\sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); } } @@ -88,7 +88,7 @@ public function getArguments(): array public function getArgument(string $name): mixed { if (!$this->definition->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault(); @@ -97,7 +97,7 @@ public function getArgument(string $name): mixed public function setArgument(string $name, mixed $value): void { if (!$this->definition->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; @@ -124,7 +124,7 @@ public function getOption(string $name): mixed } if (!$this->definition->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name)); } return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); @@ -137,7 +137,7 @@ public function setOption(string $name, mixed $value): void return; } elseif (!$this->definition->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name)); } $this->options[$name] = $value; diff --git a/Input/InputArgument.php b/Input/InputArgument.php index a5d949277..6fbb64ed0 100644 --- a/Input/InputArgument.php +++ b/Input/InputArgument.php @@ -62,7 +62,7 @@ public function __construct( if (null === $mode) { $mode = self::OPTIONAL; } elseif ($mode >= (self::IS_ARRAY << 1) || $mode < 1) { - throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); + throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode)); } $this->mode = $mode; @@ -143,7 +143,7 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti { $values = $this->suggestedValues; if ($values instanceof \Closure && !\is_array($values = $values($input))) { - throw new LogicException(sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, get_debug_type($values))); + throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, get_debug_type($values))); } if ($values) { $suggestions->suggestValues($values); diff --git a/Input/InputDefinition.php b/Input/InputDefinition.php index f27e29748..a8b006d48 100644 --- a/Input/InputDefinition.php +++ b/Input/InputDefinition.php @@ -97,15 +97,15 @@ public function addArguments(?array $arguments = []): void public function addArgument(InputArgument $argument): void { if (isset($this->arguments[$argument->getName()])) { - throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); + throw new LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName())); } if (null !== $this->lastArrayArgument) { - throw new LogicException(sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName())); + throw new LogicException(\sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName())); } if ($argument->isRequired() && null !== $this->lastOptionalArgument) { - throw new LogicException(sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName())); + throw new LogicException(\sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName())); } if ($argument->isArray()) { @@ -129,7 +129,7 @@ public function addArgument(InputArgument $argument): void public function getArgument(string|int $name): InputArgument { if (!$this->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; @@ -217,16 +217,16 @@ public function addOptions(array $options = []): void public function addOption(InputOption $option): void { if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { - throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName())); } if (isset($this->negations[$option->getName()])) { - throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName())); } if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { - throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); + throw new LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut)); } } } @@ -241,7 +241,7 @@ public function addOption(InputOption $option): void if ($option->isNegatable()) { $negatedName = 'no-'.$option->getName(); if (isset($this->options[$negatedName])) { - throw new LogicException(sprintf('An option named "%s" already exists.', $negatedName)); + throw new LogicException(\sprintf('An option named "%s" already exists.', $negatedName)); } $this->negations[$negatedName] = $option->getName(); } @@ -255,7 +255,7 @@ public function addOption(InputOption $option): void public function getOption(string $name): InputOption { if (!$this->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); + throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name)); } return $this->options[$name]; @@ -329,7 +329,7 @@ public function getOptionDefaults(): array public function shortcutToName(string $shortcut): string { if (!isset($this->shortcuts[$shortcut])) { - throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); + throw new InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut)); } return $this->shortcuts[$shortcut]; @@ -345,7 +345,7 @@ public function shortcutToName(string $shortcut): string public function negationToName(string $negation): string { if (!isset($this->negations[$negation])) { - throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $negation)); + throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $negation)); } return $this->negations[$negation]; @@ -364,7 +364,7 @@ public function getSynopsis(bool $short = false): string foreach ($this->getOptions() as $option) { $value = ''; if ($option->acceptValue()) { - $value = sprintf( + $value = \sprintf( ' %s%s%s', $option->isValueOptional() ? '[' : '', strtoupper($option->getName()), @@ -372,9 +372,9 @@ public function getSynopsis(bool $short = false): string ); } - $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; - $negation = $option->isNegatable() ? sprintf('|--no-%s', $option->getName()) : ''; - $elements[] = sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation); + $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : ''; + $negation = $option->isNegatable() ? \sprintf('|--no-%s', $option->getName()) : ''; + $elements[] = \sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation); } } diff --git a/Input/InputOption.php b/Input/InputOption.php index 617c348d5..25fb91782 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -99,7 +99,7 @@ public function __construct( if (null === $mode) { $mode = self::VALUE_NONE; } elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) { - throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); + throw new InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode)); } $this->name = $name; @@ -238,7 +238,7 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti { $values = $this->suggestedValues; if ($values instanceof \Closure && !\is_array($values = $values($input))) { - throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, get_debug_type($values))); + throw new LogicException(\sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, get_debug_type($values))); } if ($values) { $suggestions->suggestValues($values); diff --git a/Input/StringInput.php b/Input/StringInput.php index 835700143..a70f048f9 100644 --- a/Input/StringInput.php +++ b/Input/StringInput.php @@ -70,7 +70,7 @@ private function tokenize(string $input): array $token .= $match[1]; } else { // should never happen - throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10))); + throw new InvalidArgumentException(\sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10))); } $cursor += \strlen($match[0]); diff --git a/Logger/ConsoleLogger.php b/Logger/ConsoleLogger.php index ad6e49ce1..a6ef49ea9 100644 --- a/Logger/ConsoleLogger.php +++ b/Logger/ConsoleLogger.php @@ -63,7 +63,7 @@ public function __construct( public function log($level, $message, array $context = []): void { if (!isset($this->verbosityLevelMap[$level])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level)); } $output = $this->output; @@ -79,7 +79,7 @@ public function log($level, $message, array $context = []): void // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. // We only do it for efficiency here as the message formatting is relatively expensive. if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { - $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); + $output->writeln(\sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); } } diff --git a/Messenger/RunCommandMessageHandler.php b/Messenger/RunCommandMessageHandler.php index 1bc499494..0fdf7d017 100644 --- a/Messenger/RunCommandMessageHandler.php +++ b/Messenger/RunCommandMessageHandler.php @@ -41,7 +41,7 @@ public function __invoke(RunCommandMessage $message): RunCommandContext } if ($message->throwOnFailure && Command::SUCCESS !== $exitCode) { - throw new RunCommandFailedException(sprintf('Command "%s" exited with code "%s".', $message->input, $exitCode), new RunCommandContext($message, $exitCode, $output->fetch())); + throw new RunCommandFailedException(\sprintf('Command "%s" exited with code "%s".', $message->input, $exitCode), new RunCommandContext($message, $exitCode, $output->fetch())); } return new RunCommandContext($message, $exitCode, $output->fetch()); diff --git a/Output/AnsiColorMode.php b/Output/AnsiColorMode.php index ca40ffb79..dcdd1d5c4 100644 --- a/Output/AnsiColorMode.php +++ b/Output/AnsiColorMode.php @@ -51,7 +51,7 @@ public function convertFromHexToAnsiColorCode(string $hexColor): string } if (6 !== \strlen($hexColor)) { - throw new InvalidArgumentException(sprintf('Invalid "#%s" color.', $hexColor)); + throw new InvalidArgumentException(\sprintf('Invalid "#%s" color.', $hexColor)); } $color = hexdec($hexColor); @@ -63,7 +63,7 @@ public function convertFromHexToAnsiColorCode(string $hexColor): string return match ($this) { self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b), self::Ansi8 => '8;5;'.((string) $this->convertFromRGB($r, $g, $b)), - self::Ansi24 => sprintf('8;2;%d;%d;%d', $r, $g, $b), + self::Ansi24 => \sprintf('8;2;%d;%d;%d', $r, $g, $b), }; } diff --git a/Output/ConsoleSectionOutput.php b/Output/ConsoleSectionOutput.php index 09aa7fe99..44728dfd4 100644 --- a/Output/ConsoleSectionOutput.php +++ b/Output/ConsoleSectionOutput.php @@ -222,7 +222,7 @@ private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFr if ($numberOfLinesToClear > 0) { // move cursor up n lines - parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); + parent::doWrite(\sprintf("\x1b[%dA", $numberOfLinesToClear), false); // erase to end of screen parent::doWrite("\x1b[0J", false); } diff --git a/Output/TrimmedBufferOutput.php b/Output/TrimmedBufferOutput.php index c1862a2bd..f0f950545 100644 --- a/Output/TrimmedBufferOutput.php +++ b/Output/TrimmedBufferOutput.php @@ -27,7 +27,7 @@ class TrimmedBufferOutput extends Output public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null) { if ($maxLength <= 0) { - throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); + throw new InvalidArgumentException(\sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); } parent::__construct($verbosity, $decorated, $formatter); diff --git a/Question/ChoiceQuestion.php b/Question/ChoiceQuestion.php index 0ccad051c..d184ef76f 100644 --- a/Question/ChoiceQuestion.php +++ b/Question/ChoiceQuestion.php @@ -121,7 +121,7 @@ private function getDefaultValidator(): callable if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) { - throw new InvalidArgumentException(sprintf($errorMessage, $selected)); + throw new InvalidArgumentException(\sprintf($errorMessage, $selected)); } $selectedChoices = explode(',', (string) $selected); @@ -145,7 +145,7 @@ private function getDefaultValidator(): callable } if (\count($results) > 1) { - throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); + throw new InvalidArgumentException(\sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); } $result = array_search($value, $choices); @@ -161,7 +161,7 @@ private function getDefaultValidator(): callable } if (false === $result) { - throw new InvalidArgumentException(sprintf($errorMessage, $value)); + throw new InvalidArgumentException(\sprintf($errorMessage, $value)); } // For associative choices, consistently return the key as string: diff --git a/Style/SymfonyStyle.php b/Style/SymfonyStyle.php index 19ad892ef..4cf62cdba 100644 --- a/Style/SymfonyStyle.php +++ b/Style/SymfonyStyle.php @@ -73,8 +73,8 @@ public function title(string $message): void { $this->autoPrependBlock(); $this->writeln([ - sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('%s', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + \sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + \sprintf('%s', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), ]); $this->newLine(); } @@ -83,8 +83,8 @@ public function section(string $message): void { $this->autoPrependBlock(); $this->writeln([ - sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('%s', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + \sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + \sprintf('%s', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), ]); $this->newLine(); } @@ -92,7 +92,7 @@ public function section(string $message): void public function listing(array $elements): void { $this->autoPrependText(); - $elements = array_map(fn ($element) => sprintf(' * %s', $element), $elements); + $elements = array_map(fn ($element) => \sprintf(' * %s', $element), $elements); $this->writeln($elements); $this->newLine(); @@ -104,7 +104,7 @@ public function text(string|array $message): void $messages = \is_array($message) ? array_values($message) : [$message]; foreach ($messages as $message) { - $this->writeln(sprintf(' %s', $message)); + $this->writeln(\sprintf(' %s', $message)); } } @@ -404,7 +404,7 @@ private function createBlock(iterable $messages, ?string $type = null, ?string $ $lines = []; if (null !== $type) { - $type = sprintf('[%s] ', $type); + $type = \sprintf('[%s] ', $type); $indentLength = Helper::width($type); $lineIndentation = str_repeat(' ', $indentLength); } @@ -446,7 +446,7 @@ private function createBlock(iterable $messages, ?string $type = null, ?string $ $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0)); if ($style) { - $line = sprintf('<%s>%s', $style, $line); + $line = \sprintf('<%s>%s', $style, $line); } } diff --git a/Tester/Constraint/CommandIsSuccessful.php b/Tester/Constraint/CommandIsSuccessful.php index 09c6194b9..d677c27aa 100644 --- a/Tester/Constraint/CommandIsSuccessful.php +++ b/Tester/Constraint/CommandIsSuccessful.php @@ -38,6 +38,6 @@ protected function additionalFailureDescription($other): string Command::INVALID => 'Command was invalid.', ]; - return $mapping[$other] ?? sprintf('Command returned exit status %d.', $other); + return $mapping[$other] ?? \sprintf('Command returned exit status %d.', $other); } } diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index d8e1ae8b9..4fd2466e0 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -637,7 +637,7 @@ public function testFindAlternativeCommands() } catch (\Exception $e) { $this->assertInstanceOf(CommandNotFoundException::class, $e, '->find() throws a CommandNotFoundException if command does not exist'); $this->assertSame([], $e->getAlternatives()); - $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives'); + $this->assertEquals(\sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives'); } // Test if "bar1" command throw a "CommandNotFoundException" and does not contain @@ -648,7 +648,7 @@ public function testFindAlternativeCommands() } catch (\Exception $e) { $this->assertInstanceOf(CommandNotFoundException::class, $e, '->find() throws a CommandNotFoundException if command does not exist'); $this->assertSame(['afoobar1', 'foo:bar1'], $e->getAlternatives()); - $this->assertMatchesRegularExpression(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression(\sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); $this->assertMatchesRegularExpression('/afoobar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "afoobar1"'); $this->assertMatchesRegularExpression('/foo:bar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "foo:bar1"'); $this->assertDoesNotMatchRegularExpression('/foo:bar(?!1)/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without "foo:bar" alternative'); @@ -967,7 +967,7 @@ public function testRenderAnonymousException() $application = new Application(); $application->setAutoExit(false); $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); + throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); }); $tester = new ApplicationTester($application); @@ -993,7 +993,7 @@ public function testRenderExceptionStackTraceContainsRootException() $application = new Application(); $application->setAutoExit(false); $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); + throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); }); $tester = new ApplicationTester($application); diff --git a/Tests/Command/CommandTest.php b/Tests/Command/CommandTest.php index f3e4b51d1..199c0c309 100644 --- a/Tests/Command/CommandTest.php +++ b/Tests/Command/CommandTest.php @@ -139,7 +139,7 @@ public function testGetNamespaceGetNameSetName() public function testInvalidCommandNames($name) { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name)); + $this->expectExceptionMessage(\sprintf('Command name "%s" is invalid.', $name)); (new \TestCommand())->setName($name); } diff --git a/Tests/Descriptor/AbstractDescriptorTestCase.php b/Tests/Descriptor/AbstractDescriptorTestCase.php index 1f813048d..93658f4be 100644 --- a/Tests/Descriptor/AbstractDescriptorTestCase.php +++ b/Tests/Descriptor/AbstractDescriptorTestCase.php @@ -87,7 +87,7 @@ protected static function getDescriptionTestData(array $objects) { $data = []; foreach ($objects as $name => $object) { - $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, static::getFormat())); + $description = file_get_contents(\sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, static::getFormat())); $data[] = [$object, $description]; } diff --git a/Tests/Helper/ProgressIndicatorTest.php b/Tests/Helper/ProgressIndicatorTest.php index 7f7dbc0a0..8e2e10e37 100644 --- a/Tests/Helper/ProgressIndicatorTest.php +++ b/Tests/Helper/ProgressIndicatorTest.php @@ -179,6 +179,6 @@ protected function generateOutput($expected) { $count = substr_count($expected, "\n"); - return "\x0D\x1B[2K".($count ? sprintf("\033[%dA", $count) : '').$expected; + return "\x0D\x1B[2K".($count ? \sprintf("\033[%dA", $count) : '').$expected; } } diff --git a/Tests/Input/InputDefinitionTest.php b/Tests/Input/InputDefinitionTest.php index 470f3ca74..4479f4403 100644 --- a/Tests/Input/InputDefinitionTest.php +++ b/Tests/Input/InputDefinitionTest.php @@ -113,7 +113,7 @@ public function testRequiredArgumentCannotFollowAnOptionalOne() { $this->initializeArguments(); $this->expectException(\LogicException::class); - $this->expectExceptionMessage(sprintf('Cannot add a required argument "%s" after an optional one "%s".', $this->foo2->getName(), $this->foo->getName())); + $this->expectExceptionMessage(\sprintf('Cannot add a required argument "%s" after an optional one "%s".', $this->foo2->getName(), $this->foo->getName())); $definition = new InputDefinition(); $definition->addArgument($this->foo); diff --git a/Tests/Output/ConsoleSectionOutputTest.php b/Tests/Output/ConsoleSectionOutputTest.php index e50f8d54a..6d2fa6c3c 100644 --- a/Tests/Output/ConsoleSectionOutputTest.php +++ b/Tests/Output/ConsoleSectionOutputTest.php @@ -44,7 +44,7 @@ public function testClearAll() $output->clear(); rewind($output->getStream()); - $this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL.sprintf("\x1b[%dA", 2)."\x1b[0J", stream_get_contents($output->getStream())); + $this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL.\sprintf("\x1b[%dA", 2)."\x1b[0J", stream_get_contents($output->getStream())); } public function testClearNumberOfLines() @@ -56,7 +56,7 @@ public function testClearNumberOfLines() $output->clear(2); rewind($output->getStream()); - $this->assertEquals("Foo\nBar\nBaz\nFooBar".\PHP_EOL.sprintf("\x1b[%dA", 2)."\x1b[0J", stream_get_contents($output->getStream())); + $this->assertEquals("Foo\nBar\nBaz\nFooBar".\PHP_EOL.\sprintf("\x1b[%dA", 2)."\x1b[0J", stream_get_contents($output->getStream())); } public function testClearNumberOfLinesWithMultipleSections() @@ -197,7 +197,7 @@ public function testOverwriteMultipleLines() $output->overwrite('Bar'); rewind($output->getStream()); - $this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL.'Baz'.\PHP_EOL.sprintf("\x1b[%dA", 3)."\x1b[0J".'Bar'.\PHP_EOL, stream_get_contents($output->getStream())); + $this->assertEquals('Foo'.\PHP_EOL.'Bar'.\PHP_EOL.'Baz'.\PHP_EOL.\sprintf("\x1b[%dA", 3)."\x1b[0J".'Bar'.\PHP_EOL, stream_get_contents($output->getStream())); } public function testAddingMultipleSections() diff --git a/Tests/Question/ConfirmationQuestionTest.php b/Tests/Question/ConfirmationQuestionTest.php index 44f4c870b..bd11047b3 100644 --- a/Tests/Question/ConfirmationQuestionTest.php +++ b/Tests/Question/ConfirmationQuestionTest.php @@ -26,7 +26,7 @@ public function testDefaultRegexUsecases($default, $answers, $expected, $message foreach ($answers as $answer) { $normalizer = $sut->getNormalizer(); $actual = $normalizer($answer); - $this->assertEquals($expected, $actual, sprintf($message, $answer)); + $this->assertEquals($expected, $actual, \sprintf($message, $answer)); } } From f63a2ee79c1e330a378bb8262a02c7497f1662be Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 16 Jun 2024 17:17:26 +0200 Subject: [PATCH 03/31] chore: CS fixes --- Helper/ProgressIndicator.php | 1 - Tests/Input/InputDefinitionTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Helper/ProgressIndicator.php b/Helper/ProgressIndicator.php index 969d83539..4a9987a36 100644 --- a/Helper/ProgressIndicator.php +++ b/Helper/ProgressIndicator.php @@ -54,7 +54,6 @@ public function __construct( private int $indicatorChangeInterval = 100, ?array $indicatorValues = null, ) { - $format ??= $this->determineBestFormat(); $indicatorValues ??= ['-', '\\', '|', '/']; $indicatorValues = array_values($indicatorValues); diff --git a/Tests/Input/InputDefinitionTest.php b/Tests/Input/InputDefinitionTest.php index 4479f4403..a3fd3e2ea 100644 --- a/Tests/Input/InputDefinitionTest.php +++ b/Tests/Input/InputDefinitionTest.php @@ -179,7 +179,7 @@ public function testGetArgumentDefaults() new InputArgument('foo1', InputArgument::OPTIONAL), new InputArgument('foo2', InputArgument::OPTIONAL, '', 'default'), new InputArgument('foo3', InputArgument::OPTIONAL | InputArgument::IS_ARRAY), - // new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', [1, 2]), + // new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', [1, 2]), ]); $this->assertEquals(['foo1' => null, 'foo2' => 'default', 'foo3' => []], $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); From 5ed7b6cee62e34c6bdba8fb2fb1a4cbb4e0a15c3 Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Fri, 28 Jun 2024 15:26:34 +0700 Subject: [PATCH 04/31] Add return type to __toString() methods --- Completion/CompletionInput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Completion/CompletionInput.php b/Completion/CompletionInput.php index 7ba41c083..27c1c9105 100644 --- a/Completion/CompletionInput.php +++ b/Completion/CompletionInput.php @@ -226,7 +226,7 @@ private function isCursorFree(): bool return $this->currentIndex >= $nrOfTokens; } - public function __toString() + public function __toString(): string { $str = ''; foreach ($this->tokens as $i => $token) { From d36a5fe1861fafe285be56e2aede1d19fc648502 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 6 Jul 2024 09:57:16 +0200 Subject: [PATCH 05/31] Update .gitattributes --- .gitattributes | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index 84c7add05..14c3c3594 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /Tests export-ignore /phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore +/.git* export-ignore From 22e3436515bb5719c77a502cfd8cd5972e09805c Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Thu, 18 Jul 2024 14:04:31 +0700 Subject: [PATCH 06/31] [Console] Remove a redundant check in `ErrorListener` --- EventListener/ErrorListener.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/EventListener/ErrorListener.php b/EventListener/ErrorListener.php index 49915a498..87b0d70f1 100644 --- a/EventListener/ErrorListener.php +++ b/EventListener/ErrorListener.php @@ -75,19 +75,15 @@ public static function getSubscribedEvents(): array ]; } - private static function getInputString(ConsoleEvent $event): ?string + private static function getInputString(ConsoleEvent $event): string { $commandName = $event->getCommand()?->getName(); - $input = $event->getInput(); + $inputString = (string) $event->getInput(); - if ($input instanceof \Stringable) { - if ($commandName) { - return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); - } - - return (string) $input; + if ($commandName) { + return str_replace(["'$commandName'", "\"$commandName\""], $commandName, $inputString); } - return $commandName; + return $inputString; } } From f807c5379d2e4068c57ada1c5ee9b7a5c32cd64f Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 22 Jul 2024 09:20:55 +0200 Subject: [PATCH 07/31] Replace `TestCase::assertTrue(true)` with `TestCase::expectNotToPerformAssertions()` --- Tests/Command/CompleteCommandTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Command/CompleteCommandTest.php b/Tests/Command/CompleteCommandTest.php index 0f64fbc8e..27b998b36 100644 --- a/Tests/Command/CompleteCommandTest.php +++ b/Tests/Command/CompleteCommandTest.php @@ -53,6 +53,8 @@ public function testUnsupportedShellOption() public function testAdditionalShellSupport() { + $this->expectNotToPerformAssertions(); + $this->command = new CompleteCommand(['supported' => BashCompletionOutput::class]); $this->command->setApplication($this->application); $this->tester = new CommandTester($this->command); @@ -61,8 +63,6 @@ public function testAdditionalShellSupport() // verify that the default set of shells is still supported $this->execute(['--shell' => 'bash', '--current' => '1', '--input' => ['bin/console']]); - - $this->assertTrue(true); } /** From 43b48b29222efc89b65032409d6eb4d0c2883c34 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 22 Jul 2024 10:27:43 +0200 Subject: [PATCH 08/31] Use CPP where possible --- CI/GithubActionReporter.php | 8 +++----- Formatter/OutputFormatter.php | 9 ++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/CI/GithubActionReporter.php b/CI/GithubActionReporter.php index 28112c2a2..952d380d5 100644 --- a/CI/GithubActionReporter.php +++ b/CI/GithubActionReporter.php @@ -20,8 +20,6 @@ */ class GithubActionReporter { - private OutputInterface $output; - /** * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 */ @@ -42,9 +40,9 @@ class GithubActionReporter ',' => '%2C', ]; - public function __construct(OutputInterface $output) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + ) { } public static function isGithubActionEnvironment(): bool diff --git a/Formatter/OutputFormatter.php b/Formatter/OutputFormatter.php index 1f3d04a2e..3c8c287e8 100644 --- a/Formatter/OutputFormatter.php +++ b/Formatter/OutputFormatter.php @@ -23,7 +23,6 @@ */ class OutputFormatter implements WrappableOutputFormatterInterface { - private bool $decorated; private array $styles = []; private OutputFormatterStyleStack $styleStack; @@ -67,10 +66,10 @@ public static function escapeTrailingBackslash(string $text): string * * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances */ - public function __construct(bool $decorated = false, array $styles = []) - { - $this->decorated = $decorated; - + public function __construct( + private bool $decorated = false, + array $styles = [], + ) { $this->setStyle('error', new OutputFormatterStyle('white', 'red')); $this->setStyle('info', new OutputFormatterStyle('green')); $this->setStyle('comment', new OutputFormatterStyle('yellow')); From 8b3ee1c3ef9de3ade24c0ccb42377c334acd311f Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 19 Jul 2024 13:24:25 +0200 Subject: [PATCH 09/31] [Cache][Config][Console][DependencyInjection][FrameworkBundle] Remove dead code and useless casts --- Command/CompleteCommand.php | 8 ++++---- Descriptor/ReStructuredTextDescriptor.php | 2 +- Descriptor/XmlDescriptor.php | 8 +++----- Output/AnsiColorMode.php | 2 +- Output/TrimmedBufferOutput.php | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Command/CompleteCommand.php b/Command/CompleteCommand.php index df0cddabb..15eeea16a 100644 --- a/Command/CompleteCommand.php +++ b/Command/CompleteCommand.php @@ -98,13 +98,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int '', ''.date('Y-m-d H:i:s').'', 'Input: ("|" indicates the cursor position)', - ' '.(string) $completionInput, + ' '.$completionInput, 'Command:', - ' '.(string) implode(' ', $_SERVER['argv']), + ' '.implode(' ', $_SERVER['argv']), 'Messages:', ]); - $command = $this->findCommand($completionInput, $output); + $command = $this->findCommand($completionInput); if (null === $command) { $this->log(' No command found, completing using the Application class.'); @@ -185,7 +185,7 @@ private function createCompletionInput(InputInterface $input): CompletionInput return $completionInput; } - private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command + private function findCommand(CompletionInput $completionInput): ?Command { try { $inputName = $completionInput->getFirstArgument(); diff --git a/Descriptor/ReStructuredTextDescriptor.php b/Descriptor/ReStructuredTextDescriptor.php index 462b9bb0b..cbf49d879 100644 --- a/Descriptor/ReStructuredTextDescriptor.php +++ b/Descriptor/ReStructuredTextDescriptor.php @@ -92,7 +92,7 @@ protected function describeInputOption(InputOption $option, array $options = []) protected function describeInputDefinition(InputDefinition $definition, array $options = []): void { if ($showArguments = ((bool) $definition->getArguments())) { - $this->write("Arguments\n".str_repeat($this->subsubsectionChar, 9))."\n\n"; + $this->write("Arguments\n".str_repeat($this->subsubsectionChar, 9)); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); $this->describeInputArgument($argument); diff --git a/Descriptor/XmlDescriptor.php b/Descriptor/XmlDescriptor.php index 8e44c88c4..00055557c 100644 --- a/Descriptor/XmlDescriptor.php +++ b/Descriptor/XmlDescriptor.php @@ -208,11 +208,9 @@ private function getInputOptionDocument(InputOption $option): \DOMDocument $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - if ($defaults) { - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); } } diff --git a/Output/AnsiColorMode.php b/Output/AnsiColorMode.php index dcdd1d5c4..cde0539fe 100644 --- a/Output/AnsiColorMode.php +++ b/Output/AnsiColorMode.php @@ -62,7 +62,7 @@ public function convertFromHexToAnsiColorCode(string $hexColor): string return match ($this) { self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b), - self::Ansi8 => '8;5;'.((string) $this->convertFromRGB($r, $g, $b)), + self::Ansi8 => '8;5;'.$this->convertFromRGB($r, $g, $b), self::Ansi24 => \sprintf('8;2;%d;%d;%d', $r, $g, $b), }; } diff --git a/Output/TrimmedBufferOutput.php b/Output/TrimmedBufferOutput.php index f0f950545..33db072c5 100644 --- a/Output/TrimmedBufferOutput.php +++ b/Output/TrimmedBufferOutput.php @@ -53,6 +53,6 @@ protected function doWrite(string $message, bool $newline): void $this->buffer .= \PHP_EOL; } - $this->buffer = substr($this->buffer, 0 - $this->maxLength); + $this->buffer = substr($this->buffer, -$this->maxLength); } } From b54fbe5f9e6ac1b5ee9a82ee901708c96f1ff184 Mon Sep 17 00:00:00 2001 From: norbertosus <123432231+norbertosus@users.noreply.github.com> Date: Sat, 27 Jul 2024 01:53:07 +0200 Subject: [PATCH 10/31] Create devcontainer.json --- .devcontainer/devcontainer.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..ad93c14a0 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,5 @@ +{ + "image": "mcr.microsoft.com/devcontainers/universal:2", + "features": { + } +} From d48400b51d1bd1de2513afc097b2b6f3deaa88ab Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 31 Jul 2024 16:13:26 +0200 Subject: [PATCH 11/31] Remove unused code and unnecessary `else` branches --- Application.php | 2 -- Helper/ProgressBar.php | 2 +- Helper/ProgressIndicator.php | 2 +- Input/ArgvInput.php | 4 ++-- Output/AnsiColorMode.php | 10 +++++----- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Application.php b/Application.php index aa4af5c58..d90600c5e 100644 --- a/Application.php +++ b/Application.php @@ -383,8 +383,6 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) { $suggestions->suggestOptions($this->getDefinition()->getOptions()); - - return; } } diff --git a/Helper/ProgressBar.php b/Helper/ProgressBar.php index 5f1a32bc9..2dac1dfa2 100644 --- a/Helper/ProgressBar.php +++ b/Helper/ProgressBar.php @@ -610,7 +610,7 @@ private function buildLine(): string { \assert(null !== $this->format); - $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; + $regex = '{%([a-z\-_]+)(?:\:([^%]+))?%}i'; $callback = function ($matches) { if ($formatter = $this->getPlaceholderFormatter($matches[1])) { $text = $formatter($this, $this->output); diff --git a/Helper/ProgressIndicator.php b/Helper/ProgressIndicator.php index 4a9987a36..d06897d85 100644 --- a/Helper/ProgressIndicator.php +++ b/Helper/ProgressIndicator.php @@ -171,7 +171,7 @@ private function display(): void return; } - $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { + $this->overwrite(preg_replace_callback('{%([a-z\-_]+)(?:\:([^%]+))?%}i', function ($matches) { if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { return $formatter($this); } diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index e0f426510..fe25b861a 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -133,9 +133,9 @@ private function parseShortOptionSet(string $name): void $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); break; - } else { - $this->addLongOption($option->getName(), null); } + + $this->addLongOption($option->getName(), null); } } diff --git a/Output/AnsiColorMode.php b/Output/AnsiColorMode.php index cde0539fe..0e1422a27 100644 --- a/Output/AnsiColorMode.php +++ b/Output/AnsiColorMode.php @@ -96,11 +96,11 @@ private function degradeHexColorToAnsi8(int $r, int $g, int $b): int } return (int) round(($r - 8) / 247 * 24) + 232; - } else { - return 16 + - (36 * (int) round($r / 255 * 5)) + - (6 * (int) round($g / 255 * 5)) + - (int) round($b / 255 * 5); } + + return 16 + + (36 * (int) round($r / 255 * 5)) + + (6 * (int) round($g / 255 * 5)) + + (int) round($b / 255 * 5); } } From 7d6b78e000021ea69c8bf425cbbac326bf08720c Mon Sep 17 00:00:00 2001 From: Roy de Vos Burchart Date: Thu, 1 Aug 2024 17:21:17 +0200 Subject: [PATCH 12/31] Code style change in `@PER-CS2.0` affecting `@Symfony` (parentheses for anonymous classes) --- Tests/ApplicationTest.php | 4 ++-- Tests/Command/SingleCommandApplicationTest.php | 2 +- Tests/Messenger/RunCommandMessageHandlerTest.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index 84684bf84..a1884ff31 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -965,7 +965,7 @@ public function testRenderAnonymousException() $application = new Application(); $application->setAutoExit(false); $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); + throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class {})::class)); }); $tester = new ApplicationTester($application); @@ -991,7 +991,7 @@ public function testRenderExceptionStackTraceContainsRootException() $application = new Application(); $application->setAutoExit(false); $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class() {})::class)); + throw new \InvalidArgumentException(\sprintf('Dummy type "%s" is invalid.', (new class {})::class)); }); $tester = new ApplicationTester($application); diff --git a/Tests/Command/SingleCommandApplicationTest.php b/Tests/Command/SingleCommandApplicationTest.php index 8fae4876b..98000c0a7 100644 --- a/Tests/Command/SingleCommandApplicationTest.php +++ b/Tests/Command/SingleCommandApplicationTest.php @@ -21,7 +21,7 @@ class SingleCommandApplicationTest extends TestCase { public function testRun() { - $command = new class() extends SingleCommandApplication { + $command = new class extends SingleCommandApplication { protected function execute(InputInterface $input, OutputInterface $output): int { return 0; diff --git a/Tests/Messenger/RunCommandMessageHandlerTest.php b/Tests/Messenger/RunCommandMessageHandlerTest.php index adc31e0ec..58b33d565 100644 --- a/Tests/Messenger/RunCommandMessageHandlerTest.php +++ b/Tests/Messenger/RunCommandMessageHandlerTest.php @@ -86,7 +86,7 @@ private function createApplicationWithCommand(): Application $application = new Application(); $application->setAutoExit(false); $application->addCommands([ - new class() extends Command { + new class extends Command { public function configure(): void { $this From 7884dc76c55a618ca70cf3a5919277b053f703bb Mon Sep 17 00:00:00 2001 From: Artfaith Date: Fri, 19 Jul 2024 15:07:04 +0200 Subject: [PATCH 13/31] [PhpUnitBridge][Console][VarDumper] Add support for `FORCE_COLOR` environment variable --- CHANGELOG.md | 5 +++++ Output/StreamOutput.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d7f7179..a959f65d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.2 +--- + + * Add support for `FORCE_COLOR` environment variable + 7.1 --- diff --git a/Output/StreamOutput.php b/Output/StreamOutput.php index 84a7fa734..f77b49db6 100644 --- a/Output/StreamOutput.php +++ b/Output/StreamOutput.php @@ -94,6 +94,11 @@ protected function hasColorSupport(): bool return false; } + // Follow https://force-color.org/ + if ('' !== (($_SERVER['FORCE_COLOR'] ?? getenv('FORCE_COLOR'))[0] ?? '')) { + return true; + } + // Detect msysgit/mingw and assume this is a tty because detection // does not work correctly, see https://github.com/composer/composer/issues/9690 if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { From ee7ee22b1dabcff731b7d79d3633c96251ad8404 Mon Sep 17 00:00:00 2001 From: Will Rowe Date: Fri, 23 Aug 2024 11:21:30 -0400 Subject: [PATCH 14/31] [Console][Process] Add `$verbosity` argument to `mustRun` helper method --- CHANGELOG.md | 1 + Helper/ProcessHelper.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a959f65d8..5a3dd745a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add support for `FORCE_COLOR` environment variable + * Add `verbosity` argument to `mustRun` process helper method 7.1 --- diff --git a/Helper/ProcessHelper.php b/Helper/ProcessHelper.php index ae55a83c2..4a8cfc9d9 100644 --- a/Helper/ProcessHelper.php +++ b/Helper/ProcessHelper.php @@ -94,9 +94,9 @@ public function run(OutputInterface $output, array|Process $cmd, ?string $error * * @see run() */ - public function mustRun(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null): Process + public function mustRun(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process { - $process = $this->run($output, $cmd, $error, $callback); + $process = $this->run($output, $cmd, $error, $callback, $verbosity); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); From 07d683cda368a88df91d231aa97dfdfa02c4f3ac Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 5 Sep 2024 08:55:30 +0200 Subject: [PATCH 15/31] no longer use the internal TestFailure class --- .../Tester/Constraint/CommandIsSuccessfulTest.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Tests/Tester/Constraint/CommandIsSuccessfulTest.php b/Tests/Tester/Constraint/CommandIsSuccessfulTest.php index 7a2b4c719..61ab5d0f8 100644 --- a/Tests/Tester/Constraint/CommandIsSuccessfulTest.php +++ b/Tests/Tester/Constraint/CommandIsSuccessfulTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\TestFailure; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful; @@ -35,16 +34,9 @@ public function testUnsuccessfulCommand(string $expectedException, int $exitCode { $constraint = new CommandIsSuccessful(); - try { - $constraint->evaluate($exitCode); - } catch (ExpectationFailedException $e) { - $this->assertStringContainsString('Failed asserting that the command is successful.', TestFailure::exceptionToString($e)); - $this->assertStringContainsString($expectedException, TestFailure::exceptionToString($e)); - - return; - } - - $this->fail(); + $this->expectException(ExpectationFailedException::class); + $this->expectExceptionMessageMatches('/Failed asserting that the command is successful\..*'.$expectedException.'/s'); + $constraint->evaluate($exitCode); } public static function providesUnsuccessful(): iterable From e57e6e0355bf231a6befd5d8ff2940308f0005eb Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 19 Sep 2024 14:29:18 +0200 Subject: [PATCH 16/31] [Console] Add silent verbosity mode suppressing all output, including errors --- Application.php | 13 ++- CHANGELOG.md | 2 + Descriptor/ReStructuredTextDescriptor.php | 1 + Output/NullOutput.php | 9 +- Output/Output.php | 10 ++- Output/OutputInterface.php | 3 + Style/OutputStyle.php | 6 ++ Tests/ApplicationTest.php | 5 +- Tests/Command/CompleteCommandTest.php | 4 +- Tests/Command/ListCommandTest.php | 3 +- Tests/Fixtures/application_1.json | 44 +++++++++- Tests/Fixtures/application_1.md | 36 +++++++- Tests/Fixtures/application_1.txt | 3 +- Tests/Fixtures/application_1.xml | 20 ++++- Tests/Fixtures/application_2.json | 88 +++++++++++++++++-- Tests/Fixtures/application_2.md | 72 +++++++++++++-- Tests/Fixtures/application_2.txt | 3 +- Tests/Fixtures/application_2.xml | 40 +++++++-- .../application_filtered_namespace.txt | 3 +- Tests/Fixtures/application_mbstring.md | 48 +++++++++- Tests/Fixtures/application_mbstring.txt | 3 +- Tests/Fixtures/application_run1.txt | 3 +- Tests/Fixtures/application_run2.txt | 3 +- Tests/Fixtures/application_run3.txt | 3 +- Tests/Fixtures/application_run5.txt | 3 +- Tests/Output/NullOutputTest.php | 14 ++- Tests/Output/OutputTest.php | 1 + Tests/phpt/single_application/help_name.phpt | 3 +- 28 files changed, 385 insertions(+), 61 deletions(-) diff --git a/Application.php b/Application.php index d90600c5e..140ea5d72 100644 --- a/Application.php +++ b/Application.php @@ -913,6 +913,9 @@ protected function configureIO(InputInterface $input, OutputInterface $output): } switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -2: + $output->setVerbosity(OutputInterface::VERBOSITY_SILENT); + break; case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; @@ -930,7 +933,10 @@ protected function configureIO(InputInterface $input, OutputInterface $output): break; } - if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { + if (true === $input->hasParameterOption(['--silent'], true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_SILENT); + $shellVerbosity = -2; + } elseif (true === $input->hasParameterOption(['--quiet', '-q'], true)) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); $shellVerbosity = -1; } else { @@ -946,7 +952,7 @@ protected function configureIO(InputInterface $input, OutputInterface $output): } } - if (-1 === $shellVerbosity) { + if (0 > $shellVerbosity) { $input->setInteractive(false); } @@ -1082,7 +1088,8 @@ protected function getDefaultInputDefinition(): InputDefinition return new InputDefinition([ new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the '.$this->defaultCommand.' command'), - new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), + new InputOption('--silent', null, InputOption::VALUE_NONE, 'Do not output any message'), + new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Only errors are displayed. All other output is suppressed'), 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'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a3dd745a..e1581b5d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * Add support for `FORCE_COLOR` environment variable * Add `verbosity` argument to `mustRun` process helper method + * [BC BREAK] Add silent verbosity (`--silent`/`SHELL_VERBOSITY=-2`) to suppress all output, including errors + * Add `OutputInterface::isSilent()`, `Output::isSilent()`, `OutputStyle::isSilent()` methods 7.1 --- diff --git a/Descriptor/ReStructuredTextDescriptor.php b/Descriptor/ReStructuredTextDescriptor.php index cbf49d879..d2dde6fba 100644 --- a/Descriptor/ReStructuredTextDescriptor.php +++ b/Descriptor/ReStructuredTextDescriptor.php @@ -217,6 +217,7 @@ private function getNonDefaultOptions(InputDefinition $definition): array { $globalOptions = [ 'help', + 'silent', 'quiet', 'verbose', 'version', diff --git a/Output/NullOutput.php b/Output/NullOutput.php index 40ae33282..8bec706d4 100644 --- a/Output/NullOutput.php +++ b/Output/NullOutput.php @@ -54,14 +54,19 @@ public function setVerbosity(int $level): void public function getVerbosity(): int { - return self::VERBOSITY_QUIET; + return self::VERBOSITY_SILENT; } - public function isQuiet(): bool + public function isSilent(): bool { return true; } + public function isQuiet(): bool + { + return false; + } + public function isVerbose(): bool { return false; diff --git a/Output/Output.php b/Output/Output.php index 2bb105748..32e6cb241 100644 --- a/Output/Output.php +++ b/Output/Output.php @@ -17,13 +17,14 @@ /** * Base class for output classes. * - * There are five levels of verbosity: + * There are six levels of verbosity: * * * normal: no option passed (normal output) * * verbose: -v (more output) * * very verbose: -vv (highly extended output) * * debug: -vvv (all debug output) - * * quiet: -q (no output) + * * quiet: -q (only output errors) + * * silent: --silent (no output) * * @author Fabien Potencier */ @@ -74,6 +75,11 @@ public function getVerbosity(): int return $this->verbosity; } + public function isSilent(): bool + { + return self::VERBOSITY_SILENT === $this->verbosity; + } + public function isQuiet(): bool { return self::VERBOSITY_QUIET === $this->verbosity; diff --git a/Output/OutputInterface.php b/Output/OutputInterface.php index 41315fbf2..969a3b022 100644 --- a/Output/OutputInterface.php +++ b/Output/OutputInterface.php @@ -17,9 +17,12 @@ * OutputInterface is the interface implemented by all Output classes. * * @author Fabien Potencier + * + * @method bool isSilent() */ interface OutputInterface { + public const VERBOSITY_SILENT = 8; public const VERBOSITY_QUIET = 16; public const VERBOSITY_NORMAL = 32; public const VERBOSITY_VERBOSE = 64; diff --git a/Style/OutputStyle.php b/Style/OutputStyle.php index 9f62ea312..89a3a4177 100644 --- a/Style/OutputStyle.php +++ b/Style/OutputStyle.php @@ -78,6 +78,12 @@ public function getFormatter(): OutputFormatterInterface return $this->output->getFormatter(); } + public function isSilent(): bool + { + // @deprecated since Symfony 7.2, change to $this->output->isSilent() in 8.0 + return method_exists($this->output, 'isSilent') ? $this->output->isSilent() : self::VERBOSITY_SILENT === $this->output->getVerbosity(); + } + public function isQuiet(): bool { return $this->output->isQuiet(); diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index a1884ff31..0fa10d85a 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -851,12 +851,15 @@ public function testRenderException() putenv('COLUMNS=120'); $tester = new ApplicationTester($application); - $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_QUIET, 'capture_stderr_separately' => true]); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception'); $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true]); $this->assertStringContainsString('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); + $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_SILENT, 'capture_stderr_separately' => true]); + $this->assertSame('', $tester->getErrorOutput(true), '->renderException() renders nothing in SILENT verbosity'); + $tester->run(['command' => 'list', '--foo' => true], ['decorated' => false, 'capture_stderr_separately' => true]); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); diff --git a/Tests/Command/CompleteCommandTest.php b/Tests/Command/CompleteCommandTest.php index 27b998b36..75519eb49 100644 --- a/Tests/Command/CompleteCommandTest.php +++ b/Tests/Command/CompleteCommandTest.php @@ -119,9 +119,9 @@ public function testCompleteCommandInputDefinition(array $input, array $suggesti public static function provideCompleteCommandInputDefinitionInputs() { - yield 'definition' => [['bin/console', 'hello', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']]; + yield 'definition' => [['bin/console', 'hello', '-'], ['--help', '--silent', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']]; yield 'custom' => [['bin/console', 'hello'], ['Fabien', 'Robin', 'Wouter']]; - yield 'definition-aliased' => [['bin/console', 'ahoy', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']]; + yield 'definition-aliased' => [['bin/console', 'ahoy', '-'], ['--help', '--silent', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']]; yield 'custom-aliased' => [['bin/console', 'ahoy'], ['Fabien', 'Robin', 'Wouter']]; } diff --git a/Tests/Command/ListCommandTest.php b/Tests/Command/ListCommandTest.php index 20dfa8d30..a6ffc8ab5 100644 --- a/Tests/Command/ListCommandTest.php +++ b/Tests/Command/ListCommandTest.php @@ -80,7 +80,8 @@ public function testExecuteListsCommandsOrder() Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_1.json b/Tests/Fixtures/application_1.json index bd0bd94c7..1477659ad 100644 --- a/Tests/Fixtures/application_1.json +++ b/Tests/Fixtures/application_1.json @@ -29,13 +29,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -150,13 +159,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -262,13 +280,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -365,13 +392,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { diff --git a/Tests/Fixtures/application_1.md b/Tests/Fixtures/application_1.md index bb722c077..79d9b27aa 100644 --- a/Tests/Fixtures/application_1.md +++ b/Tests/Fixtures/application_1.md @@ -48,7 +48,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -58,6 +58,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -159,7 +169,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -169,6 +179,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -286,7 +306,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -296,6 +316,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug diff --git a/Tests/Fixtures/application_1.txt b/Tests/Fixtures/application_1.txt index f72f43a07..7fce7ce52 100644 --- a/Tests/Fixtures/application_1.txt +++ b/Tests/Fixtures/application_1.txt @@ -5,7 +5,8 @@ Console Tool Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_1.xml b/Tests/Fixtures/application_1.xml index d109e055f..d726cee35 100644 --- a/Tests/Fixtures/application_1.xml +++ b/Tests/Fixtures/application_1.xml @@ -32,9 +32,12 @@ - + @@ -71,9 +74,12 @@ - + @@ -126,9 +132,12 @@ - + @@ -188,9 +197,12 @@ - + diff --git a/Tests/Fixtures/application_2.json b/Tests/Fixtures/application_2.json index b3eb10bda..4a6f411f5 100644 --- a/Tests/Fixtures/application_2.json +++ b/Tests/Fixtures/application_2.json @@ -33,13 +33,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -154,13 +163,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -266,13 +284,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -369,13 +396,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -457,13 +493,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -553,13 +598,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -630,13 +684,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { @@ -709,13 +772,22 @@ "description": "Display help for the given command. When no command is given display help for the list command", "default": false }, + "silent": { + "name": "--silent", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, "quiet": { "name": "--quiet", "shortcut": "-q", "accept_value": false, "is_value_required": false, "is_multiple": false, - "description": "Do not output any message", + "description": "Only errors are displayed. All other output is suppressed", "default": false }, "verbose": { diff --git a/Tests/Fixtures/application_2.md b/Tests/Fixtures/application_2.md index d4802c747..37e6c28fc 100644 --- a/Tests/Fixtures/application_2.md +++ b/Tests/Fixtures/application_2.md @@ -61,7 +61,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -71,6 +71,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -172,7 +182,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -182,6 +192,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -299,7 +319,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -309,6 +329,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -374,7 +404,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -384,6 +414,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -465,7 +505,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -475,6 +515,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -537,7 +587,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -547,6 +597,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug diff --git a/Tests/Fixtures/application_2.txt b/Tests/Fixtures/application_2.txt index aed535fa4..1725b5fa6 100644 --- a/Tests/Fixtures/application_2.txt +++ b/Tests/Fixtures/application_2.txt @@ -5,7 +5,8 @@ My Symfony application v1.0 Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_2.xml b/Tests/Fixtures/application_2.xml index 6ee45c1fa..dd4b1800a 100644 --- a/Tests/Fixtures/application_2.xml +++ b/Tests/Fixtures/application_2.xml @@ -32,9 +32,12 @@ - + @@ -71,9 +74,12 @@ - + @@ -126,9 +132,12 @@ - + @@ -188,9 +197,12 @@ - + @@ -221,9 +233,12 @@ - + @@ -262,9 +277,12 @@ - + @@ -293,9 +311,12 @@ - + @@ -326,9 +347,12 @@ - + diff --git a/Tests/Fixtures/application_filtered_namespace.txt b/Tests/Fixtures/application_filtered_namespace.txt index c24da0bbc..762a7f68d 100644 --- a/Tests/Fixtures/application_filtered_namespace.txt +++ b/Tests/Fixtures/application_filtered_namespace.txt @@ -5,7 +5,8 @@ My Symfony application v1.0 Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_mbstring.md b/Tests/Fixtures/application_mbstring.md index e7bc69c71..5e31b7ef4 100644 --- a/Tests/Fixtures/application_mbstring.md +++ b/Tests/Fixtures/application_mbstring.md @@ -52,7 +52,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -62,6 +62,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -163,7 +173,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -173,6 +183,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -290,7 +310,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -300,6 +320,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug @@ -381,7 +411,7 @@ Display help for the given command. When no command is given display help for th * Is negatable: no * Default: `false` -#### `--quiet|-q` +#### `--silent` Do not output any message @@ -391,6 +421,16 @@ Do not output any message * Is negatable: no * Default: `false` +#### `--quiet|-q` + +Only errors are displayed. All other output is suppressed + +* Accept value: no +* Is value required: no +* Is multiple: no +* Is negatable: no +* Default: `false` + #### `--verbose|-v|-vv|-vvv` Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug diff --git a/Tests/Fixtures/application_mbstring.txt b/Tests/Fixtures/application_mbstring.txt index 73a47fff4..e904ddf05 100644 --- a/Tests/Fixtures/application_mbstring.txt +++ b/Tests/Fixtures/application_mbstring.txt @@ -5,7 +5,8 @@ MbString åpplicätion Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_run1.txt b/Tests/Fixtures/application_run1.txt index 0b24a777c..2d6f6c666 100644 --- a/Tests/Fixtures/application_run1.txt +++ b/Tests/Fixtures/application_run1.txt @@ -5,7 +5,8 @@ Usage: Options: -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_run2.txt b/Tests/Fixtures/application_run2.txt index ccd73d14c..8523e16a6 100644 --- a/Tests/Fixtures/application_run2.txt +++ b/Tests/Fixtures/application_run2.txt @@ -12,7 +12,8 @@ Options: --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] --short To skip describing commands' arguments -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_run3.txt b/Tests/Fixtures/application_run3.txt index ccd73d14c..8523e16a6 100644 --- a/Tests/Fixtures/application_run3.txt +++ b/Tests/Fixtures/application_run3.txt @@ -12,7 +12,8 @@ Options: --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] --short To skip describing commands' arguments -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Fixtures/application_run5.txt b/Tests/Fixtures/application_run5.txt index de3fdd346..c5696492d 100644 --- a/Tests/Fixtures/application_run5.txt +++ b/Tests/Fixtures/application_run5.txt @@ -11,7 +11,8 @@ Options: --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] --raw To output raw command help -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question diff --git a/Tests/Output/NullOutputTest.php b/Tests/Output/NullOutputTest.php index 1e0967ea5..4da46cf8f 100644 --- a/Tests/Output/NullOutputTest.php +++ b/Tests/Output/NullOutputTest.php @@ -35,10 +35,10 @@ public function testConstructor() public function testVerbosity() { $output = new NullOutput(); - $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() returns VERBOSITY_QUIET for NullOutput by default'); + $this->assertSame(OutputInterface::VERBOSITY_SILENT, $output->getVerbosity(), '->getVerbosity() returns VERBOSITY_SILENT for NullOutput by default'); $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); - $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput'); + $this->assertSame(OutputInterface::VERBOSITY_SILENT, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput'); } public function testGetFormatter() @@ -60,7 +60,7 @@ public function testSetVerbosity() { $output = new NullOutput(); $output->setVerbosity(Output::VERBOSITY_NORMAL); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity()); + $this->assertEquals(Output::VERBOSITY_SILENT, $output->getVerbosity()); } public function testSetDecorated() @@ -70,10 +70,16 @@ public function testSetDecorated() $this->assertFalse($output->isDecorated()); } + public function testIsSilent() + { + $output = new NullOutput(); + $this->assertTrue($output->isSilent()); + } + public function testIsQuiet() { $output = new NullOutput(); - $this->assertTrue($output->isQuiet()); + $this->assertFalse($output->isQuiet()); } public function testIsVerbose() diff --git a/Tests/Output/OutputTest.php b/Tests/Output/OutputTest.php index 8a1e2840e..64e491048 100644 --- a/Tests/Output/OutputTest.php +++ b/Tests/Output/OutputTest.php @@ -164,6 +164,7 @@ public function testWriteWithVerbosityOption($verbosity, $expected, $msg) public static function verbosityProvider() { return [ + [Output::VERBOSITY_SILENT, '', '->write() in SILENT mode never outputs'], [Output::VERBOSITY_QUIET, '2', '->write() in QUIET mode only outputs when an explicit QUIET verbosity is passed'], [Output::VERBOSITY_NORMAL, '123', '->write() in NORMAL mode outputs anything below an explicit VERBOSE verbosity'], [Output::VERBOSITY_VERBOSE, '1234', '->write() in VERBOSE mode outputs anything below an explicit VERY_VERBOSE verbosity'], diff --git a/Tests/phpt/single_application/help_name.phpt b/Tests/phpt/single_application/help_name.phpt index f3d220b72..3291c83c5 100644 --- a/Tests/phpt/single_application/help_name.phpt +++ b/Tests/phpt/single_application/help_name.phpt @@ -29,7 +29,8 @@ Usage: Options: -h, --help Display help for the given command. When no command is given display help for the %s command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question From 300899a19db417c7be602aff998525e831545787 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 24 Sep 2024 12:58:43 +0200 Subject: [PATCH 17/31] Fix `$this` calls to static ones when relevant --- Command/DumpCompletionCommand.php | 2 +- EventListener/ErrorListener.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index daf3553ab..2853fc5f4 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -35,7 +35,7 @@ protected function configure(): void $commandName = basename($fullCommand); $fullCommand = @realpath($fullCommand) ?: $fullCommand; - $shell = $this->guessShell(); + $shell = self::guessShell(); [$rcFile, $completionFile] = match ($shell) { 'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/$commandName.fish"], 'zsh' => ['~/.zshrc', '$fpath[1]/_'.$commandName], diff --git a/EventListener/ErrorListener.php b/EventListener/ErrorListener.php index 87b0d70f1..9acb0e41d 100644 --- a/EventListener/ErrorListener.php +++ b/EventListener/ErrorListener.php @@ -37,7 +37,7 @@ public function onConsoleError(ConsoleErrorEvent $event): void $error = $event->getError(); - if (!$inputString = $this->getInputString($event)) { + if (!$inputString = self::getInputString($event)) { $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); return; @@ -58,7 +58,7 @@ public function onConsoleTerminate(ConsoleTerminateEvent $event): void return; } - if (!$inputString = $this->getInputString($event)) { + if (!$inputString = self::getInputString($event)) { $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); return; From dde368aa236153442f39a63c7ed27395ccd415c6 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 24 Sep 2024 13:28:07 +0200 Subject: [PATCH 18/31] Remove useless parent method calls in tests --- Tests/Question/QuestionTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Question/QuestionTest.php b/Tests/Question/QuestionTest.php index 0bc6f75db..15d8212b9 100644 --- a/Tests/Question/QuestionTest.php +++ b/Tests/Question/QuestionTest.php @@ -20,7 +20,6 @@ class QuestionTest extends TestCase protected function setUp(): void { - parent::setUp(); $this->question = new Question('Test question'); } From dbccd36c99ceffc024f8ef557187b6f62b2058d2 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 26 Sep 2024 10:09:09 +0200 Subject: [PATCH 19/31] Remove unused imports --- Tests/Fixtures/Style/SymfonyStyle/command/command_19.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php b/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php index e44b18b76..e25a7ef29 100644 --- a/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php +++ b/Tests/Fixtures/Style/SymfonyStyle/command/command_19.php @@ -1,6 +1,5 @@ Date: Tue, 1 Oct 2024 15:17:35 +0200 Subject: [PATCH 20/31] Remove a few unnecessary full qualifier --- Tests/Helper/TableCellStyleTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tests/Helper/TableCellStyleTest.php b/Tests/Helper/TableCellStyleTest.php index ac80750eb..d934cf801 100644 --- a/Tests/Helper/TableCellStyleTest.php +++ b/Tests/Helper/TableCellStyleTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Tests\Helper; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Helper\TableCellStyle; class TableCellStyleTest extends TestCase @@ -21,7 +22,8 @@ public function testCreateTableCellStyle() $tableCellStyle = new TableCellStyle(['fg' => 'red']); $this->assertEquals('red', $tableCellStyle->getOptions()['fg']); - $this->expectException(\Symfony\Component\Console\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); + new TableCellStyle(['wrong_key' => null]); } } From 6f86f8da2384dbf2a251fae8e8e615a7fec95756 Mon Sep 17 00:00:00 2001 From: Laurens Laman Date: Fri, 28 Jun 2024 11:27:52 +0200 Subject: [PATCH 21/31] Add finished indicator to ProgressIndicator --- CHANGELOG.md | 1 + Helper/ProgressIndicator.php | 22 +++++++++++++-- Tests/Helper/ProgressIndicatorTest.php | 37 ++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1581b5d4..a7b3c0450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * Add `verbosity` argument to `mustRun` process helper method * [BC BREAK] Add silent verbosity (`--silent`/`SHELL_VERBOSITY=-2`) to suppress all output, including errors * Add `OutputInterface::isSilent()`, `Output::isSilent()`, `OutputStyle::isSilent()` methods + * Add a configurable finished indicator to the progress indicator to show that the progress is finished 7.1 --- diff --git a/Helper/ProgressIndicator.php b/Helper/ProgressIndicator.php index d06897d85..b6bbd0cfa 100644 --- a/Helper/ProgressIndicator.php +++ b/Helper/ProgressIndicator.php @@ -36,8 +36,10 @@ class ProgressIndicator private ?string $message = null; private array $indicatorValues; private int $indicatorCurrent; + private string $finishedIndicatorValue; private float $indicatorUpdateTime; private bool $started = false; + private bool $finished = false; /** * @var array @@ -53,10 +55,12 @@ public function __construct( ?string $format = null, private int $indicatorChangeInterval = 100, ?array $indicatorValues = null, + ?string $finishedIndicatorValue = null, ) { $format ??= $this->determineBestFormat(); $indicatorValues ??= ['-', '\\', '|', '/']; $indicatorValues = array_values($indicatorValues); + $finishedIndicatorValue ??= '✔'; if (2 > \count($indicatorValues)) { throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); @@ -64,6 +68,7 @@ public function __construct( $this->format = self::getFormatDefinition($format); $this->indicatorValues = $indicatorValues; + $this->finishedIndicatorValue = $finishedIndicatorValue; $this->startTime = time(); } @@ -88,6 +93,7 @@ public function start(string $message): void $this->message = $message; $this->started = true; + $this->finished = false; $this->startTime = time(); $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; $this->indicatorCurrent = 0; @@ -122,13 +128,25 @@ public function advance(): void /** * Finish the indicator with message. + * + * @param ?string $finishedIndicator */ - public function finish(string $message): void + public function finish(string $message/* , ?string $finishedIndicator = null */): void { + $finishedIndicator = 1 < \func_num_args() ? func_get_arg(1) : null; + if (null !== $finishedIndicator && !\is_string($finishedIndicator)) { + throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be of the type string or null, "%s" given.', __METHOD__, get_debug_type($finishedIndicator))); + } + if (!$this->started) { throw new LogicException('Progress indicator has not yet been started.'); } + if (null !== $finishedIndicator) { + $this->finishedIndicatorValue = $finishedIndicator; + } + + $this->finished = true; $this->message = $message; $this->display(); $this->output->writeln(''); @@ -215,7 +233,7 @@ private function getCurrentTimeInMilliseconds(): float private static function initPlaceholderFormatters(): array { return [ - 'indicator' => fn (self $indicator) => $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)], + 'indicator' => fn (self $indicator) => $indicator->finished ? $indicator->finishedIndicatorValue : $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)], 'message' => fn (self $indicator) => $indicator->message, 'elapsed' => fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime, 2), 'memory' => fn () => Helper::formatMemory(memory_get_usage(true)), diff --git a/Tests/Helper/ProgressIndicatorTest.php b/Tests/Helper/ProgressIndicatorTest.php index 8e2e10e37..2a4441d57 100644 --- a/Tests/Helper/ProgressIndicatorTest.php +++ b/Tests/Helper/ProgressIndicatorTest.php @@ -54,11 +54,11 @@ public function testDefaultIndicator() $this->generateOutput(' \\ Starting...'). $this->generateOutput(' \\ Advancing...'). $this->generateOutput(' | Advancing...'). - $this->generateOutput(' | Done...'). + $this->generateOutput(' ✔ Done...'). \PHP_EOL. $this->generateOutput(' - Starting Again...'). $this->generateOutput(' \\ Starting Again...'). - $this->generateOutput(' \\ Done Again...'). + $this->generateOutput(' ✔ Done Again...'). \PHP_EOL, stream_get_contents($output->getStream()) ); @@ -109,6 +109,39 @@ public function testCustomIndicatorValues() ); } + public function testCustomFinishedIndicatorValue() + { + $bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, ['a', 'b'], '✅'); + + $bar->start('Starting...'); + usleep(101000); + $bar->finish('Done'); + + rewind($output->getStream()); + + $this->assertSame( + $this->generateOutput(' a Starting...'). + $this->generateOutput(' ✅ Done').\PHP_EOL, + stream_get_contents($output->getStream()) + ); + } + + public function testCustomFinishedIndicatorWhenFinishingProcess() + { + $bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, ['a', 'b']); + + $bar->start('Starting...'); + $bar->finish('Process failed', '❌'); + + rewind($output->getStream()); + + $this->assertEquals( + $this->generateOutput(' a Starting...'). + $this->generateOutput(' ❌ Process failed').\PHP_EOL, + stream_get_contents($output->getStream()) + ); + } + public function testCannotSetInvalidIndicatorCharacters() { $this->expectException(\InvalidArgumentException::class); From 84539561c69f597508b990af8a552b7c05b6257e Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 3 Oct 2024 14:15:19 +0200 Subject: [PATCH 22/31] Various CS fix for consistency --- Tests/Fixtures/application_signalable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Fixtures/application_signalable.php b/Tests/Fixtures/application_signalable.php index 12cf744ea..978406637 100644 --- a/Tests/Fixtures/application_signalable.php +++ b/Tests/Fixtures/application_signalable.php @@ -12,7 +12,7 @@ } require $vendor.'/vendor/autoload.php'; -(new class() extends SingleCommandApplication implements SignalableCommandInterface { +(new class extends SingleCommandApplication implements SignalableCommandInterface { public function getSubscribedSignals(): array { return [SIGINT]; From 270fd988c707d8d3aeae056de564130d3cd1b2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Fri, 4 Oct 2024 11:00:10 +0200 Subject: [PATCH 23/31] [Console] Use assertSame for input tests --- Tests/Input/ArgvInputTest.php | 50 ++++++++++++------------- Tests/Input/ArrayInputTest.php | 20 +++++----- Tests/Input/InputArgumentTest.php | 10 ++--- Tests/Input/InputDefinitionTest.php | 58 ++++++++++++++--------------- Tests/Input/InputOptionTest.php | 32 ++++++++-------- Tests/Input/InputTest.php | 28 +++++++------- Tests/Input/StringInputTest.php | 10 ++--- 7 files changed, 104 insertions(+), 104 deletions(-) diff --git a/Tests/Input/ArgvInputTest.php b/Tests/Input/ArgvInputTest.php index 31b4b03dd..0e76f9ee6 100644 --- a/Tests/Input/ArgvInputTest.php +++ b/Tests/Input/ArgvInputTest.php @@ -26,17 +26,17 @@ public function testConstructor() $r = new \ReflectionObject($input); $p = $r->getProperty('tokens'); - $this->assertEquals(['foo'], $p->getValue($input), '__construct() automatically get its input from the argv server variable'); + $this->assertSame(['foo'], $p->getValue($input), '__construct() automatically get its input from the argv server variable'); } public function testParseArguments() { $input = new ArgvInput(['cli.php', 'foo']); $input->bind(new InputDefinition([new InputArgument('name')])); - $this->assertEquals(['name' => 'foo'], $input->getArguments(), '->parse() parses required arguments'); + $this->assertSame(['name' => 'foo'], $input->getArguments(), '->parse() parses required arguments'); $input->bind(new InputDefinition([new InputArgument('name')])); - $this->assertEquals(['name' => 'foo'], $input->getArguments(), '->parse() is stateless'); + $this->assertSame(['name' => 'foo'], $input->getArguments(), '->parse() is stateless'); } /** @@ -57,7 +57,7 @@ public function testParseOptionsNegatable($input, $options, $expectedOptions, $m { $input = new ArgvInput($input); $input->bind(new InputDefinition($options)); - $this->assertEquals($expectedOptions, $input->getOptions(), $message); + $this->assertSame($expectedOptions, $input->getOptions(), $message); } public static function provideOptions() @@ -363,7 +363,7 @@ public function testParseArrayArgument() $input = new ArgvInput(['cli.php', 'foo', 'bar', 'baz', 'bat']); $input->bind(new InputDefinition([new InputArgument('name', InputArgument::IS_ARRAY)])); - $this->assertEquals(['name' => ['foo', 'bar', 'baz', 'bat']], $input->getArguments(), '->parse() parses array arguments'); + $this->assertSame(['name' => ['foo', 'bar', 'baz', 'bat']], $input->getArguments(), '->parse() parses array arguments'); } public function testParseArrayOption() @@ -371,11 +371,11 @@ public function testParseArrayOption() $input = new ArgvInput(['cli.php', '--name=foo', '--name=bar', '--name=baz']); $input->bind(new InputDefinition([new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)])); - $this->assertEquals(['name' => ['foo', 'bar', 'baz']], $input->getOptions(), '->parse() parses array options ("--option=value" syntax)'); + $this->assertSame(['name' => ['foo', 'bar', 'baz']], $input->getOptions(), '->parse() parses array options ("--option=value" syntax)'); $input = new ArgvInput(['cli.php', '--name', 'foo', '--name', 'bar', '--name', 'baz']); $input->bind(new InputDefinition([new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)])); - $this->assertEquals(['name' => ['foo', 'bar', 'baz']], $input->getOptions(), '->parse() parses array options ("--option value" syntax)'); + $this->assertSame(['name' => ['foo', 'bar', 'baz']], $input->getOptions(), '->parse() parses array options ("--option value" syntax)'); $input = new ArgvInput(['cli.php', '--name=foo', '--name=bar', '--name=']); $input->bind(new InputDefinition([new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)])); @@ -393,12 +393,12 @@ public function testParseNegativeNumberAfterDoubleDash() { $input = new ArgvInput(['cli.php', '--', '-1']); $input->bind(new InputDefinition([new InputArgument('number')])); - $this->assertEquals(['number' => '-1'], $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); + $this->assertSame(['number' => '-1'], $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); $input = new ArgvInput(['cli.php', '-f', 'bar', '--', '-1']); $input->bind(new InputDefinition([new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)])); - $this->assertEquals(['foo' => 'bar'], $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence'); - $this->assertEquals(['number' => '-1'], $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); + $this->assertSame(['foo' => 'bar'], $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence'); + $this->assertSame(['number' => '-1'], $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); } public function testParseEmptyStringArgument() @@ -406,7 +406,7 @@ public function testParseEmptyStringArgument() $input = new ArgvInput(['cli.php', '-f', 'bar', '']); $input->bind(new InputDefinition([new InputArgument('empty'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)])); - $this->assertEquals(['empty' => ''], $input->getArguments(), '->parse() parses empty string arguments'); + $this->assertSame(['empty' => ''], $input->getArguments(), '->parse() parses empty string arguments'); } public function testGetFirstArgument() @@ -415,7 +415,7 @@ public function testGetFirstArgument() $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null when there is no arguments'); $input = new ArgvInput(['cli.php', '-fbbar', 'foo']); - $this->assertEquals('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input'); + $this->assertSame('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input'); $input = new ArgvInput(['cli.php', '--foo', 'fooval', 'bar']); $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('arg')])); @@ -495,7 +495,7 @@ public function testNoWarningOnInvalidParameterOption() // No warning thrown $this->assertFalse($input->hasParameterOption(['-m', ''])); - $this->assertEquals('dev', $input->getParameterOption(['-e', ''])); + $this->assertSame('dev', $input->getParameterOption(['-e', ''])); // No warning thrown $this->assertFalse($input->getParameterOption(['-m', ''])); } @@ -503,10 +503,10 @@ public function testNoWarningOnInvalidParameterOption() public function testToString() { $input = new ArgvInput(['cli.php', '-f', 'foo']); - $this->assertEquals('-f foo', (string) $input); + $this->assertSame('-f foo', (string) $input); $input = new ArgvInput(['cli.php', '-f', '--bar=foo', 'a b c d', "A\nB'C"]); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); + $this->assertSame('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); } /** @@ -515,7 +515,7 @@ public function testToString() public function testGetParameterOptionEqualSign($argv, $key, $default, $onlyParams, $expected) { $input = new ArgvInput($argv); - $this->assertEquals($expected, $input->getParameterOption($key, $default, $onlyParams), '->getParameterOption() returns the expected value'); + $this->assertSame($expected, $input->getParameterOption($key, $default, $onlyParams), '->getParameterOption() returns the expected value'); } public static function provideGetParameterOptionValues() @@ -539,33 +539,33 @@ public function testParseSingleDashAsArgument() { $input = new ArgvInput(['cli.php', '-']); $input->bind(new InputDefinition([new InputArgument('file')])); - $this->assertEquals(['file' => '-'], $input->getArguments(), '->parse() parses single dash as an argument'); + $this->assertSame(['file' => '-'], $input->getArguments(), '->parse() parses single dash as an argument'); } public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument() { $input = new ArgvInput(['cli.php', '--foo=', 'bar']); $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)])); - $this->assertEquals(['foo' => null], $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(['name' => 'bar'], $input->getArguments(), '->parse() parses required arguments'); + $this->assertSame(['foo' => ''], $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertSame(['name' => 'bar'], $input->getArguments(), '->parse() parses required arguments'); $input = new ArgvInput(['cli.php', '--foo=0', 'bar']); $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)])); - $this->assertEquals(['foo' => '0'], $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(['name' => 'bar'], $input->getArguments(), '->parse() parses required arguments'); + $this->assertSame(['foo' => '0'], $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertSame(['name' => 'bar'], $input->getArguments(), '->parse() parses required arguments'); } public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument() { $input = new ArgvInput(['cli.php', '--foo=', 'bar']); $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)])); - $this->assertEquals(['foo' => null], $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(['name' => 'bar'], $input->getArguments(), '->parse() parses optional arguments'); + $this->assertSame(['foo' => ''], $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertSame(['name' => 'bar'], $input->getArguments(), '->parse() parses optional arguments'); $input = new ArgvInput(['cli.php', '--foo=0', 'bar']); $input->bind(new InputDefinition([new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)])); - $this->assertEquals(['foo' => '0'], $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(['name' => 'bar'], $input->getArguments(), '->parse() parses optional arguments'); + $this->assertSame(['foo' => '0'], $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertSame(['name' => 'bar'], $input->getArguments(), '->parse() parses optional arguments'); } public function testGetRawTokensFalse() diff --git a/Tests/Input/ArrayInputTest.php b/Tests/Input/ArrayInputTest.php index d6fe32bb3..74d2c089f 100644 --- a/Tests/Input/ArrayInputTest.php +++ b/Tests/Input/ArrayInputTest.php @@ -24,9 +24,9 @@ public function testGetFirstArgument() $input = new ArrayInput([]); $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null if no argument were passed'); $input = new ArrayInput(['name' => 'Fabien']); - $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); + $this->assertSame('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); $input = new ArrayInput(['--foo' => 'bar', 'name' => 'Fabien']); - $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); + $this->assertSame('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); } public function testHasParameterOption() @@ -46,22 +46,22 @@ public function testHasParameterOption() public function testGetParameterOption() { $input = new ArrayInput(['name' => 'Fabien', '--foo' => 'bar']); - $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); - $this->assertEquals('default', $input->getParameterOption('--bar', 'default'), '->getParameterOption() returns the default value if an option is not present in the passed parameters'); + $this->assertSame('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); + $this->assertSame('default', $input->getParameterOption('--bar', 'default'), '->getParameterOption() returns the default value if an option is not present in the passed parameters'); $input = new ArrayInput(['Fabien', '--foo' => 'bar']); - $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); + $this->assertSame('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); $input = new ArrayInput(['--foo', '--', '--bar' => 'woop']); - $this->assertEquals('woop', $input->getParameterOption('--bar'), '->getParameterOption() returns the correct value if an option is present in the passed parameters'); - $this->assertEquals('default', $input->getParameterOption('--bar', 'default', true), '->getParameterOption() returns the default value if an option is present in the passed parameters after an end of options signal'); + $this->assertSame('woop', $input->getParameterOption('--bar'), '->getParameterOption() returns the correct value if an option is present in the passed parameters'); + $this->assertSame('default', $input->getParameterOption('--bar', 'default', true), '->getParameterOption() returns the default value if an option is present in the passed parameters after an end of options signal'); } public function testParseArguments() { $input = new ArrayInput(['name' => 'foo'], new InputDefinition([new InputArgument('name')])); - $this->assertEquals(['name' => 'foo'], $input->getArguments(), '->parse() parses required arguments'); + $this->assertSame(['name' => 'foo'], $input->getArguments(), '->parse() parses required arguments'); } /** @@ -71,7 +71,7 @@ public function testParseOptions($input, $options, $expectedOptions, $message) { $input = new ArrayInput($input, new InputDefinition($options)); - $this->assertEquals($expectedOptions, $input->getOptions(), $message); + $this->assertSame($expectedOptions, $input->getOptions(), $message); } public static function provideOptions(): array @@ -162,7 +162,7 @@ public static function provideInvalidInput(): array public function testToString() { $input = new ArrayInput(['-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C"]); - $this->assertEquals('-f -b bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); + $this->assertSame('-f -b bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); $input = new ArrayInput(['-b' => ['bval_1', 'bval_2'], '--f' => ['fval_1', 'fval_2']]); $this->assertSame('-b bval_1 -b bval_2 --f=fval_1 --f=fval_2', (string) $input); diff --git a/Tests/Input/InputArgumentTest.php b/Tests/Input/InputArgumentTest.php index 05447426c..a9d612f97 100644 --- a/Tests/Input/InputArgumentTest.php +++ b/Tests/Input/InputArgumentTest.php @@ -23,7 +23,7 @@ class InputArgumentTest extends TestCase public function testConstructor() { $argument = new InputArgument('foo'); - $this->assertEquals('foo', $argument->getName(), '__construct() takes a name as its first argument'); + $this->assertSame('foo', $argument->getName(), '__construct() takes a name as its first argument'); } public function testModes() @@ -62,13 +62,13 @@ public function testIsArray() public function testGetDescription() { $argument = new InputArgument('foo', null, 'Some description'); - $this->assertEquals('Some description', $argument->getDescription(), '->getDescription() return the message description'); + $this->assertSame('Some description', $argument->getDescription(), '->getDescription() return the message description'); } public function testGetDefault() { $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default'); - $this->assertEquals('default', $argument->getDefault(), '->getDefault() return the default value'); + $this->assertSame('default', $argument->getDefault(), '->getDefault() return the default value'); } public function testSetDefault() @@ -77,11 +77,11 @@ public function testSetDefault() $argument->setDefault(null); $this->assertNull($argument->getDefault(), '->setDefault() can reset the default value by passing null'); $argument->setDefault('another'); - $this->assertEquals('another', $argument->getDefault(), '->setDefault() changes the default value'); + $this->assertSame('another', $argument->getDefault(), '->setDefault() changes the default value'); $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY); $argument->setDefault([1, 2]); - $this->assertEquals([1, 2], $argument->getDefault(), '->setDefault() changes the default value'); + $this->assertSame([1, 2], $argument->getDefault(), '->setDefault() changes the default value'); } public function testSetDefaultWithRequiredArgument() diff --git a/Tests/Input/InputDefinitionTest.php b/Tests/Input/InputDefinitionTest.php index a3fd3e2ea..ab203e6e5 100644 --- a/Tests/Input/InputDefinitionTest.php +++ b/Tests/Input/InputDefinitionTest.php @@ -36,10 +36,10 @@ public function testConstructorArguments() $this->initializeArguments(); $definition = new InputDefinition(); - $this->assertEquals([], $definition->getArguments(), '__construct() creates a new InputDefinition object'); + $this->assertSame([], $definition->getArguments(), '__construct() creates a new InputDefinition object'); $definition = new InputDefinition([$this->foo, $this->bar]); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '__construct() takes an array of InputArgument objects as its first argument'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '__construct() takes an array of InputArgument objects as its first argument'); } public function testConstructorOptions() @@ -47,10 +47,10 @@ public function testConstructorOptions() $this->initializeOptions(); $definition = new InputDefinition(); - $this->assertEquals([], $definition->getOptions(), '__construct() creates a new InputDefinition object'); + $this->assertSame([], $definition->getOptions(), '__construct() creates a new InputDefinition object'); $definition = new InputDefinition([$this->foo, $this->bar]); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '__construct() takes an array of InputOption objects as its first argument'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '__construct() takes an array of InputOption objects as its first argument'); } public function testSetArguments() @@ -59,10 +59,10 @@ public function testSetArguments() $definition = new InputDefinition(); $definition->setArguments([$this->foo]); - $this->assertEquals(['foo' => $this->foo], $definition->getArguments(), '->setArguments() sets the array of InputArgument objects'); + $this->assertSame(['foo' => $this->foo], $definition->getArguments(), '->setArguments() sets the array of InputArgument objects'); $definition->setArguments([$this->bar]); - $this->assertEquals(['bar' => $this->bar], $definition->getArguments(), '->setArguments() clears all InputArgument objects'); + $this->assertSame(['bar' => $this->bar], $definition->getArguments(), '->setArguments() clears all InputArgument objects'); } public function testAddArguments() @@ -71,9 +71,9 @@ public function testAddArguments() $definition = new InputDefinition(); $definition->addArguments([$this->foo]); - $this->assertEquals(['foo' => $this->foo], $definition->getArguments(), '->addArguments() adds an array of InputArgument objects'); + $this->assertSame(['foo' => $this->foo], $definition->getArguments(), '->addArguments() adds an array of InputArgument objects'); $definition->addArguments([$this->bar]); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '->addArguments() does not clear existing InputArgument objects'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '->addArguments() does not clear existing InputArgument objects'); } public function testAddArgument() @@ -82,9 +82,9 @@ public function testAddArgument() $definition = new InputDefinition(); $definition->addArgument($this->foo); - $this->assertEquals(['foo' => $this->foo], $definition->getArguments(), '->addArgument() adds a InputArgument object'); + $this->assertSame(['foo' => $this->foo], $definition->getArguments(), '->addArgument() adds a InputArgument object'); $definition->addArgument($this->bar); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '->addArgument() adds a InputArgument object'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getArguments(), '->addArgument() adds a InputArgument object'); } public function testArgumentsMustHaveDifferentNames() @@ -126,7 +126,7 @@ public function testGetArgument() $definition = new InputDefinition(); $definition->addArguments([$this->foo]); - $this->assertEquals($this->foo, $definition->getArgument('foo'), '->getArgument() returns a InputArgument by its name'); + $this->assertSame($this->foo, $definition->getArgument('foo'), '->getArgument() returns a InputArgument by its name'); } public function testGetInvalidArgument() @@ -157,9 +157,9 @@ public function testGetArgumentRequiredCount() $definition = new InputDefinition(); $definition->addArgument($this->foo2); - $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); + $this->assertSame(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); $definition->addArgument($this->foo); - $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); + $this->assertSame(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); } public function testGetArgumentCount() @@ -168,9 +168,9 @@ public function testGetArgumentCount() $definition = new InputDefinition(); $definition->addArgument($this->foo2); - $this->assertEquals(1, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); + $this->assertSame(1, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); $definition->addArgument($this->foo); - $this->assertEquals(2, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); + $this->assertSame(2, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); } public function testGetArgumentDefaults() @@ -181,12 +181,12 @@ public function testGetArgumentDefaults() new InputArgument('foo3', InputArgument::OPTIONAL | InputArgument::IS_ARRAY), // new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', [1, 2]), ]); - $this->assertEquals(['foo1' => null, 'foo2' => 'default', 'foo3' => []], $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); + $this->assertSame(['foo1' => null, 'foo2' => 'default', 'foo3' => []], $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); $definition = new InputDefinition([ new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', [1, 2]), ]); - $this->assertEquals(['foo4' => [1, 2]], $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); + $this->assertSame(['foo4' => [1, 2]], $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); } public function testSetOptions() @@ -194,9 +194,9 @@ public function testSetOptions() $this->initializeOptions(); $definition = new InputDefinition([$this->foo]); - $this->assertEquals(['foo' => $this->foo], $definition->getOptions(), '->setOptions() sets the array of InputOption objects'); + $this->assertSame(['foo' => $this->foo], $definition->getOptions(), '->setOptions() sets the array of InputOption objects'); $definition->setOptions([$this->bar]); - $this->assertEquals(['bar' => $this->bar], $definition->getOptions(), '->setOptions() clears all InputOption objects'); + $this->assertSame(['bar' => $this->bar], $definition->getOptions(), '->setOptions() clears all InputOption objects'); } public function testSetOptionsClearsOptions() @@ -215,9 +215,9 @@ public function testAddOptions() $this->initializeOptions(); $definition = new InputDefinition([$this->foo]); - $this->assertEquals(['foo' => $this->foo], $definition->getOptions(), '->addOptions() adds an array of InputOption objects'); + $this->assertSame(['foo' => $this->foo], $definition->getOptions(), '->addOptions() adds an array of InputOption objects'); $definition->addOptions([$this->bar]); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '->addOptions() does not clear existing InputOption objects'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '->addOptions() does not clear existing InputOption objects'); } public function testAddOption() @@ -226,9 +226,9 @@ public function testAddOption() $definition = new InputDefinition(); $definition->addOption($this->foo); - $this->assertEquals(['foo' => $this->foo], $definition->getOptions(), '->addOption() adds a InputOption object'); + $this->assertSame(['foo' => $this->foo], $definition->getOptions(), '->addOption() adds a InputOption object'); $definition->addOption($this->bar); - $this->assertEquals(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '->addOption() adds a InputOption object'); + $this->assertSame(['foo' => $this->foo, 'bar' => $this->bar], $definition->getOptions(), '->addOption() adds a InputOption object'); } public function testAddDuplicateOption() @@ -278,7 +278,7 @@ public function testGetOption() $this->initializeOptions(); $definition = new InputDefinition([$this->foo]); - $this->assertEquals($this->foo, $definition->getOption('foo'), '->getOption() returns a InputOption by its name'); + $this->assertSame($this->foo, $definition->getOption('foo'), '->getOption() returns a InputOption by its name'); } public function testGetInvalidOption() @@ -314,7 +314,7 @@ public function testGetOptionForShortcut() $this->initializeOptions(); $definition = new InputDefinition([$this->foo]); - $this->assertEquals($this->foo, $definition->getOptionForShortcut('f'), '->getOptionForShortcut() returns a InputOption by its shortcut'); + $this->assertSame($this->foo, $definition->getOptionForShortcut('f'), '->getOptionForShortcut() returns a InputOption by its shortcut'); } public function testGetOptionForMultiShortcut() @@ -322,8 +322,8 @@ public function testGetOptionForMultiShortcut() $this->initializeOptions(); $definition = new InputDefinition([$this->multi]); - $this->assertEquals($this->multi, $definition->getOptionForShortcut('m'), '->getOptionForShortcut() returns a InputOption by its shortcut'); - $this->assertEquals($this->multi, $definition->getOptionForShortcut('mmm'), '->getOptionForShortcut() returns a InputOption by its shortcut'); + $this->assertSame($this->multi, $definition->getOptionForShortcut('m'), '->getOptionForShortcut() returns a InputOption by its shortcut'); + $this->assertSame($this->multi, $definition->getOptionForShortcut('mmm'), '->getOptionForShortcut() returns a InputOption by its shortcut'); } public function testGetOptionForInvalidShortcut() @@ -364,7 +364,7 @@ public function testGetOptionDefaults() */ public function testGetSynopsis(InputDefinition $definition, $expectedSynopsis, $message = null) { - $this->assertEquals($expectedSynopsis, $definition->getSynopsis(), $message ? '->getSynopsis() '.$message : ''); + $this->assertSame($expectedSynopsis, $definition->getSynopsis(), $message ? '->getSynopsis() '.$message : ''); } public static function getGetSynopsisData() @@ -388,7 +388,7 @@ public static function getGetSynopsisData() public function testGetShortSynopsis() { $definition = new InputDefinition([new InputOption('foo'), new InputOption('bar'), new InputArgument('cat')]); - $this->assertEquals('[options] [--] []', $definition->getSynopsis(true), '->getSynopsis(true) groups options in [options]'); + $this->assertSame('[options] [--] []', $definition->getSynopsis(true), '->getSynopsis(true) groups options in [options]'); } protected function initializeArguments() diff --git a/Tests/Input/InputOptionTest.php b/Tests/Input/InputOptionTest.php index 7e3fb16da..47ab503f7 100644 --- a/Tests/Input/InputOptionTest.php +++ b/Tests/Input/InputOptionTest.php @@ -23,9 +23,9 @@ class InputOptionTest extends TestCase public function testConstructor() { $option = new InputOption('foo'); - $this->assertEquals('foo', $option->getName(), '__construct() takes a name as its first argument'); + $this->assertSame('foo', $option->getName(), '__construct() takes a name as its first argument'); $option = new InputOption('--foo'); - $this->assertEquals('foo', $option->getName(), '__construct() removes the leading -- of the option name'); + $this->assertSame('foo', $option->getName(), '__construct() removes the leading -- of the option name'); } public function testArrayModeWithoutValue() @@ -52,11 +52,11 @@ public function testBooleanWithOptional() public function testShortcut() { $option = new InputOption('foo', 'f'); - $this->assertEquals('f', $option->getShortcut(), '__construct() can take a shortcut as its second argument'); + $this->assertSame('f', $option->getShortcut(), '__construct() can take a shortcut as its second argument'); $option = new InputOption('foo', '-f|-ff|fff'); - $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); + $this->assertSame('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); $option = new InputOption('foo', ['f', 'ff', '-fff']); - $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); + $this->assertSame('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); $option = new InputOption('foo'); $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null by default'); $option = new InputOption('foo', ''); @@ -64,15 +64,15 @@ public function testShortcut() $option = new InputOption('foo', []); $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null when given an empty array'); $option = new InputOption('foo', ['f', '', 'fff']); - $this->assertEquals('f|fff', $option->getShortcut(), '__construct() removes empty shortcuts'); + $this->assertSame('f|fff', $option->getShortcut(), '__construct() removes empty shortcuts'); $option = new InputOption('foo', 'f||fff'); - $this->assertEquals('f|fff', $option->getShortcut(), '__construct() removes empty shortcuts'); + $this->assertSame('f|fff', $option->getShortcut(), '__construct() removes empty shortcuts'); $option = new InputOption('foo', '0'); - $this->assertEquals('0', $option->getShortcut(), '-0 is an acceptable shortcut value'); + $this->assertSame('0', $option->getShortcut(), '-0 is an acceptable shortcut value'); $option = new InputOption('foo', ['0', 'z']); - $this->assertEquals('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in an array'); + $this->assertSame('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in an array'); $option = new InputOption('foo', '0|z'); - $this->assertEquals('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in a string-list'); + $this->assertSame('0|z', $option->getShortcut(), '-0 is an acceptable shortcut value when embedded in a string-list'); $option = new InputOption('foo', false); $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null when given a false as value'); } @@ -142,22 +142,22 @@ public function testIsArray() public function testGetDescription() { $option = new InputOption('foo', 'f', null, 'Some description'); - $this->assertEquals('Some description', $option->getDescription(), '->getDescription() returns the description message'); + $this->assertSame('Some description', $option->getDescription(), '->getDescription() returns the description message'); } public function testGetDefault() { $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL, '', 'default'); - $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value'); + $this->assertSame('default', $option->getDefault(), '->getDefault() returns the default value'); $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default'); - $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value'); + $this->assertSame('default', $option->getDefault(), '->getDefault() returns the default value'); $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED); $this->assertNull($option->getDefault(), '->getDefault() returns null if no default value is configured'); $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY); - $this->assertEquals([], $option->getDefault(), '->getDefault() returns an empty array if option is an array'); + $this->assertSame([], $option->getDefault(), '->getDefault() returns an empty array if option is an array'); $option = new InputOption('foo', null, InputOption::VALUE_NONE); $this->assertFalse($option->getDefault(), '->getDefault() returns false if the option does not take a value'); @@ -169,11 +169,11 @@ public function testSetDefault() $option->setDefault(null); $this->assertNull($option->getDefault(), '->setDefault() can reset the default value by passing null'); $option->setDefault('another'); - $this->assertEquals('another', $option->getDefault(), '->setDefault() changes the default value'); + $this->assertSame('another', $option->getDefault(), '->setDefault() changes the default value'); $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY); $option->setDefault([1, 2]); - $this->assertEquals([1, 2], $option->getDefault(), '->setDefault() changes the default value'); + $this->assertSame([1, 2], $option->getDefault(), '->setDefault() changes the default value'); } public function testDefaultValueWithValueNoneMode() diff --git a/Tests/Input/InputTest.php b/Tests/Input/InputTest.php index 34fb4833b..19a840da6 100644 --- a/Tests/Input/InputTest.php +++ b/Tests/Input/InputTest.php @@ -22,29 +22,29 @@ class InputTest extends TestCase public function testConstructor() { $input = new ArrayInput(['name' => 'foo'], new InputDefinition([new InputArgument('name')])); - $this->assertEquals('foo', $input->getArgument('name'), '->__construct() takes a InputDefinition as an argument'); + $this->assertSame('foo', $input->getArgument('name'), '->__construct() takes a InputDefinition as an argument'); } public function testOptions() { $input = new ArrayInput(['--name' => 'foo'], new InputDefinition([new InputOption('name')])); - $this->assertEquals('foo', $input->getOption('name'), '->getOption() returns the value for the given option'); + $this->assertSame('foo', $input->getOption('name'), '->getOption() returns the value for the given option'); $input->setOption('name', 'bar'); - $this->assertEquals('bar', $input->getOption('name'), '->setOption() sets the value for a given option'); - $this->assertEquals(['name' => 'bar'], $input->getOptions(), '->getOptions() returns all option values'); + $this->assertSame('bar', $input->getOption('name'), '->setOption() sets the value for a given option'); + $this->assertSame(['name' => 'bar'], $input->getOptions(), '->getOptions() returns all option values'); $input = new ArrayInput(['--name' => 'foo'], new InputDefinition([new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')])); - $this->assertEquals('default', $input->getOption('bar'), '->getOption() returns the default value for optional options'); - $this->assertEquals(['name' => 'foo', 'bar' => 'default'], $input->getOptions(), '->getOptions() returns all option values, even optional ones'); + $this->assertSame('default', $input->getOption('bar'), '->getOption() returns the default value for optional options'); + $this->assertSame(['name' => 'foo', 'bar' => 'default'], $input->getOptions(), '->getOptions() returns all option values, even optional ones'); $input = new ArrayInput(['--name' => 'foo', '--bar' => ''], new InputDefinition([new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')])); - $this->assertEquals('', $input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); - $this->assertEquals(['name' => 'foo', 'bar' => ''], $input->getOptions(), '->getOptions() returns all option values.'); + $this->assertSame('', $input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); + $this->assertSame(['name' => 'foo', 'bar' => ''], $input->getOptions(), '->getOptions() returns all option values.'); $input = new ArrayInput(['--name' => 'foo', '--bar' => null], new InputDefinition([new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')])); $this->assertNull($input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); - $this->assertEquals(['name' => 'foo', 'bar' => null], $input->getOptions(), '->getOptions() returns all option values'); + $this->assertSame(['name' => 'foo', 'bar' => null], $input->getOptions(), '->getOptions() returns all option values'); $input = new ArrayInput(['--name' => null], new InputDefinition([new InputOption('name', null, InputOption::VALUE_NEGATABLE)])); $this->assertTrue($input->hasOption('name')); @@ -84,15 +84,15 @@ public function testGetInvalidOption() public function testArguments() { $input = new ArrayInput(['name' => 'foo'], new InputDefinition([new InputArgument('name')])); - $this->assertEquals('foo', $input->getArgument('name'), '->getArgument() returns the value for the given argument'); + $this->assertSame('foo', $input->getArgument('name'), '->getArgument() returns the value for the given argument'); $input->setArgument('name', 'bar'); - $this->assertEquals('bar', $input->getArgument('name'), '->setArgument() sets the value for a given argument'); - $this->assertEquals(['name' => 'bar'], $input->getArguments(), '->getArguments() returns all argument values'); + $this->assertSame('bar', $input->getArgument('name'), '->setArgument() sets the value for a given argument'); + $this->assertSame(['name' => 'bar'], $input->getArguments(), '->getArguments() returns all argument values'); $input = new ArrayInput(['name' => 'foo'], new InputDefinition([new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default')])); - $this->assertEquals('default', $input->getArgument('bar'), '->getArgument() returns the default value for optional arguments'); - $this->assertEquals(['name' => 'foo', 'bar' => 'default'], $input->getArguments(), '->getArguments() returns all argument values, even optional ones'); + $this->assertSame('default', $input->getArgument('bar'), '->getArgument() returns the default value for optional arguments'); + $this->assertSame(['name' => 'foo', 'bar' => 'default'], $input->getArguments(), '->getArguments() returns all argument values, even optional ones'); } public function testSetInvalidArgument() diff --git a/Tests/Input/StringInputTest.php b/Tests/Input/StringInputTest.php index 338c1428a..92425daab 100644 --- a/Tests/Input/StringInputTest.php +++ b/Tests/Input/StringInputTest.php @@ -27,7 +27,7 @@ public function testTokenize($input, $tokens, $message) $input = new StringInput($input); $r = new \ReflectionClass(ArgvInput::class); $p = $r->getProperty('tokens'); - $this->assertEquals($tokens, $p->getValue($input), $message); + $this->assertSame($tokens, $p->getValue($input), $message); } public function testInputOptionWithGivenString() @@ -39,7 +39,7 @@ public function testInputOptionWithGivenString() // call to bind $input = new StringInput('--foo=bar'); $input->bind($definition); - $this->assertEquals('bar', $input->getOption('foo')); + $this->assertSame('bar', $input->getOption('foo')); } public static function getTokenizeData() @@ -77,12 +77,12 @@ public static function getTokenizeData() public function testToString() { $input = new StringInput('-f foo'); - $this->assertEquals('-f foo', (string) $input); + $this->assertSame('-f foo', (string) $input); $input = new StringInput('-f --bar=foo "a b c d"'); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d'), (string) $input); + $this->assertSame('-f --bar=foo '.escapeshellarg('a b c d'), (string) $input); $input = new StringInput('-f --bar=foo \'a b c d\' '."'A\nB\\'C'"); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); + $this->assertSame('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); } } From 23a1a633e4ee488f843cfac61de2f90f0d764c82 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Tue, 17 Sep 2024 08:40:29 +0200 Subject: [PATCH 24/31] [Console] Add ability to schedule alarm signals and a `console.alarm` event --- Application.php | 59 ++++++-- CHANGELOG.md | 1 + Event/ConsoleAlarmEvent.php | 47 ++++++ SignalRegistry/SignalRegistry.php | 8 ++ Tests/ApplicationTest.php | 215 +++++++++++++++++++++++++++- Tests/phpt/alarm/command_exit.phpt | 64 +++++++++ Tests/phpt/signal/command_exit.phpt | 2 +- 7 files changed, 382 insertions(+), 14 deletions(-) create mode 100644 Event/ConsoleAlarmEvent.php create mode 100644 Tests/phpt/alarm/command_exit.phpt diff --git a/Application.php b/Application.php index 868f666ae..6075a6ef5 100644 --- a/Application.php +++ b/Application.php @@ -22,6 +22,7 @@ use Symfony\Component\Console\Completion\CompletionInput; use Symfony\Component\Console\Completion\CompletionSuggestions; use Symfony\Component\Console\Completion\Suggestion; +use Symfony\Component\Console\Event\ConsoleAlarmEvent; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleErrorEvent; use Symfony\Component\Console\Event\ConsoleSignalEvent; @@ -88,6 +89,7 @@ class Application implements ResetInterface private bool $initialized = false; private ?SignalRegistry $signalRegistry = null; private array $signalsToDispatchEvent = []; + private ?int $alarmInterval = null; public function __construct( private string $name = 'UNKNOWN', @@ -97,7 +99,7 @@ public function __construct( $this->defaultCommand = 'list'; if (\defined('SIGINT') && SignalRegistry::isSupported()) { $this->signalRegistry = new SignalRegistry(); - $this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2]; + $this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2, \SIGALRM]; } } @@ -128,6 +130,22 @@ public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent): void $this->signalsToDispatchEvent = $signalsToDispatchEvent; } + /** + * Sets the interval to schedule a SIGALRM signal in seconds. + */ + public function setAlarmInterval(?int $seconds): void + { + $this->alarmInterval = $seconds; + $this->scheduleAlarm(); + } + + private function scheduleAlarm(): void + { + if (null !== $this->alarmInterval) { + $this->getSignalRegistry()->scheduleAlarm($this->alarmInterval); + } + } + /** * Runs the current application. * @@ -981,34 +999,47 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : []; if ($commandSignals || $this->dispatcher && $this->signalsToDispatchEvent) { - if (!$this->signalRegistry) { - throw new RuntimeException('Unable to subscribe to signal events. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); - } + $signalRegistry = $this->getSignalRegistry(); if (Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); foreach ([\SIGINT, \SIGQUIT, \SIGTERM] as $signal) { - $this->signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode)); + $signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode)); } } if ($this->dispatcher) { // We register application signals, so that we can dispatch the event foreach ($this->signalsToDispatchEvent as $signal) { - $event = new ConsoleSignalEvent($command, $input, $output, $signal); - - $this->signalRegistry->register($signal, function ($signal) use ($event, $command, $commandSignals) { - $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL); - $exitCode = $event->getExitCode(); + $signalEvent = new ConsoleSignalEvent($command, $input, $output, $signal); + $alarmEvent = \SIGALRM === $signal ? new ConsoleAlarmEvent($command, $input, $output) : null; + + $signalRegistry->register($signal, function ($signal) use ($signalEvent, $alarmEvent, $command, $commandSignals, $input, $output) { + $this->dispatcher->dispatch($signalEvent, ConsoleEvents::SIGNAL); + $exitCode = $signalEvent->getExitCode(); + + if (null !== $alarmEvent) { + if (false !== $exitCode) { + $alarmEvent->setExitCode($exitCode); + } else { + $alarmEvent->abortExit(); + } + $this->dispatcher->dispatch($alarmEvent); + $exitCode = $alarmEvent->getExitCode(); + } // If the command is signalable, we call the handleSignal() method if (\in_array($signal, $commandSignals, true)) { $exitCode = $command->handleSignal($signal, $exitCode); } + if (\SIGALRM === $signal) { + $this->scheduleAlarm(); + } + if (false !== $exitCode) { - $event = new ConsoleTerminateEvent($command, $event->getInput(), $event->getOutput(), $exitCode, $signal); + $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode, $signal); $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); exit($event->getExitCode()); @@ -1021,7 +1052,11 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } foreach ($commandSignals as $signal) { - $this->signalRegistry->register($signal, function (int $signal) use ($command): void { + $signalRegistry->register($signal, function (int $signal) use ($command): void { + if (\SIGALRM === $signal) { + $this->scheduleAlarm(); + } + if (false !== $exitCode = $command->handleSignal($signal)) { exit($exitCode); } diff --git a/CHANGELOG.md b/CHANGELOG.md index a7b3c0450..2c963568c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * [BC BREAK] Add silent verbosity (`--silent`/`SHELL_VERBOSITY=-2`) to suppress all output, including errors * Add `OutputInterface::isSilent()`, `Output::isSilent()`, `OutputStyle::isSilent()` methods * Add a configurable finished indicator to the progress indicator to show that the progress is finished + * Add ability to schedule alarm signals and a `ConsoleAlarmEvent` 7.1 --- diff --git a/Event/ConsoleAlarmEvent.php b/Event/ConsoleAlarmEvent.php new file mode 100644 index 000000000..876ab59b9 --- /dev/null +++ b/Event/ConsoleAlarmEvent.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +final class ConsoleAlarmEvent extends ConsoleEvent +{ + public function __construct( + Command $command, + InputInterface $input, + OutputInterface $output, + private int|false $exitCode = 0, + ) { + parent::__construct($command, $input, $output); + } + + public function setExitCode(int $exitCode): void + { + if ($exitCode < 0 || $exitCode > 255) { + throw new \InvalidArgumentException('Exit code must be between 0 and 255.'); + } + + $this->exitCode = $exitCode; + } + + public function abortExit(): void + { + $this->exitCode = false; + } + + public function getExitCode(): int|false + { + return $this->exitCode; + } +} diff --git a/SignalRegistry/SignalRegistry.php b/SignalRegistry/SignalRegistry.php index ef2e5f04e..8c2939eec 100644 --- a/SignalRegistry/SignalRegistry.php +++ b/SignalRegistry/SignalRegistry.php @@ -54,4 +54,12 @@ public function handle(int $signal): void $signalHandler($signal, $hasNext); } } + + /** + * @internal + */ + public function scheduleAlarm(int $seconds): void + { + pcntl_alarm($seconds); + } } diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index 0fa10d85a..a4ec0de7c 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\Console\Event\ConsoleAlarmEvent; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleErrorEvent; use Symfony\Component\Console\Event\ConsoleSignalEvent; @@ -70,6 +71,9 @@ protected function tearDown(): void unset($_SERVER['SHELL_VERBOSITY']); if (\function_exists('pcntl_signal')) { + // We cancel any pending alarms + pcntl_alarm(0); + // We reset all signals to their default value to avoid side effects pcntl_signal(\SIGINT, \SIG_DFL); pcntl_signal(\SIGTERM, \SIG_DFL); @@ -2230,6 +2234,167 @@ public function testSignalableRestoresStty() $this->assertSame($previousSttyMode, $sttyMode); } + /** + * @requires extension pcntl + */ + public function testAlarmSubscriberNotCalledByDefault() + { + $command = new BaseSignableCommand(false); + + $subscriber = new AlarmEventSubscriber(); + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber($subscriber); + + $application = $this->createSignalableApplication($command, $dispatcher); + + $this->assertSame(0, $application->run(new ArrayInput(['signal']))); + $this->assertFalse($subscriber->signaled); + } + + /** + * @requires extension pcntl + */ + public function testAlarmSubscriberNotCalledForOtherSignals() + { + $command = new SignableCommand(); + + $subscriber1 = new SignalEventSubscriber(); + $subscriber2 = new AlarmEventSubscriber(); + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber($subscriber1); + $dispatcher->addSubscriber($subscriber2); + + $application = $this->createSignalableApplication($command, $dispatcher); + + $this->assertSame(1, $application->run(new ArrayInput(['signal']))); + $this->assertTrue($subscriber1->signaled); + $this->assertFalse($subscriber2->signaled); + } + + /** + * @requires extension pcntl + */ + public function testAlarmSubscriber() + { + $command = new BaseSignableCommand(signal: \SIGALRM); + + $subscriber1 = new AlarmEventSubscriber(); + $subscriber2 = new AlarmEventSubscriber(); + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber($subscriber1); + $dispatcher->addSubscriber($subscriber2); + + $application = $this->createSignalableApplication($command, $dispatcher); + + $this->assertSame(1, $application->run(new ArrayInput(['signal']))); + $this->assertTrue($subscriber1->signaled); + $this->assertTrue($subscriber2->signaled); + } + + /** + * @requires extension pcntl + */ + public function testAlarmDispatchWithoutEventDispatcher() + { + $command = new AlarmableCommand(1); + $command->loop = 11000; + + $application = $this->createSignalableApplication($command, null); + + $this->assertSame(1, $application->run(new ArrayInput(['alarm']))); + $this->assertTrue($command->signaled); + } + + /** + * @requires extension pcntl + */ + public function testAlarmableCommandWithoutInterval() + { + $command = new AlarmableCommand(0); + $command->loop = 11000; + + $dispatcher = new EventDispatcher(); + + $application = new Application(); + $application->setAutoExit(false); + $application->setDispatcher($dispatcher); + $application->add($command); + + $this->assertSame(0, $application->run(new ArrayInput(['alarm']))); + $this->assertFalse($command->signaled); + } + + /** + * @requires extension pcntl + */ + public function testAlarmableCommandHandlerCalledAfterEventListener() + { + $command = new AlarmableCommand(1); + $command->loop = 11000; + + $subscriber = new AlarmEventSubscriber(); + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber($subscriber); + + $application = $this->createSignalableApplication($command, $dispatcher); + + $this->assertSame(1, $application->run(new ArrayInput(['alarm']))); + $this->assertSame([AlarmEventSubscriber::class, AlarmableCommand::class], $command->signalHandlers); + } + + /** + * @requires extension pcntl + * + * @testWith [false] + * [4] + */ + public function testAlarmSubscriberCalledAfterSignalSubscriberAndInheritsExitCode(int|false $exitCode) + { + $command = new BaseSignableCommand(signal: \SIGALRM); + + $subscriber1 = new class($exitCode) extends SignalEventSubscriber { + public function __construct(private int|false $exitCode) + { + } + + public function onSignal(ConsoleSignalEvent $event): void + { + parent::onSignal($event); + + if (false === $this->exitCode) { + $event->abortExit(); + } else { + $event->setExitCode($this->exitCode); + } + } + }; + $subscriber2 = new class($exitCode) extends AlarmEventSubscriber { + public function __construct(private int|false $exitCode) + { + } + + public function onAlarm(ConsoleAlarmEvent $event): void + { + TestCase::assertSame($this->exitCode, $event->getExitCode()); + + parent::onAlarm($event); + } + }; + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber($subscriber1); + $dispatcher->addSubscriber($subscriber2); + + $application = $this->createSignalableApplication($command, $dispatcher); + + $this->assertSame(1, $application->run(new ArrayInput(['signal']))); + $this->assertSame([SignalEventSubscriber::class, AlarmEventSubscriber::class], $command->signalHandlers); + } + private function createSignalableApplication(Command $command, ?EventDispatcherInterface $dispatcher): Application { $application = new Application(); @@ -2237,7 +2402,7 @@ private function createSignalableApplication(Command $command, ?EventDispatcherI if ($dispatcher) { $application->setDispatcher($dispatcher); } - $application->add(new LazyCommand('signal', [], '', false, fn () => $command, true)); + $application->add(new LazyCommand($command::getDefaultName(), [], '', false, fn () => $command, true)); return $application; } @@ -2427,3 +2592,51 @@ public static function getSubscribedEvents(): array return ['console.signal' => 'onSignal']; } } + +#[AsCommand(name: 'alarm')] +class AlarmableCommand extends BaseSignableCommand implements SignalableCommandInterface +{ + public function __construct(private int $alarmInterval) + { + parent::__construct(false); + } + + protected function initialize(InputInterface $input, OutputInterface $output): void + { + $this->getApplication()->setAlarmInterval($this->alarmInterval); + } + + public function getSubscribedSignals(): array + { + return [\SIGALRM]; + } + + public function handleSignal(int $signal, false|int $previousExitCode = 0): int|false + { + if (\SIGALRM === $signal) { + $this->signaled = true; + $this->signalHandlers[] = __CLASS__; + } + + return false; + } +} + +class AlarmEventSubscriber implements EventSubscriberInterface +{ + public bool $signaled = false; + + public function onAlarm(ConsoleAlarmEvent $event): void + { + $this->signaled = true; + $event->getCommand()->signaled = true; + $event->getCommand()->signalHandlers[] = __CLASS__; + + $event->abortExit(); + } + + public static function getSubscribedEvents(): array + { + return [ConsoleAlarmEvent::class => 'onAlarm']; + } +} diff --git a/Tests/phpt/alarm/command_exit.phpt b/Tests/phpt/alarm/command_exit.phpt new file mode 100644 index 000000000..18b3fa023 --- /dev/null +++ b/Tests/phpt/alarm/command_exit.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test command that exits +--SKIPIF-- + +--FILE-- +getApplication()->setAlarmInterval(1); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + sleep(5); + + $output->writeln('should not be displayed'); + + return 0; + } + + public function getSubscribedSignals(): array + { + return [\SIGALRM]; + } + + public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false + { + if (\SIGALRM === $signal) { + echo "Received alarm!"; + + return 0; + } + + return false; + } +} + +$app = new Application(); +$app->setDispatcher(new \Symfony\Component\EventDispatcher\EventDispatcher()); +$app->add(new MyCommand('foo')); + +$app + ->setDefaultCommand('foo', true) + ->run() +; +--EXPECT-- +Received alarm! diff --git a/Tests/phpt/signal/command_exit.phpt b/Tests/phpt/signal/command_exit.phpt index fde3793a8..b1a314d8a 100644 --- a/Tests/phpt/signal/command_exit.phpt +++ b/Tests/phpt/signal/command_exit.phpt @@ -1,5 +1,5 @@ --TEST-- -Test command that exist +Test command that exits --SKIPIF-- --FILE-- From de23257c024f6b7ca426ef7b5c0b6ea4efb14b13 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 6 Oct 2024 18:45:39 +0200 Subject: [PATCH 25/31] CS: clean some whitespaces/indentation --- Tests/Helper/TableTest.php | 322 ++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/Tests/Helper/TableTest.php b/Tests/Helper/TableTest.php index 4af12e34c..608d23c21 100644 --- a/Tests/Helper/TableTest.php +++ b/Tests/Helper/TableTest.php @@ -102,7 +102,7 @@ public static function renderProvider() ['ISBN', 'Title', 'Author'], $books, 'default', -<<<'TABLE' + <<<'TABLE' +---------------+--------------------------+------------------+ | ISBN | Title | Author | +---------------+--------------------------+------------------+ @@ -191,7 +191,7 @@ public static function renderProvider() ['80-902734-1-6', 'And Then There Were None', 'Agatha Christie'], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+--------------------------+------------------+ | ISBN | Title | | +---------------+--------------------------+------------------+ @@ -212,7 +212,7 @@ public static function renderProvider() ['80-902734-1-6', 'And Then There Were None', 'Agatha Christie'], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+--------------------------+------------------+ | 99921-58-10-7 | Divine Comedy | Dante Alighieri | | 9971-5-0210-0 | | | @@ -231,7 +231,7 @@ public static function renderProvider() ['960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+----------------------------+-----------------+ | ISBN | Title | Author | +---------------+----------------------------+-----------------+ @@ -251,7 +251,7 @@ public static function renderProvider() ['ISBN', 'Title'], [], 'default', -<<<'TABLE' + <<<'TABLE' +------+-------+ | ISBN | Title | +------+-------+ @@ -271,7 +271,7 @@ public static function renderProvider() ['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+----------------------+-----------------+ | ISBN | Title | Author | +---------------+----------------------+-----------------+ @@ -288,7 +288,7 @@ public static function renderProvider() ['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'], ], 'default', -<<<'TABLE' + <<<'TABLE' +----------------------------------+----------------------+-----------------+ | ISBN | Title | Author | +----------------------------------+----------------------+-----------------+ @@ -320,7 +320,7 @@ public static function renderProvider() ], ], 'default', -<<<'TABLE' + <<<'TABLE' +-------------------------------+-------------------------------+-----------------------------+ | ISBN | Title | Author | +-------------------------------+-------------------------------+-----------------------------+ @@ -347,7 +347,7 @@ public static function renderProvider() ], ], 'default', -<<<'TABLE' + <<<'TABLE' +-----+-----+-----+ | Foo | Bar | Baz | +-----+-----+-----+ @@ -366,7 +366,7 @@ public static function renderProvider() ], ], 'default', -<<<'TABLE' + <<<'TABLE' +-----+-----+------+ | Foo | Bar | Baz | +-----+-----+------+ @@ -392,7 +392,7 @@ public static function renderProvider() ['80-902734-1-7', 'Test'], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+---------------+-----------------+ | ISBN | Title | Author | +---------------+---------------+-----------------+ @@ -425,7 +425,7 @@ public static function renderProvider() ['J. R. R'], ], 'default', -<<<'TABLE' + <<<'TABLE' +------------------+---------+-----------------+ | ISBN | Title | Author | +------------------+---------+-----------------+ @@ -460,7 +460,7 @@ public static function renderProvider() ], ], 'default', -<<<'TABLE' + <<<'TABLE' +-----------------+-------+-----------------+ | ISBN | Title | Author | +-----------------+-------+-----------------+ @@ -497,7 +497,7 @@ public static function renderProvider() ['Charles Dickens'], ], 'default', -<<<'TABLE' + <<<'TABLE' +-----------------+-------+-----------------+ | ISBN | Title | Author | +-----------------+-------+-----------------+ @@ -524,7 +524,7 @@ public static function renderProvider() ['Charles Dickens'], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+-----------------+ | ISBN | Author | +---------------+-----------------+ @@ -542,7 +542,7 @@ public static function renderProvider() ], [], 'default', -<<<'TABLE' + <<<'TABLE' +------+-------+--------+ | Main title | +------+-------+--------+ @@ -560,9 +560,9 @@ public static function renderProvider() new TableCell('3', ['colspan' => 2]), new TableCell('4', ['colspan' => 2]), ], - ], + ], 'default', -<<<'TABLE' + <<<'TABLE' +---+--+--+---+--+---+--+---+--+ | 1 | 2 | 3 | 4 | +---+--+--+---+--+---+--+---+--+ @@ -595,7 +595,7 @@ public static function renderProvider() +-----------------+------------------+---------+ TABLE - , + , true, ], 'Row with formatted cells containing a newline' => [ @@ -607,7 +607,7 @@ public static function renderProvider() new TableSeparator(), [ 'foo', - new TableCell('Dont break'."\n".'here', ['rowspan' => 2]), + new TableCell('Dont break'."\n".'here', ['rowspan' => 2]), ], [ 'bar', @@ -624,77 +624,77 @@ public static function renderProvider() +-------+------------+ TABLE - , + , true, ], 'TabeCellStyle with align. Also with rowspan and colspan > 1' => [ - [ - new TableCell( - 'ISBN', - [ - 'style' => new TableCellStyle([ - 'align' => 'right', - ]), - ] - ), - 'Title', - new TableCell( - 'Author', - [ - 'style' => new TableCellStyle([ - 'align' => 'center', - ]), - ] - ), - ], - [ - [ - new TableCell( - '978', - [ - 'style' => new TableCellStyle([ - 'align' => 'center', - ]), - ] - ), - 'De Monarchia', - new TableCell( - "Dante Alighieri \nspans multiple rows rows Dante Alighieri \nspans multiple rows rows", - [ - 'rowspan' => 2, - 'style' => new TableCellStyle([ - 'align' => 'center', - ]), - ] - ), - ], - [ - '99921-58-10-7', - 'Divine Comedy', - ], - new TableSeparator(), - [ - new TableCell( - 'test', - [ - 'colspan' => 2, - 'style' => new TableCellStyle([ - 'align' => 'center', - ]), - ] - ), - new TableCell( - 'tttt', - [ - 'style' => new TableCellStyle([ - 'align' => 'right', - ]), - ] - ), - ], - ], - 'default', -<<<'TABLE' + [ + new TableCell( + 'ISBN', + [ + 'style' => new TableCellStyle([ + 'align' => 'right', + ]), + ] + ), + 'Title', + new TableCell( + 'Author', + [ + 'style' => new TableCellStyle([ + 'align' => 'center', + ]), + ] + ), + ], + [ + [ + new TableCell( + '978', + [ + 'style' => new TableCellStyle([ + 'align' => 'center', + ]), + ] + ), + 'De Monarchia', + new TableCell( + "Dante Alighieri \nspans multiple rows rows Dante Alighieri \nspans multiple rows rows", + [ + 'rowspan' => 2, + 'style' => new TableCellStyle([ + 'align' => 'center', + ]), + ] + ), + ], + [ + '99921-58-10-7', + 'Divine Comedy', + ], + new TableSeparator(), + [ + new TableCell( + 'test', + [ + 'colspan' => 2, + 'style' => new TableCellStyle([ + 'align' => 'center', + ]), + ] + ), + new TableCell( + 'tttt', + [ + 'style' => new TableCellStyle([ + 'align' => 'right', + ]), + ] + ), + ], + ], + 'default', + <<<'TABLE' +---------------+---------------+-------------------------------------------+ | ISBN | Title | Author | +---------------+---------------+-------------------------------------------+ @@ -706,66 +706,66 @@ public static function renderProvider() +---------------+---------------+-------------------------------------------+ TABLE - , - ], + , + ], 'TabeCellStyle with fg,bg. Also with rowspan and colspan > 1' => [ [], [ - [ - new TableCell( - '978', - [ - 'style' => new TableCellStyle([ - 'fg' => 'black', - 'bg' => 'green', - ]), - ] - ), - 'De Monarchia', - new TableCell( - "Dante Alighieri \nspans multiple rows rows Dante Alighieri \nspans multiple rows rows", - [ - 'rowspan' => 2, - 'style' => new TableCellStyle([ - 'fg' => 'red', - 'bg' => 'green', - 'align' => 'center', - ]), - ] - ), - ], - - [ - '99921-58-10-7', - 'Divine Comedy', - ], - new TableSeparator(), - [ - new TableCell( - 'test', - [ - 'colspan' => 2, - 'style' => new TableCellStyle([ - 'fg' => 'red', - 'bg' => 'green', - 'align' => 'center', - ]), - ] - ), - new TableCell( - 'tttt', - [ - 'style' => new TableCellStyle([ - 'fg' => 'red', - 'bg' => 'green', - 'align' => 'right', - ]), - ] - ), - ], + [ + new TableCell( + '978', + [ + 'style' => new TableCellStyle([ + 'fg' => 'black', + 'bg' => 'green', + ]), + ] + ), + 'De Monarchia', + new TableCell( + "Dante Alighieri \nspans multiple rows rows Dante Alighieri \nspans multiple rows rows", + [ + 'rowspan' => 2, + 'style' => new TableCellStyle([ + 'fg' => 'red', + 'bg' => 'green', + 'align' => 'center', + ]), + ] + ), + ], + + [ + '99921-58-10-7', + 'Divine Comedy', + ], + new TableSeparator(), + [ + new TableCell( + 'test', + [ + 'colspan' => 2, + 'style' => new TableCellStyle([ + 'fg' => 'red', + 'bg' => 'green', + 'align' => 'center', + ]), + ] + ), + new TableCell( + 'tttt', + [ + 'style' => new TableCellStyle([ + 'fg' => 'red', + 'bg' => 'green', + 'align' => 'right', + ]), + ] + ), + ], ], 'default', -<<<'TABLE' + <<<'TABLE' +---------------+---------------+-------------------------------------------+ | 978 | De Monarchia | Dante Alighieri | | 99921-58-10-7 | Divine Comedy | spans multiple rows rows Dante Alighieri | @@ -775,9 +775,9 @@ public static function renderProvider() +---------------+---------------+-------------------------------------------+ TABLE - , - true, - ], + , + true, + ], 'TabeCellStyle with cellFormat. Also with rowspan and colspan > 1' => [ [ new TableCell( @@ -820,7 +820,7 @@ public static function renderProvider() ], ], 'default', -<<<'TABLE' + <<<'TABLE' +----------------+---------------+---------------------+ | ISBN | Title | Author | +----------------+---------------+---------------------+ @@ -832,7 +832,7 @@ public static function renderProvider() TABLE , true, - ], + ], ]; } @@ -1288,7 +1288,7 @@ public static function renderSetTitle() TABLE , true, - ], + ], 'header contains multiple lines' => [ 'Multiline'."\n".'header'."\n".'here', 'footer', @@ -1558,18 +1558,18 @@ public function testWithColspanAndMaxWith() $table->setColumnMaxWidth(1, 15); $table->setColumnMaxWidth(2, 15); $table->setRows([ - [new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor', ['colspan' => 3])], - new TableSeparator(), - [new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor', ['colspan' => 3])], - new TableSeparator(), - [new TableCell('Lorem ipsum dolor sit amet, consectetur ', ['colspan' => 2]), 'hello world'], - new TableSeparator(), - ['hello world', new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit', ['colspan' => 2])], - new TableSeparator(), - ['hello ', new TableCell('world', ['colspan' => 1]), 'Lorem ipsum dolor sit amet, consectetur'], - new TableSeparator(), - ['Symfony ', new TableCell('Test', ['colspan' => 1]), 'Lorem ipsum dolor sit amet, consectetur'], - ]) + [new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor', ['colspan' => 3])], + new TableSeparator(), + [new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor', ['colspan' => 3])], + new TableSeparator(), + [new TableCell('Lorem ipsum dolor sit amet, consectetur ', ['colspan' => 2]), 'hello world'], + new TableSeparator(), + ['hello world', new TableCell('Lorem ipsum dolor sit amet, consectetur adipiscing elit', ['colspan' => 2])], + new TableSeparator(), + ['hello ', new TableCell('world', ['colspan' => 1]), 'Lorem ipsum dolor sit amet, consectetur'], + new TableSeparator(), + ['Symfony ', new TableCell('Test', ['colspan' => 1]), 'Lorem ipsum dolor sit amet, consectetur'], + ]) ; $table->render(); From a97129d215b0730fe86c59f1ceefc6ad2e93533d Mon Sep 17 00:00:00 2001 From: valtzu Date: Sun, 13 Oct 2024 15:18:50 +0300 Subject: [PATCH 26/31] Add `$seconds` to `keepalive` methods --- Application.php | 8 ++++++++ Tests/ApplicationTest.php | 1 + 2 files changed, 9 insertions(+) diff --git a/Application.php b/Application.php index 6075a6ef5..2ed1319cb 100644 --- a/Application.php +++ b/Application.php @@ -139,6 +139,14 @@ public function setAlarmInterval(?int $seconds): void $this->scheduleAlarm(); } + /** + * Gets the interval in seconds on which a SIGALRM signal is dispatched. + */ + public function getAlarmInterval(): ?int + { + return $this->alarmInterval; + } + private function scheduleAlarm(): void { if (null !== $this->alarmInterval) { diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index a4ec0de7c..469353505 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -2305,6 +2305,7 @@ public function testAlarmDispatchWithoutEventDispatcher() $application = $this->createSignalableApplication($command, null); $this->assertSame(1, $application->run(new ArrayInput(['alarm']))); + $this->assertSame(1, $application->getAlarmInterval()); $this->assertTrue($command->signaled); } From 8f6d3ecb5ae72d1f21af58fc7ec50a4d9e4273e4 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 14 Oct 2024 20:03:05 +0200 Subject: [PATCH 27/31] Reduce common control flows --- Completion/CompletionInput.php | 4 ++-- Tests/Logger/ConsoleLoggerTest.php | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Completion/CompletionInput.php b/Completion/CompletionInput.php index 50febf2de..9f9619e18 100644 --- a/Completion/CompletionInput.php +++ b/Completion/CompletionInput.php @@ -123,13 +123,13 @@ public function bind(InputDefinition $definition): void if ($this->currentIndex >= \count($this->tokens)) { if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) { $this->completionName = $argumentName; - $this->completionValue = ''; } else { // we've reached the end $this->completionType = self::TYPE_NONE; $this->completionName = null; - $this->completionValue = ''; } + + $this->completionValue = ''; } } diff --git a/Tests/Logger/ConsoleLoggerTest.php b/Tests/Logger/ConsoleLoggerTest.php index 43d779631..0464c8c5f 100644 --- a/Tests/Logger/ConsoleLoggerTest.php +++ b/Tests/Logger/ConsoleLoggerTest.php @@ -151,11 +151,7 @@ public function testContextReplacement() public function testObjectCastToString() { - if (method_exists($this, 'createPartialMock')) { - $dummy = $this->createPartialMock(DummyTest::class, ['__toString']); - } else { - $dummy = $this->createPartialMock(DummyTest::class, ['__toString']); - } + $dummy = $this->createPartialMock(DummyTest::class, ['__toString']); $dummy->method('__toString')->willReturn('DUMMY'); $this->getLogger()->warning($dummy); From de74db6d7c9f4ecabf7b4a1a20655e021b034001 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 18 Oct 2024 16:04:52 +0200 Subject: [PATCH 28/31] Remove always true/false occurrences --- DependencyInjection/AddConsoleCommandPass.php | 2 +- SingleCommandApplication.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/AddConsoleCommandPass.php b/DependencyInjection/AddConsoleCommandPass.php index 642247e3f..f1521602a 100644 --- a/DependencyInjection/AddConsoleCommandPass.php +++ b/DependencyInjection/AddConsoleCommandPass.php @@ -53,7 +53,7 @@ public function process(ContainerBuilder $container): void $aliases = str_replace('%', '%%', $class::getDefaultName() ?? ''); } - $aliases = explode('|', $aliases ?? ''); + $aliases = explode('|', $aliases); $commandName = array_shift($aliases); if ($isHidden = '' === $commandName) { diff --git a/SingleCommandApplication.php b/SingleCommandApplication.php index ff1c17247..2b54fb870 100644 --- a/SingleCommandApplication.php +++ b/SingleCommandApplication.php @@ -67,6 +67,6 @@ public function run(?InputInterface $input = null, ?OutputInterface $output = nu $this->running = false; } - return $ret ?? 1; + return $ret; } } From c32691c80952990ee151c054f62d09aceeece23b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 27 Oct 2024 07:46:44 +0100 Subject: [PATCH 29/31] Don't use `die()` in PHPT `--SKIPIF--` Unlocks a performance optimization in PHPUnit 11.x see https://staabm.github.io/2024/10/19/phpunit-codesprint-munich.html --- Tests/phpt/alarm/command_exit.phpt | 2 +- Tests/phpt/signal/command_exit.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/phpt/alarm/command_exit.phpt b/Tests/phpt/alarm/command_exit.phpt index 18b3fa023..d3015ad9d 100644 --- a/Tests/phpt/alarm/command_exit.phpt +++ b/Tests/phpt/alarm/command_exit.phpt @@ -1,7 +1,7 @@ --TEST-- Test command that exits --SKIPIF-- - + --FILE-- + --FILE-- Date: Sat, 7 Dec 2024 13:07:30 +0100 Subject: [PATCH 30/31] fix risky test that doesn't perform any assertions --- Tests/Helper/ProgressBarTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tests/Helper/ProgressBarTest.php b/Tests/Helper/ProgressBarTest.php index c32307720..a1db94583 100644 --- a/Tests/Helper/ProgressBarTest.php +++ b/Tests/Helper/ProgressBarTest.php @@ -112,8 +112,10 @@ public function testRegularTimeEstimation() public function testRegularTimeRemainingWithDifferentStartAtAndCustomDisplay() { + $this->expectNotToPerformAssertions(); + ProgressBar::setFormatDefinition('custom', ' %current%/%max% [%bar%] %percent:3s%% %remaining% %estimated%'); - $bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0); + $bar = new ProgressBar($this->getOutputStream(), 1_200, 0); $bar->setFormat('custom'); $bar->start(1_200, 600); } From fefcc18c0f5d0efe3ab3152f15857298868dc2c3 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 11 Dec 2024 04:49:26 +0100 Subject: [PATCH 31/31] [Console] Fix tests --- Tests/ApplicationTest.php | 1 + Tests/ConsoleEventsTest.php | 1 + Tests/SignalRegistry/SignalRegistryTest.php | 1 + 3 files changed, 3 insertions(+) diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index 469353505..4f6e6cb96 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -79,6 +79,7 @@ protected function tearDown(): void pcntl_signal(\SIGTERM, \SIG_DFL); pcntl_signal(\SIGUSR1, \SIG_DFL); pcntl_signal(\SIGUSR2, \SIG_DFL); + pcntl_signal(\SIGALRM, \SIG_DFL); } } diff --git a/Tests/ConsoleEventsTest.php b/Tests/ConsoleEventsTest.php index 9c04d2706..408f8c0d3 100644 --- a/Tests/ConsoleEventsTest.php +++ b/Tests/ConsoleEventsTest.php @@ -39,6 +39,7 @@ protected function tearDown(): void pcntl_signal(\SIGTERM, \SIG_DFL); pcntl_signal(\SIGUSR1, \SIG_DFL); pcntl_signal(\SIGUSR2, \SIG_DFL); + pcntl_signal(\SIGALRM, \SIG_DFL); } } diff --git a/Tests/SignalRegistry/SignalRegistryTest.php b/Tests/SignalRegistry/SignalRegistryTest.php index f997f7c1d..92d500f9e 100644 --- a/Tests/SignalRegistry/SignalRegistryTest.php +++ b/Tests/SignalRegistry/SignalRegistryTest.php @@ -27,6 +27,7 @@ protected function tearDown(): void pcntl_signal(\SIGTERM, \SIG_DFL); pcntl_signal(\SIGUSR1, \SIG_DFL); pcntl_signal(\SIGUSR2, \SIG_DFL); + pcntl_signal(\SIGALRM, \SIG_DFL); } public function testOneCallbackForASignalSignalIsHandled()