From 235179850a9136f1acc79645038f4ce3f9c886ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 15 Nov 2023 23:01:24 +0100 Subject: [PATCH 01/65] Fix ProgressBar::iterate on empty iterator Co-authored-by: Florian Reimair --- Helper/ProgressBar.php | 59 +++++++++++++++++++++++--------- Tests/Helper/ProgressBarTest.php | 16 ++++++++- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Helper/ProgressBar.php b/Helper/ProgressBar.php index 64389c4a2..a1f806d5f 100644 --- a/Helper/ProgressBar.php +++ b/Helper/ProgressBar.php @@ -195,7 +195,7 @@ public function getStartTime(): int public function getMaxSteps(): int { - return $this->max; + return $this->max ?? 0; } public function getProgress(): int @@ -215,7 +215,7 @@ public function getProgressPercent(): float public function getBarOffset(): float { - return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth); + return floor(null !== $this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth); } public function getEstimated(): float @@ -253,7 +253,7 @@ public function setBarCharacter(string $char): void public function getBarCharacter(): string { - return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar); + return $this->barChar ?? (null !== $this->max ? '=' : $this->emptyBarChar); } public function setEmptyBarCharacter(string $char): void @@ -315,7 +315,21 @@ public function maxSecondsBetweenRedraws(float $seconds): void */ public function iterate(iterable $iterable, int $max = null): iterable { - $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); + if (0 === $max) { + $max = null; + } + + $max ??= is_countable($iterable) ? \count($iterable) : null; + + if (0 === $max) { + $this->max = 0; + $this->stepWidth = 2; + $this->finish(); + + return; + } + + $this->start($max); foreach ($iterable as $key => $value) { yield $key => $value; @@ -373,11 +387,15 @@ public function setProgress(int $step): void $step = 0; } - $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); - $prevPeriod = (int) ($this->step / $redrawFreq); - $currPeriod = (int) ($step / $redrawFreq); + $redrawFreq = $this->redrawFreq ?? (($this->max ?? 10) / 10); + $prevPeriod = $redrawFreq ? (int) ($this->step / $redrawFreq) : 0; + $currPeriod = $redrawFreq ? (int) ($step / $redrawFreq) : 0; $this->step = $step; - $this->percent = $this->max ? (float) $this->step / $this->max : 0; + $this->percent = match ($this->max) { + null => 0, + 0 => 1, + default => (float) $this->step / $this->max, + }; $timeInterval = microtime(true) - $this->lastWriteTime; // Draw regardless of other limits @@ -398,11 +416,20 @@ public function setProgress(int $step): void } } - public function setMaxSteps(int $max): void + public function setMaxSteps(?int $max): void { + if (0 === $max) { + $max = null; + } + $this->format = null; - $this->max = max(0, $max); - $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4; + if (null === $max) { + $this->max = null; + $this->stepWidth = 4; + } else { + $this->max = max(0, $max); + $this->stepWidth = Helper::width((string) $this->max); + } } /** @@ -410,16 +437,16 @@ public function setMaxSteps(int $max): void */ public function finish(): void { - if (!$this->max) { + if (null === $this->max) { $this->max = $this->step; } - if ($this->step === $this->max && !$this->overwrite) { + if (($this->step === $this->max || null === $this->max) && !$this->overwrite) { // prevent double 100% output return; } - $this->setProgress($this->max); + $this->setProgress($this->max ?? $this->step); } /** @@ -542,14 +569,14 @@ private static function initPlaceholderFormatters(): array }, 'elapsed' => fn (self $bar) => Helper::formatTime(time() - $bar->getStartTime(), 2), 'remaining' => function (self $bar) { - if (!$bar->getMaxSteps()) { + if (null === $bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } return Helper::formatTime($bar->getRemaining(), 2); }, 'estimated' => function (self $bar) { - if (!$bar->getMaxSteps()) { + if (null === $bar->getMaxSteps()) { throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } diff --git a/Tests/Helper/ProgressBarTest.php b/Tests/Helper/ProgressBarTest.php index 4dff078ae..cc7ed6c88 100644 --- a/Tests/Helper/ProgressBarTest.php +++ b/Tests/Helper/ProgressBarTest.php @@ -1092,6 +1092,20 @@ public function testIterateUncountable() ); } + public function testEmptyInputWithDebugFormat() + { + $bar = new ProgressBar($output = $this->getOutputStream()); + $bar->setFormat('%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%'); + + $this->assertEquals([], iterator_to_array($bar->iterate([]))); + + rewind($output->getStream()); + $this->assertEquals( + ' 0/0 [============================] 100% < 1 sec/< 1 sec', + stream_get_contents($output->getStream()) + ); + } + protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL) { return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated); @@ -1263,7 +1277,7 @@ public function testMultiLineFormatIsFullyCorrectlyWithManuallyCleanup() 'Foo!'.\PHP_EOL. $this->generateOutput('[--->------------------------]'). "\nProcessing \"foobar\"...". - $this->generateOutput("[----->----------------------]\nProcessing \"foobar\"..."), + $this->generateOutput("[============================]\nProcessing \"foobar\"..."), stream_get_contents($output->getStream()) ); } From 531f11d95b6c89815c37d446ff63d630ab9c9977 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Mon, 20 Nov 2023 19:32:45 +0100 Subject: [PATCH 02/65] [CssSelector][Serializer][Translation] [Command] Clean unused code --- Command/Command.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Command/Command.php b/Command/Command.php index c49891777..ef1e7c31e 100644 --- a/Command/Command.php +++ b/Command/Command.php @@ -277,10 +277,6 @@ public function run(InputInterface $input, OutputInterface $output): int $statusCode = ($this->code)($input, $output); } else { $statusCode = $this->execute($input, $output); - - if (!\is_int($statusCode)) { - throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode))); - } } return is_numeric($statusCode) ? (int) $statusCode : 0; From 0b33220c25d174123c4582f23b3d35625ae881a0 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 14 Dec 2023 11:03:37 +0100 Subject: [PATCH 03/65] Set `strict` parameter of `in_array` to true where possible --- Application.php | 2 +- Descriptor/ReStructuredTextDescriptor.php | 2 +- Helper/TableCellStyle.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Application.php b/Application.php index 07cc6d674..4d1a6d953 100644 --- a/Application.php +++ b/Application.php @@ -716,7 +716,7 @@ public function find(string $name): Command $aliases[$nameOrAlias] = $commandName; - return $commandName === $nameOrAlias || !\in_array($commandName, $commands); + return $commandName === $nameOrAlias || !\in_array($commandName, $commands, true); })); } diff --git a/Descriptor/ReStructuredTextDescriptor.php b/Descriptor/ReStructuredTextDescriptor.php index d4423fd34..f12fecb67 100644 --- a/Descriptor/ReStructuredTextDescriptor.php +++ b/Descriptor/ReStructuredTextDescriptor.php @@ -226,7 +226,7 @@ private function getNonDefaultOptions(InputDefinition $definition): array $nonDefaultOptions = []; foreach ($definition->getOptions() as $option) { // Skip global options. - if (!\in_array($option->getName(), $globalOptions)) { + if (!\in_array($option->getName(), $globalOptions, true)) { $nonDefaultOptions[] = $option; } } diff --git a/Helper/TableCellStyle.php b/Helper/TableCellStyle.php index 9419dcb40..49b97f853 100644 --- a/Helper/TableCellStyle.php +++ b/Helper/TableCellStyle.php @@ -67,7 +67,7 @@ public function getTagOptions(): array { return array_filter( $this->getOptions(), - fn ($key) => \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]), + fn ($key) => \in_array($key, self::TAG_OPTIONS, true) && isset($this->options[$key]), \ARRAY_FILTER_USE_KEY ); } From e6bafc780aad05f332917caa3f7b7576a1e05ef2 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 18 Dec 2023 08:46:12 +0100 Subject: [PATCH 04/65] Code updates --- Helper/Table.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Helper/Table.php b/Helper/Table.php index fe2ac87c1..fd2e94d5d 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -717,7 +717,7 @@ private function fillNextRows(array $rows, int $line): array foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { // we need to know if $unmergedRow will be merged or inserted into $rows - if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { + if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRow) <= $this->numberOfColumns)) { foreach ($unmergedRow as $cellKey => $cell) { // insert cell into row at cellKey position array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); @@ -726,7 +726,7 @@ private function fillNextRows(array $rows, int $line): array $row = $this->copyRow($rows, $unmergedRowKey - 1); foreach ($unmergedRow as $column => $cell) { if (!empty($cell)) { - $row[$column] = $unmergedRow[$column]; + $row[$column] = $cell; } } array_splice($rows, $unmergedRowKey, 0, [$row]); From e0b2ccdd08585175012a8a9999d842153835df78 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 10 Oct 2023 16:04:32 +0200 Subject: [PATCH 05/65] [Console][EventDispatcher][Security][Serializer][Workflow] Add PHPDoc to attribute classes and properties --- Attribute/AsCommand.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Attribute/AsCommand.php b/Attribute/AsCommand.php index b337f548f..6066d7c53 100644 --- a/Attribute/AsCommand.php +++ b/Attribute/AsCommand.php @@ -17,6 +17,12 @@ #[\Attribute(\Attribute::TARGET_CLASS)] class AsCommand { + /** + * @param string $name The name of the command, used when calling it (i.e. "cache:clear") + * @param string|null $description The description of the command, displayed with the help page + * @param string[] $aliases The list of aliases of the command. The command will be executed when using one of them (i.e. "cache:clean") + * @param bool $hidden If true, the command won't be shown when listing all the available commands, but it can still be run as any other command + */ public function __construct( public string $name, public ?string $description = null, From f92fef1127ac0222ab92dd09122ad6b324610785 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Tue, 2 Jan 2024 15:49:33 +0100 Subject: [PATCH 06/65] CS: trailing commas --- Completion/Suggestion.php | 2 +- Helper/OutputWrapper.php | 2 +- Output/AnsiColorMode.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Completion/Suggestion.php b/Completion/Suggestion.php index 7392965a2..3251b079f 100644 --- a/Completion/Suggestion.php +++ b/Completion/Suggestion.php @@ -20,7 +20,7 @@ class Suggestion implements \Stringable { public function __construct( private readonly string $value, - private readonly string $description = '' + private readonly string $description = '', ) { } diff --git a/Helper/OutputWrapper.php b/Helper/OutputWrapper.php index 2ec819c74..0ea2b7056 100644 --- a/Helper/OutputWrapper.php +++ b/Helper/OutputWrapper.php @@ -49,7 +49,7 @@ final class OutputWrapper private const URL_PATTERN = 'https?://\S+'; public function __construct( - private bool $allowCutUrls = false + private bool $allowCutUrls = false, ) { } diff --git a/Output/AnsiColorMode.php b/Output/AnsiColorMode.php index 5f9f744fe..ca40ffb79 100644 --- a/Output/AnsiColorMode.php +++ b/Output/AnsiColorMode.php @@ -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), }; } @@ -72,7 +72,7 @@ private function convertFromRGB(int $r, int $g, int $b): int return match ($this) { self::Ansi4 => $this->degradeHexColorToAnsi4($r, $g, $b), self::Ansi8 => $this->degradeHexColorToAnsi8($r, $g, $b), - default => throw new InvalidArgumentException("RGB cannot be converted to {$this->name}.") + default => throw new InvalidArgumentException("RGB cannot be converted to {$this->name}."), }; } From 7739bb6aef4a98d2a28465de5a5e2a78f66caa7a Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Tue, 2 Jan 2024 14:14:18 +0100 Subject: [PATCH 07/65] [Asset][BrowserKit][Cache][Console][CssSelector] Use CPP --- Application.php | 10 ++++------ Command/LazyCommand.php | 12 ++++++++---- CommandLoader/ContainerCommandLoader.php | 11 ++++------- CommandLoader/FactoryCommandLoader.php | 8 +++----- Cursor.php | 8 ++++---- Descriptor/ApplicationDescription.php | 13 +++++-------- Event/ConsoleErrorEvent.php | 11 ++++++----- Event/ConsoleEvent.php | 15 +++++---------- Event/ConsoleSignalEvent.php | 14 +++++++------- EventListener/ErrorListener.php | 8 +++----- Exception/CommandNotFoundException.php | 12 ++++++------ Helper/Dumper.php | 14 +++++--------- Helper/ProgressIndicator.php | 12 ++++++------ Helper/Table.php | 8 +++----- Helper/TableCell.php | 9 ++++----- Helper/TableRows.php | 8 +++----- Input/ArrayInput.php | 10 ++++------ Input/InputArgument.php | 15 +++++++-------- Input/InputOption.php | 14 ++++++++------ Logger/ConsoleLogger.php | 9 +++++---- Messenger/RunCommandMessageHandler.php | 5 +++-- Question/ChoiceQuestion.php | 9 +++++---- Question/ConfirmationQuestion.php | 10 +++++----- Question/Question.php | 10 ++++------ Style/OutputStyle.php | 8 +++----- Style/SymfonyStyle.php | 11 +++++------ Tester/ApplicationTester.php | 8 +++----- Tester/CommandCompletionTester.php | 8 +++----- Tester/CommandTester.php | 8 +++----- 29 files changed, 134 insertions(+), 164 deletions(-) diff --git a/Application.php b/Application.php index 4d1a6d953..00acef1dd 100644 --- a/Application.php +++ b/Application.php @@ -75,8 +75,6 @@ class Application implements ResetInterface private array $commands = []; private bool $wantHelps = false; private ?Command $runningCommand = null; - private string $name; - private string $version; private ?CommandLoaderInterface $commandLoader = null; private bool $catchExceptions = true; private bool $catchErrors = false; @@ -91,10 +89,10 @@ class Application implements ResetInterface private ?SignalRegistry $signalRegistry = null; private array $signalsToDispatchEvent = []; - public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') - { - $this->name = $name; - $this->version = $version; + public function __construct( + private string $name = 'UNKNOWN', + private string $version = 'UNKNOWN', + ) { $this->terminal = new Terminal(); $this->defaultCommand = 'list'; if (\defined('SIGINT') && SignalRegistry::isSupported()) { diff --git a/Command/LazyCommand.php b/Command/LazyCommand.php index 7279724a6..df44b3d01 100644 --- a/Command/LazyCommand.php +++ b/Command/LazyCommand.php @@ -27,17 +27,21 @@ final class LazyCommand extends Command { private \Closure|Command $command; - private ?bool $isEnabled; - public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true) - { + public function __construct( + string $name, + array $aliases, + string $description, + bool $isHidden, + \Closure $commandFactory, + private ?bool $isEnabled = true, + ) { $this->setName($name) ->setAliases($aliases) ->setHidden($isHidden) ->setDescription($description); $this->command = $commandFactory; - $this->isEnabled = $isEnabled; } public function ignoreValidationErrors(): void diff --git a/CommandLoader/ContainerCommandLoader.php b/CommandLoader/ContainerCommandLoader.php index bfa0ac467..84e25be76 100644 --- a/CommandLoader/ContainerCommandLoader.php +++ b/CommandLoader/ContainerCommandLoader.php @@ -22,16 +22,13 @@ */ class ContainerCommandLoader implements CommandLoaderInterface { - private ContainerInterface $container; - private array $commandMap; - /** * @param array $commandMap An array with command names as keys and service ids as values */ - public function __construct(ContainerInterface $container, array $commandMap) - { - $this->container = $container; - $this->commandMap = $commandMap; + public function __construct( + private ContainerInterface $container, + private array $commandMap, + ) { } public function get(string $name): Command diff --git a/CommandLoader/FactoryCommandLoader.php b/CommandLoader/FactoryCommandLoader.php index 9ced75aeb..ae16bf6f1 100644 --- a/CommandLoader/FactoryCommandLoader.php +++ b/CommandLoader/FactoryCommandLoader.php @@ -21,14 +21,12 @@ */ class FactoryCommandLoader implements CommandLoaderInterface { - private array $factories; - /** * @param callable[] $factories Indexed by command names */ - public function __construct(array $factories) - { - $this->factories = $factories; + public function __construct( + private array $factories, + ) { } public function has(string $name): bool diff --git a/Cursor.php b/Cursor.php index 69fd3821c..965f996e0 100644 --- a/Cursor.php +++ b/Cursor.php @@ -18,16 +18,16 @@ */ final class Cursor { - private OutputInterface $output; /** @var resource */ private $input; /** * @param resource|null $input */ - public function __construct(OutputInterface $output, $input = null) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + $input = null, + ) { $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+')); } diff --git a/Descriptor/ApplicationDescription.php b/Descriptor/ApplicationDescription.php index f8ed18045..5149fde4c 100644 --- a/Descriptor/ApplicationDescription.php +++ b/Descriptor/ApplicationDescription.php @@ -24,9 +24,6 @@ class ApplicationDescription { public const GLOBAL_NAMESPACE = '_global'; - private Application $application; - private ?string $namespace; - private bool $showHidden; private array $namespaces; /** @@ -39,11 +36,11 @@ class ApplicationDescription */ private array $aliases = []; - public function __construct(Application $application, string $namespace = null, bool $showHidden = false) - { - $this->application = $application; - $this->namespace = $namespace; - $this->showHidden = $showHidden; + public function __construct( + private Application $application, + private ?string $namespace = null, + private bool $showHidden = false, + ) { } public function getNamespaces(): array diff --git a/Event/ConsoleErrorEvent.php b/Event/ConsoleErrorEvent.php index d4a691216..f469fbcee 100644 --- a/Event/ConsoleErrorEvent.php +++ b/Event/ConsoleErrorEvent.php @@ -22,14 +22,15 @@ */ final class ConsoleErrorEvent extends ConsoleEvent { - private \Throwable $error; private int $exitCode; - public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) - { + public function __construct( + InputInterface $input, + OutputInterface $output, + private \Throwable $error, + Command $command = null, + ) { parent::__construct($command, $input, $output); - - $this->error = $error; } public function getError(): \Throwable diff --git a/Event/ConsoleEvent.php b/Event/ConsoleEvent.php index 437a58e1e..2f9f0778e 100644 --- a/Event/ConsoleEvent.php +++ b/Event/ConsoleEvent.php @@ -23,16 +23,11 @@ */ class ConsoleEvent extends Event { - protected ?Command $command; - - private InputInterface $input; - private OutputInterface $output; - - public function __construct(?Command $command, InputInterface $input, OutputInterface $output) - { - $this->command = $command; - $this->input = $input; - $this->output = $output; + public function __construct( + protected ?Command $command, + private InputInterface $input, + private OutputInterface $output, + ) { } /** diff --git a/Event/ConsoleSignalEvent.php b/Event/ConsoleSignalEvent.php index 95af1f915..b27f08a18 100644 --- a/Event/ConsoleSignalEvent.php +++ b/Event/ConsoleSignalEvent.php @@ -20,14 +20,14 @@ */ final class ConsoleSignalEvent extends ConsoleEvent { - private int $handlingSignal; - private int|false $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal, int|false $exitCode = 0) - { + public function __construct( + Command $command, + InputInterface $input, + OutputInterface $output, + private int $handlingSignal, + private int|false $exitCode = 0, + ) { parent::__construct($command, $input, $output); - $this->handlingSignal = $handlingSignal; - $this->exitCode = $exitCode; } public function getHandlingSignal(): int diff --git a/EventListener/ErrorListener.php b/EventListener/ErrorListener.php index 5c38e8ef8..49915a498 100644 --- a/EventListener/ErrorListener.php +++ b/EventListener/ErrorListener.php @@ -24,11 +24,9 @@ */ class ErrorListener implements EventSubscriberInterface { - private ?LoggerInterface $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->logger = $logger; + public function __construct( + private ?LoggerInterface $logger = null, + ) { } public function onConsoleError(ConsoleErrorEvent $event): void diff --git a/Exception/CommandNotFoundException.php b/Exception/CommandNotFoundException.php index 1e9f1c793..47750d5f9 100644 --- a/Exception/CommandNotFoundException.php +++ b/Exception/CommandNotFoundException.php @@ -18,19 +18,19 @@ */ class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface { - private array $alternatives; - /** * @param string $message Exception message to throw * @param string[] $alternatives List of similar defined names * @param int $code Exception code * @param \Throwable|null $previous Previous exception used for the exception chaining */ - public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) - { + public function __construct( + string $message, + private array $alternatives = [], + int $code = 0, + \Throwable $previous = null, + ) { parent::__construct($message, $code, $previous); - - $this->alternatives = $alternatives; } /** diff --git a/Helper/Dumper.php b/Helper/Dumper.php index 8c6a94d51..0cd01e616 100644 --- a/Helper/Dumper.php +++ b/Helper/Dumper.php @@ -21,17 +21,13 @@ */ final class Dumper { - private OutputInterface $output; - private ?CliDumper $dumper; - private ?ClonerInterface $cloner; private \Closure $handler; - public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) - { - $this->output = $output; - $this->dumper = $dumper; - $this->cloner = $cloner; - + public function __construct( + private OutputInterface $output, + private ?CliDumper $dumper = null, + private ?ClonerInterface $cloner = null, + ) { if (class_exists(CliDumper::class)) { $this->handler = function ($var): string { $dumper = $this->dumper ??= new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); diff --git a/Helper/ProgressIndicator.php b/Helper/ProgressIndicator.php index 8865ecc34..8ebf99145 100644 --- a/Helper/ProgressIndicator.php +++ b/Helper/ProgressIndicator.php @@ -31,13 +31,11 @@ class ProgressIndicator 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', ]; - private OutputInterface $output; private int $startTime; private ?string $format = null; private ?string $message = null; private array $indicatorValues; private int $indicatorCurrent; - private int $indicatorChangeInterval; private float $indicatorUpdateTime; private bool $started = false; @@ -50,9 +48,12 @@ class ProgressIndicator * @param int $indicatorChangeInterval Change interval in milliseconds * @param array|null $indicatorValues Animated indicator characters */ - public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + string $format = null, + private int $indicatorChangeInterval = 100, + array $indicatorValues = null, + ) { $format ??= $this->determineBestFormat(); $indicatorValues ??= ['-', '\\', '|', '/']; @@ -63,7 +64,6 @@ public function __construct(OutputInterface $output, string $format = null, int } $this->format = self::getFormatDefinition($format); - $this->indicatorChangeInterval = $indicatorChangeInterval; $this->indicatorValues = $indicatorValues; $this->startTime = time(); } diff --git a/Helper/Table.php b/Helper/Table.php index fd2e94d5d..87cea7f77 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -45,7 +45,6 @@ class Table private array $rows = []; private array $effectiveColumnWidths = []; private int $numberOfColumns; - private OutputInterface $output; private TableStyle $style; private array $columnStyles = []; private array $columnWidths = []; @@ -55,10 +54,9 @@ class Table private static array $styles; - public function __construct(OutputInterface $output) - { - $this->output = $output; - + public function __construct( + private OutputInterface $output, + ) { self::$styles ??= self::initStyles(); $this->setStyle('default'); diff --git a/Helper/TableCell.php b/Helper/TableCell.php index 394b2bc95..1c4eeea20 100644 --- a/Helper/TableCell.php +++ b/Helper/TableCell.php @@ -18,17 +18,16 @@ */ class TableCell { - private string $value; private array $options = [ 'rowspan' => 1, 'colspan' => 1, 'style' => null, ]; - public function __construct(string $value = '', array $options = []) - { - $this->value = $value; - + public function __construct( + private string $value = '', + array $options = [], + ) { // 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))); diff --git a/Helper/TableRows.php b/Helper/TableRows.php index 97d07726e..fb2dc2789 100644 --- a/Helper/TableRows.php +++ b/Helper/TableRows.php @@ -16,11 +16,9 @@ */ class TableRows implements \IteratorAggregate { - private \Closure $generator; - - public function __construct(\Closure $generator) - { - $this->generator = $generator; + public function __construct( + private \Closure $generator, + ) { } public function getIterator(): \Traversable diff --git a/Input/ArrayInput.php b/Input/ArrayInput.php index 03b200b13..2697e3721 100644 --- a/Input/ArrayInput.php +++ b/Input/ArrayInput.php @@ -25,12 +25,10 @@ */ class ArrayInput extends Input { - private array $parameters; - - public function __construct(array $parameters, InputDefinition $definition = null) - { - $this->parameters = $parameters; - + public function __construct( + private array $parameters, + InputDefinition $definition = null, + ) { parent::__construct($definition); } diff --git a/Input/InputArgument.php b/Input/InputArgument.php index 642ae6600..9d6c17fa3 100644 --- a/Input/InputArgument.php +++ b/Input/InputArgument.php @@ -29,11 +29,8 @@ class InputArgument public const OPTIONAL = 2; public const IS_ARRAY = 4; - private string $name; private int $mode; private string|int|bool|array|null|float $default; - private array|\Closure $suggestedValues; - private string $description; /** * @param string $name The argument name @@ -44,18 +41,20 @@ class InputArgument * * @throws InvalidArgumentException When argument mode is not valid */ - public function __construct(string $name, int $mode = null, string $description = '', string|bool|int|float|array $default = null, \Closure|array $suggestedValues = []) - { + public function __construct( + private string $name, + int $mode = null, + private string $description = '', + string|bool|int|float|array $default = null, + private \Closure|array $suggestedValues = [], + ) { if (null === $mode) { $mode = self::OPTIONAL; } elseif ($mode > 7 || $mode < 1) { throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } - $this->name = $name; $this->mode = $mode; - $this->description = $description; - $this->suggestedValues = $suggestedValues; $this->setDefault($default); } diff --git a/Input/InputOption.php b/Input/InputOption.php index f8e9b0dd6..5d305518a 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -54,8 +54,6 @@ class InputOption private string|array|null $shortcut; private int $mode; private string|int|bool|array|null|float $default; - private array|\Closure $suggestedValues; - private string $description; /** * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts @@ -65,8 +63,14 @@ class InputOption * * @throws InvalidArgumentException If option mode is invalid or incompatible */ - public function __construct(string $name, string|array $shortcut = null, int $mode = null, string $description = '', string|bool|int|float|array $default = null, array|\Closure $suggestedValues = []) - { + public function __construct( + string $name, + string|array $shortcut = null, + int $mode = null, + private string $description = '', + string|bool|int|float|array $default = null, + private array|\Closure $suggestedValues = [], + ) { if (str_starts_with($name, '--')) { $name = substr($name, 2); } @@ -101,8 +105,6 @@ public function __construct(string $name, string|array $shortcut = null, int $mo $this->name = $name; $this->shortcut = $shortcut; $this->mode = $mode; - $this->description = $description; - $this->suggestedValues = $suggestedValues; if ($suggestedValues && !$this->acceptValue()) { throw new LogicException('Cannot set suggested values if the option does not accept a value.'); diff --git a/Logger/ConsoleLogger.php b/Logger/ConsoleLogger.php index fddef50cd..ad6e49ce1 100644 --- a/Logger/ConsoleLogger.php +++ b/Logger/ConsoleLogger.php @@ -29,7 +29,6 @@ class ConsoleLogger extends AbstractLogger public const INFO = 'info'; public const ERROR = 'error'; - private OutputInterface $output; private array $verbosityLevelMap = [ LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, @@ -52,9 +51,11 @@ class ConsoleLogger extends AbstractLogger ]; private bool $errored = false; - public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + array $verbosityLevelMap = [], + array $formatLevelMap = [], + ) { $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; } diff --git a/Messenger/RunCommandMessageHandler.php b/Messenger/RunCommandMessageHandler.php index 14f9c1764..1bc499494 100644 --- a/Messenger/RunCommandMessageHandler.php +++ b/Messenger/RunCommandMessageHandler.php @@ -22,8 +22,9 @@ */ final class RunCommandMessageHandler { - public function __construct(private readonly Application $application) - { + public function __construct( + private readonly Application $application, + ) { } public function __invoke(RunCommandMessage $message): RunCommandContext diff --git a/Question/ChoiceQuestion.php b/Question/ChoiceQuestion.php index e449ff683..0ccad051c 100644 --- a/Question/ChoiceQuestion.php +++ b/Question/ChoiceQuestion.php @@ -20,7 +20,6 @@ */ class ChoiceQuestion extends Question { - private array $choices; private bool $multiselect = false; private string $prompt = ' > '; private string $errorMessage = 'Value "%s" is invalid'; @@ -30,15 +29,17 @@ class ChoiceQuestion extends Question * @param array $choices The list of available choices * @param mixed $default The default answer to return */ - public function __construct(string $question, array $choices, mixed $default = null) - { + public function __construct( + string $question, + private array $choices, + mixed $default = null, + ) { if (!$choices) { throw new \LogicException('Choice question must have at least 1 choice available.'); } parent::__construct($question, $default); - $this->choices = $choices; $this->setValidator($this->getDefaultValidator()); $this->setAutocompleterValues($choices); } diff --git a/Question/ConfirmationQuestion.php b/Question/ConfirmationQuestion.php index 40eab2429..951d68140 100644 --- a/Question/ConfirmationQuestion.php +++ b/Question/ConfirmationQuestion.php @@ -18,18 +18,18 @@ */ class ConfirmationQuestion extends Question { - private string $trueAnswerRegex; - /** * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer */ - public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') - { + public function __construct( + string $question, + bool $default = true, + private string $trueAnswerRegex = '/^y/i', + ) { parent::__construct($question, $default); - $this->trueAnswerRegex = $trueAnswerRegex; $this->setNormalizer($this->getDefaultNormalizer()); } diff --git a/Question/Question.php b/Question/Question.php index c79683cd5..a82125c91 100644 --- a/Question/Question.php +++ b/Question/Question.php @@ -21,13 +21,11 @@ */ class Question { - private string $question; private ?int $attempts = null; private bool $hidden = false; private bool $hiddenFallback = true; private ?\Closure $autocompleterCallback = null; private ?\Closure $validator = null; - private string|int|bool|null|float $default; private ?\Closure $normalizer = null; private bool $trimmable = true; private bool $multiline = false; @@ -36,10 +34,10 @@ class Question * @param string $question The question to ask to the user * @param string|bool|int|float|null $default The default answer to return if the user enters nothing */ - public function __construct(string $question, string|bool|int|float $default = null) - { - $this->question = $question; - $this->default = $default; + public function __construct( + private string $question, + private null|string|bool|int|float $default = null, + ) { } /** diff --git a/Style/OutputStyle.php b/Style/OutputStyle.php index 05076c00f..9f62ea312 100644 --- a/Style/OutputStyle.php +++ b/Style/OutputStyle.php @@ -23,11 +23,9 @@ */ abstract class OutputStyle implements OutputInterface, StyleInterface { - private OutputInterface $output; - - public function __construct(OutputInterface $output) - { - $this->output = $output; + public function __construct( + private OutputInterface $output, + ) { } public function newLine(int $count = 1): void diff --git a/Style/SymfonyStyle.php b/Style/SymfonyStyle.php index 0da5d6981..3fd531d98 100644 --- a/Style/SymfonyStyle.php +++ b/Style/SymfonyStyle.php @@ -40,22 +40,21 @@ class SymfonyStyle extends OutputStyle { public const MAX_LINE_LENGTH = 120; - private InputInterface $input; - private OutputInterface $output; private SymfonyQuestionHelper $questionHelper; private ProgressBar $progressBar; private int $lineLength; private TrimmedBufferOutput $bufferedOutput; - public function __construct(InputInterface $input, OutputInterface $output) - { - $this->input = $input; + public function __construct( + private InputInterface $input, + private OutputInterface $output, + ) { $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter()); // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); - parent::__construct($this->output = $output); + parent::__construct($output); } /** diff --git a/Tester/ApplicationTester.php b/Tester/ApplicationTester.php index 58aee54d6..cebb6f8eb 100644 --- a/Tester/ApplicationTester.php +++ b/Tester/ApplicationTester.php @@ -28,11 +28,9 @@ class ApplicationTester { use TesterTrait; - private Application $application; - - public function __construct(Application $application) - { - $this->application = $application; + public function __construct( + private Application $application, + ) { } /** diff --git a/Tester/CommandCompletionTester.php b/Tester/CommandCompletionTester.php index a90fe52ef..76cbaf14f 100644 --- a/Tester/CommandCompletionTester.php +++ b/Tester/CommandCompletionTester.php @@ -22,11 +22,9 @@ */ class CommandCompletionTester { - private Command $command; - - public function __construct(Command $command) - { - $this->command = $command; + public function __construct( + private Command $command, + ) { } /** diff --git a/Tester/CommandTester.php b/Tester/CommandTester.php index 2ff813b7d..d39cde7f6 100644 --- a/Tester/CommandTester.php +++ b/Tester/CommandTester.php @@ -24,11 +24,9 @@ class CommandTester { use TesterTrait; - private Command $command; - - public function __construct(Command $command) - { - $this->command = $command; + public function __construct( + private Command $command, + ) { } /** From e930278484a07b8c4779d9c021b7280bfa07bfee Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Mon, 15 Jan 2024 20:49:54 +0100 Subject: [PATCH 08/65] CS: enable ordered_types.null_adjustment=always_last --- Input/InputArgument.php | 2 +- Input/InputOption.php | 2 +- Question/Question.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Input/InputArgument.php b/Input/InputArgument.php index 9d6c17fa3..521048a06 100644 --- a/Input/InputArgument.php +++ b/Input/InputArgument.php @@ -30,7 +30,7 @@ class InputArgument public const IS_ARRAY = 4; private int $mode; - private string|int|bool|array|null|float $default; + private string|int|bool|array|float|null $default; /** * @param string $name The argument name diff --git a/Input/InputOption.php b/Input/InputOption.php index 5d305518a..870f18f73 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -53,7 +53,7 @@ class InputOption private string $name; private string|array|null $shortcut; private int $mode; - private string|int|bool|array|null|float $default; + private string|int|bool|array|float|null $default; /** * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts diff --git a/Question/Question.php b/Question/Question.php index a82125c91..46a60c798 100644 --- a/Question/Question.php +++ b/Question/Question.php @@ -36,7 +36,7 @@ class Question */ public function __construct( private string $question, - private null|string|bool|int|float $default = null, + private string|bool|int|float|null $default = null, ) { } From 7cc16b1ffc962425545f6497c469de518bf86c49 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Jan 2024 09:28:05 +0100 Subject: [PATCH 09/65] [Console] Remove needless state from QuestionHelper --- Helper/QuestionHelper.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Helper/QuestionHelper.php b/Helper/QuestionHelper.php index cb75ac914..0967156ca 100644 --- a/Helper/QuestionHelper.php +++ b/Helper/QuestionHelper.php @@ -34,11 +34,6 @@ */ class QuestionHelper extends Helper { - /** - * @var resource|null - */ - private $inputStream; - private static bool $stty = true; private static bool $stdinIsInteractive; @@ -59,16 +54,15 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu return $this->getDefaultAnswer($question); } - if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { - $this->inputStream = $stream; - } + $inputStream = $input instanceof StreamableInputInterface ? $input->getStream() : null; + $inputStream ??= STDIN; try { if (!$question->getValidator()) { - return $this->doAsk($output, $question); + return $this->doAsk($inputStream, $output, $question); } - $interviewer = fn () => $this->doAsk($output, $question); + $interviewer = fn () => $this->doAsk($inputStream, $output, $question); return $this->validateAttempts($interviewer, $output, $question); } catch (MissingInputException $exception) { @@ -98,13 +92,14 @@ public static function disableStty(): void /** * Asks the question to the user. * + * @param resource $inputStream + * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ - private function doAsk(OutputInterface $output, Question $question): mixed + private function doAsk($inputStream, OutputInterface $output, Question $question): mixed { $this->writePrompt($output, $question); - $inputStream = $this->inputStream ?: \STDIN; $autocomplete = $question->getAutocompleterCallback(); if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { From f96f8d16b0a98719f3337e7f3e734d7971f7cb17 Mon Sep 17 00:00:00 2001 From: Jesper Noordsij Date: Fri, 13 Oct 2023 21:34:54 +0200 Subject: [PATCH 10/65] [Console] `InputArgument` and `InputOption` code cleanup --- Command/Command.php | 12 ++++++------ Input/InputArgument.php | 23 +++++++++++++++++------ Input/InputOption.php | 19 +++++++++++++++---- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Command/Command.php b/Command/Command.php index a9e52db94..03da6db43 100644 --- a/Command/Command.php +++ b/Command/Command.php @@ -283,7 +283,7 @@ public function run(InputInterface $input, OutputInterface $output): int } /** - * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + * Supplies suggestions when resolving possible completion options for input (e.g. option or argument). */ public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { @@ -401,8 +401,8 @@ public function getNativeDefinition(): InputDefinition /** * Adds an argument. * - * @param $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param $default The default value (for InputArgument::OPTIONAL mode only) + * @param $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param $default The default value (for InputArgument::OPTIONAL mode only) * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion * * @return $this @@ -420,9 +420,9 @@ public function addArgument(string $name, ?int $mode = null, string $description /** * Adds an option. * - * @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param $mode The option mode: One of the InputOption::VALUE_* constants - * @param $default The default value (must be null for InputOption::VALUE_NONE) + * @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param $mode The option mode: One of the InputOption::VALUE_* constants + * @param $default The default value (must be null for InputOption::VALUE_NONE) * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion * * @return $this diff --git a/Input/InputArgument.php b/Input/InputArgument.php index c33c6a057..a049bebe5 100644 --- a/Input/InputArgument.php +++ b/Input/InputArgument.php @@ -25,16 +25,26 @@ */ class InputArgument { + /** + * Providing an argument is required (e.g. just 'app:foo' is not allowed). + */ public const REQUIRED = 1; + + /** + * Providing an argument is optional (e.g. 'app:foo' and 'app:foo bar' are both allowed). This is the default behavior of arguments. + */ public const OPTIONAL = 2; + + /** + * The argument accepts multiple values and turn them into an array (e.g. 'app:foo bar baz' will result in value ['bar', 'baz']). + */ public const IS_ARRAY = 4; private int $mode; - private string|int|bool|array|float|null $default; /** * @param string $name The argument name - * @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY + * @param int-mask-of|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY * @param string $description A description text * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only) * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion @@ -50,7 +60,7 @@ public function __construct( ) { if (null === $mode) { $mode = self::OPTIONAL; - } elseif ($mode > 7 || $mode < 1) { + } elseif ($mode >= (self::IS_ARRAY << 1) || $mode < 1) { throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } @@ -89,8 +99,6 @@ public function isArray(): bool /** * Sets the default value. - * - * @throws LogicException When incorrect default value is given */ public function setDefault(string|bool|int|float|array|null $default): void { @@ -117,13 +125,16 @@ public function getDefault(): string|bool|int|float|array|null return $this->default; } + /** + * Returns true if the argument has values for input completion. + */ public function hasCompletion(): bool { return [] !== $this->suggestedValues; } /** - * Adds suggestions to $suggestions for the current completion input. + * Supplies suggestions when command resolves possible completion options for input. * * @see Command::complete() */ diff --git a/Input/InputOption.php b/Input/InputOption.php index d2ebb7827..50851c44c 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -46,18 +46,18 @@ class InputOption public const VALUE_IS_ARRAY = 8; /** - * The option may have either positive or negative value (e.g. --ansi or --no-ansi). + * The option allows passing a negated variant (e.g. --ansi or --no-ansi). */ public const VALUE_NEGATABLE = 16; private string $name; - private string|array|null $shortcut; + private ?string $shortcut; private int $mode; private string|int|bool|array|float|null $default; /** * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the VALUE_* constants + * @param int-mask-of|null $mode The option mode: One of the VALUE_* constants * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion * @@ -175,11 +175,19 @@ public function isArray(): bool return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } + /** + * Returns true if the option allows passing a negated variant. + * + * @return bool true if mode is self::VALUE_NEGATABLE, false otherwise + */ public function isNegatable(): bool { return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); } + /** + * Sets the default value. + */ public function setDefault(string|bool|int|float|array|null $default): void { if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { @@ -213,13 +221,16 @@ public function getDescription(): string return $this->description; } + /** + * Returns true if the option has values for input completion. + */ public function hasCompletion(): bool { return [] !== $this->suggestedValues; } /** - * Adds suggestions to $suggestions for the current completion input. + * Supplies suggestions when command resolves possible completion options for input. * * @see Command::complete() */ From 82efc31d66f28eebfc21d23736fdadf4cb258f74 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 3 Feb 2024 17:11:47 +0100 Subject: [PATCH 11/65] re-add accidentally removed property --- Input/InputArgument.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Input/InputArgument.php b/Input/InputArgument.php index a049bebe5..a5d949277 100644 --- a/Input/InputArgument.php +++ b/Input/InputArgument.php @@ -41,6 +41,7 @@ class InputArgument public const IS_ARRAY = 4; private int $mode; + private string|int|bool|array|float|null $default; /** * @param string $name The argument name From 63dbbae04e9d89a47183421422380330aebfd7d5 Mon Sep 17 00:00:00 2001 From: Adriaan Zonnenberg Date: Sat, 17 Feb 2024 14:49:48 +0100 Subject: [PATCH 12/65] [Console] Add descriptions to Fish completion output --- Completion/Output/FishCompletionOutput.php | 9 ++++++--- Resources/completion.fish | 6 +----- Tests/Completion/Output/FishCompletionOutputTest.php | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Completion/Output/FishCompletionOutput.php b/Completion/Output/FishCompletionOutput.php index d2c414e48..356a974ea 100644 --- a/Completion/Output/FishCompletionOutput.php +++ b/Completion/Output/FishCompletionOutput.php @@ -21,11 +21,14 @@ class FishCompletionOutput implements CompletionOutputInterface { public function write(CompletionSuggestions $suggestions, OutputInterface $output): void { - $values = $suggestions->getValueSuggestions(); + $values = []; + foreach ($suggestions->getValueSuggestions() as $value) { + $values[] = $value->getValue().($value->getDescription() ? "\t".$value->getDescription() : ''); + } foreach ($suggestions->getOptionSuggestions() as $option) { - $values[] = '--'.$option->getName(); + $values[] = '--'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : ''); if ($option->isNegatable()) { - $values[] = '--no-'.$option->getName(); + $values[] = '--no-'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : ''); } } $output->write(implode("\n", $values)); diff --git a/Resources/completion.fish b/Resources/completion.fish index 1c34292ae..1853dd80f 100644 --- a/Resources/completion.fish +++ b/Resources/completion.fish @@ -19,11 +19,7 @@ function _sf_{{ COMMAND_NAME }} set completecmd $completecmd "-c$c" - set sfcomplete ($completecmd) - - for i in $sfcomplete - echo $i - end + $completecmd end complete -c '{{ COMMAND_NAME }}' -a '(_sf_{{ COMMAND_NAME }})' -f diff --git a/Tests/Completion/Output/FishCompletionOutputTest.php b/Tests/Completion/Output/FishCompletionOutputTest.php index 2e615d040..93456e138 100644 --- a/Tests/Completion/Output/FishCompletionOutputTest.php +++ b/Tests/Completion/Output/FishCompletionOutputTest.php @@ -23,11 +23,11 @@ public function getCompletionOutput(): CompletionOutputInterface public function getExpectedOptionsOutput(): string { - return "--option1\n--negatable\n--no-negatable"; + return "--option1\tFirst Option\n--negatable\tCan be negative\n--no-negatable\tCan be negative"; } public function getExpectedValuesOutput(): string { - return "Green\nRed\nYellow"; + return "Green\tBeans are green\nRed\tRose are red\nYellow\tCanaries are yellow"; } } From 31c74a59d8bffdcec73adb43b398f6942f7dc26b Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 4 Mar 2024 13:46:40 +0100 Subject: [PATCH 13/65] [Console] Document argv arrays for static analysis --- Input/ArgvInput.php | 3 +++ Input/StringInput.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index 8621d62cf..6c95abc65 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -40,9 +40,11 @@ */ class ArgvInput extends Input { + /** @var list */ private array $tokens; private array $parsed; + /** @param list|null $argv */ public function __construct(?array $argv = null, ?InputDefinition $definition = null) { $argv ??= $_SERVER['argv'] ?? []; @@ -55,6 +57,7 @@ public function __construct(?array $argv = null, ?InputDefinition $definition = parent::__construct($definition); } + /** @param list $tokens */ protected function setTokens(array $tokens): void { $this->tokens = $tokens; diff --git a/Input/StringInput.php b/Input/StringInput.php index 33f0f4b39..835700143 100644 --- a/Input/StringInput.php +++ b/Input/StringInput.php @@ -40,6 +40,8 @@ public function __construct(string $input) /** * Tokenizes a string. * + * @return list + * * @throws InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize(string $input): array From b66e3b8ac723816be3f9b9ba1e00cd8e19de417f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 11 Mar 2024 15:21:04 +0100 Subject: [PATCH 14/65] [Console] Add `ArgvInput::getRawTokens()` --- CHANGELOG.md | 5 +++++ Input/ArgvInput.php | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ff71d2fa..25d7f7179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.1 +--- + + * Add `ArgvInput::getRawTokens()` + 7.0 --- diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index 6c95abc65..001bef093 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -345,6 +345,16 @@ public function getParameterOption(string|array $values, string|bool|int|float|a return $default; } + /** + * Returns un-parsed and not validated tokens. + * + * @return list + */ + public function getRawTokens(): array + { + return $this->tokens; + } + /** * Returns a stringified representation of the args passed to the command. */ From 117ef1f1c1898fec311571b4be90cb4046e344f1 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 2 Mar 2024 11:42:07 +0100 Subject: [PATCH 15/65] [Console] Add a way to use custom lock factory in lockableTrait --- Command/LockableTrait.php | 16 ++++++++----- Tests/Command/LockableTraitTest.php | 16 +++++++++++++ Tests/Fixtures/FooLock3Command.php | 35 +++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 Tests/Fixtures/FooLock3Command.php diff --git a/Command/LockableTrait.php b/Command/LockableTrait.php index cd7548f02..f0001cc52 100644 --- a/Command/LockableTrait.php +++ b/Command/LockableTrait.php @@ -26,6 +26,8 @@ trait LockableTrait { private ?LockInterface $lock = null; + private ?LockFactory $lockFactory = null; + /** * Locks a command. */ @@ -39,13 +41,17 @@ private function lock(?string $name = null, bool $blocking = false): bool throw new LogicException('A lock is already in place.'); } - if (SemaphoreStore::isSupported()) { - $store = new SemaphoreStore(); - } else { - $store = new FlockStore(); + if (null === $this->lockFactory) { + if (SemaphoreStore::isSupported()) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lockFactory = (new LockFactory($store)); } - $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); + $this->lock = $this->lockFactory->createLock($name ?: $this->getName()); if (!$this->lock->acquire($blocking)) { $this->lock = null; diff --git a/Tests/Command/LockableTraitTest.php b/Tests/Command/LockableTraitTest.php index 77b54f9ee..0268d9681 100644 --- a/Tests/Command/LockableTraitTest.php +++ b/Tests/Command/LockableTraitTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\SharedLockInterface; use Symfony\Component\Lock\Store\FlockStore; use Symfony\Component\Lock\Store\SemaphoreStore; @@ -26,6 +27,7 @@ public static function setUpBeforeClass(): void self::$fixturesPath = __DIR__.'/../Fixtures/'; require_once self::$fixturesPath.'/FooLockCommand.php'; require_once self::$fixturesPath.'/FooLock2Command.php'; + require_once self::$fixturesPath.'/FooLock3Command.php'; } public function testLockIsReleased() @@ -64,4 +66,18 @@ public function testMultipleLockCallsThrowLogicException() $tester = new CommandTester($command); $this->assertSame(1, $tester->execute([])); } + + public function testCustomLockFactoryIsUsed() + { + $lockFactory = $this->createMock(LockFactory::class); + $command = new \FooLock3Command($lockFactory); + + $tester = new CommandTester($command); + + $lock = $this->createMock(SharedLockInterface::class); + $lock->method('acquire')->willReturn(false); + + $lockFactory->expects(static::once())->method('createLock')->willReturn($lock); + $this->assertSame(1, $tester->execute([])); + } } diff --git a/Tests/Fixtures/FooLock3Command.php b/Tests/Fixtures/FooLock3Command.php new file mode 100644 index 000000000..78492de69 --- /dev/null +++ b/Tests/Fixtures/FooLock3Command.php @@ -0,0 +1,35 @@ +lockFactory = $lockFactory; + } + + protected function configure(): void + { + $this->setName('foo:lock3'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + if (!$this->lock()) { + return 1; + } + + $this->release(); + + return 2; + } +} From 07520ebce9e125cb845805626bced597d585faa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 20 Mar 2024 11:51:16 +0100 Subject: [PATCH 16/65] [Console] Allow to returns all tokens after the command name --- Input/ArgvInput.php | 23 +++++++++++++++++++++-- Tests/Input/ArgvInputTest.php | 27 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php index 001bef093..95703ba5f 100644 --- a/Input/ArgvInput.php +++ b/Input/ArgvInput.php @@ -348,11 +348,30 @@ public function getParameterOption(string|array $values, string|bool|int|float|a /** * Returns un-parsed and not validated tokens. * + * @param bool $strip Whether to return the raw parameters (false) or the values after the command name (true) + * * @return list */ - public function getRawTokens(): array + public function getRawTokens(bool $strip = false): array { - return $this->tokens; + if (!$strip) { + return $this->tokens; + } + + $parameters = []; + $keep = false; + foreach ($this->tokens as $value) { + if (!$keep && $value === $this->getFirstArgument()) { + $keep = true; + + continue; + } + if ($keep) { + $parameters[] = $value; + } + } + + return $parameters; } /** diff --git a/Tests/Input/ArgvInputTest.php b/Tests/Input/ArgvInputTest.php index a47d557b7..80ea06d67 100644 --- a/Tests/Input/ArgvInputTest.php +++ b/Tests/Input/ArgvInputTest.php @@ -562,4 +562,31 @@ public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument() $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'); } + + public function testGetRawTokensFalse() + { + $input = new ArgvInput(['cli.php', '--foo', 'bar']); + $this->assertSame(['--foo', 'bar'], $input->getRawTokens()); + } + + /** + * @dataProvider provideGetRawTokensTrueTests + */ + public function testGetRawTokensTrue(array $argv, array $expected) + { + $input = new ArgvInput($argv); + $this->assertSame($expected, $input->getRawTokens(true)); + } + + public static function provideGetRawTokensTrueTests(): iterable + { + yield [['app/console', 'foo:bar'], []]; + yield [['app/console', 'foo:bar', '--env=prod'], ['--env=prod']]; + yield [['app/console', 'foo:bar', '--env', 'prod'], ['--env', 'prod']]; + yield [['app/console', '--no-ansi', 'foo:bar', '--env', 'prod'], ['--env', 'prod']]; + yield [['app/console', '--no-ansi', 'foo:bar', '--env', 'prod'], ['--env', 'prod']]; + yield [['app/console', '--no-ansi', 'foo:bar', 'argument'], ['argument']]; + yield [['app/console', '--no-ansi', 'foo:bar', 'foo:bar'], ['foo:bar']]; + yield [['app/console', '--no-ansi', 'foo:bar', '--', 'argument'], ['--', 'argument']]; + } } From e5b4db4db27704fc0e153eacbe001feddeab0480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ostroluck=C3=BD?= Date: Sun, 31 Mar 2024 15:15:18 +0200 Subject: [PATCH 17/65] Remove unnecessary empty usages --- Application.php | 6 +++--- Descriptor/XmlDescriptor.php | 2 +- Helper/Table.php | 2 +- Input/InputOption.php | 2 +- Output/ConsoleSectionOutput.php | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Application.php b/Application.php index 9c301471c..3f7ef0419 100644 --- a/Application.php +++ b/Application.php @@ -620,7 +620,7 @@ public function findNamespace(string $namespace): string $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*'; $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); - if (empty($namespaces)) { + if (!$namespaces) { $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { @@ -674,12 +674,12 @@ public function find(string $name): Command $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*'; $commands = preg_grep('{^'.$expr.'}', $allCommands); - if (empty($commands)) { + if (!$commands) { $commands = preg_grep('{^'.$expr.'}i', $allCommands); } // if no commands matched or we just matched namespaces - if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { + if (!$commands || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); diff --git a/Descriptor/XmlDescriptor.php b/Descriptor/XmlDescriptor.php index 866c71856..8e44c88c4 100644 --- a/Descriptor/XmlDescriptor.php +++ b/Descriptor/XmlDescriptor.php @@ -208,7 +208,7 @@ 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 (!empty($defaults)) { + if ($defaults) { foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); diff --git a/Helper/Table.php b/Helper/Table.php index c1b7dba59..afdb67c49 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -726,7 +726,7 @@ private function fillNextRows(array $rows, int $line): array } else { $row = $this->copyRow($rows, $unmergedRowKey - 1); foreach ($unmergedRow as $column => $cell) { - if (!empty($cell)) { + if ($cell) { $row[$column] = $cell; } } diff --git a/Input/InputOption.php b/Input/InputOption.php index 50851c44c..617c348d5 100644 --- a/Input/InputOption.php +++ b/Input/InputOption.php @@ -75,7 +75,7 @@ public function __construct( $name = substr($name, 2); } - if (empty($name)) { + if (!$name) { throw new InvalidArgumentException('An option name cannot be empty.'); } diff --git a/Output/ConsoleSectionOutput.php b/Output/ConsoleSectionOutput.php index ded97c70e..09aa7fe99 100644 --- a/Output/ConsoleSectionOutput.php +++ b/Output/ConsoleSectionOutput.php @@ -63,7 +63,7 @@ public function setMaxHeight(int $maxHeight): void */ public function clear(?int $lines = null): void { - if (empty($this->content) || !$this->isDecorated()) { + if (!$this->content || !$this->isDecorated()) { return; } From 1b84910b638ce3265e132d7b42405b2db64f6f69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ostroluck=C3=BD?= Date: Sat, 6 Apr 2024 19:21:51 +0200 Subject: [PATCH 18/65] [Console] Handle SIGQUIT signal As both PHP-FPM and NGINX use SIGQUIT for graceful shutdown, I believe it's necessary PHP applications should also support it. It's especially important in cases where you run PHP application in container running php/nginx image, since they override shutdown signal that docker uses to SIGQUIT, see https://github.com/nginxinc/docker-nginx/commit/3fb70ddd7094c1fdd50cc83d432643dc10ab6243 --- Application.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Application.php b/Application.php index 3f7ef0419..87eb7a6c2 100644 --- a/Application.php +++ b/Application.php @@ -97,7 +97,7 @@ public function __construct( $this->defaultCommand = 'list'; if (\defined('SIGINT') && SignalRegistry::isSupported()) { $this->signalRegistry = new SignalRegistry(); - $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2]; + $this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2]; } } @@ -984,7 +984,7 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI if (Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); - foreach ([\SIGINT, \SIGTERM] as $signal) { + foreach ([\SIGINT, \SIGQUIT, \SIGTERM] as $signal) { $this->signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode)); } } From 965f054b640b28a4cfaa77cc69b53506393e3a4a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 2 May 2024 13:32:55 +0200 Subject: [PATCH 19/65] Cleanup past sponsors --- README.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ded2bc116..92f70e714 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,7 @@ interfaces. Sponsor ------- -The Console component for Symfony 7.0 is [backed][1] by [Les-Tilleuls.coop][2]. - -Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and -fix your projects. They provide a wide range of professional services including development, -consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps. -They are a worker cooperative! - -Help Symfony by [sponsoring][3] its development! +Help Symfony by [sponsoring][1] its development! Resources --------- @@ -31,6 +24,4 @@ Credits `Resources/bin/hiddeninput.exe` is a third party binary provided within this component. Find sources and license at https://github.com/Seldaek/hidden-input. -[1]: https://symfony.com/backers -[2]: https://les-tilleuls.coop -[3]: https://symfony.com/sponsor +[1]: https://symfony.com/sponsor From a1b3df8a0a0f883244a843ee806dd9cabc5441d7 Mon Sep 17 00:00:00 2001 From: Kev Date: Fri, 12 Apr 2024 10:46:21 +0200 Subject: [PATCH 20/65] [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 21/65] 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 22/65] 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 23/65] 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 24/65] 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 25/65] [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 26/65] 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 27/65] 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 28/65] [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 d48400b51d1bd1de2513afc097b2b6f3deaa88ab Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 31 Jul 2024 16:13:26 +0200 Subject: [PATCH 29/65] 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 30/65] 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 74d6d3972b9fb746ecbe50f7bd9864b10c4c201d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 9 Aug 2024 16:39:52 +0200 Subject: [PATCH 31/65] fix permitted data type of the default choice --- Question/ChoiceQuestion.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Question/ChoiceQuestion.php b/Question/ChoiceQuestion.php index e449ff683..465f3184f 100644 --- a/Question/ChoiceQuestion.php +++ b/Question/ChoiceQuestion.php @@ -26,11 +26,11 @@ class ChoiceQuestion extends Question private string $errorMessage = 'Value "%s" is invalid'; /** - * @param string $question The question to ask to the user - * @param array $choices The list of available choices - * @param mixed $default The default answer to return + * @param string $question The question to ask to the user + * @param array $choices The list of available choices + * @param string|bool|int|float|null $default The default answer to return */ - public function __construct(string $question, array $choices, mixed $default = null) + public function __construct(string $question, array $choices, string|bool|int|float|null $default = null) { if (!$choices) { throw new \LogicException('Choice question must have at least 1 choice available.'); From f96ee2a1098d49efe0df54f47474a6398c04869c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 13 Aug 2024 15:55:12 +0200 Subject: [PATCH 32/65] [PhpUnitBridge][Console][VarDumper] Fix handling NO_COLOR env var --- Output/StreamOutput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Output/StreamOutput.php b/Output/StreamOutput.php index 72479f8a2..b53955269 100644 --- a/Output/StreamOutput.php +++ b/Output/StreamOutput.php @@ -91,7 +91,7 @@ protected function doWrite(string $message, bool $newline) protected function hasColorSupport() { // Follow https://no-color.org/ - if ('' !== ($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR') ?: '')) { + if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) { return false; } From 7884dc76c55a618ca70cf3a5919277b053f703bb Mon Sep 17 00:00:00 2001 From: Artfaith Date: Fri, 19 Jul 2024 15:07:04 +0200 Subject: [PATCH 33/65] [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 c24bcd08af1fde7c0026d0201a5ae7627db6ad81 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 28 Jul 2024 09:27:30 +0200 Subject: [PATCH 34/65] [Console] Fix side-effects from running bash completions --- Resources/completion.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/completion.bash b/Resources/completion.bash index 64b87ccf7..bb44037b0 100644 --- a/Resources/completion.bash +++ b/Resources/completion.bash @@ -7,7 +7,7 @@ _sf_{{ COMMAND_NAME }}() { # Use newline as only separator to allow space in completion values - IFS=$'\n' + local IFS=$'\n' local sf_cmd="${COMP_WORDS[0]}" # for an alias, get the real script behind it From ee7ee22b1dabcff731b7d79d3633c96251ad8404 Mon Sep 17 00:00:00 2001 From: Will Rowe Date: Fri, 23 Aug 2024 11:21:30 -0400 Subject: [PATCH 35/65] [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 36/65] 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 7a7ce2c8b4246fdfc8bd42dff781298edeb54dd2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 5 Sep 2024 18:13:22 +0200 Subject: [PATCH 37/65] Don't use is_resource() on non-streams --- Terminal.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Terminal.php b/Terminal.php index b91e8afc5..948ced4ad 100644 --- a/Terminal.php +++ b/Terminal.php @@ -158,8 +158,7 @@ private static function readFromProcess(string $command): ?string $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; - $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); - if (!\is_resource($process)) { + if (!$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) { return null; } From 5b5a0aa66e3296e303e22490f90f521551835a83 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 20 Sep 2024 09:50:07 +0200 Subject: [PATCH 38/65] Mutate remaining data providers to static ones --- Tests/Formatter/OutputFormatterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Formatter/OutputFormatterTest.php b/Tests/Formatter/OutputFormatterTest.php index 21905f475..f65e0a15d 100644 --- a/Tests/Formatter/OutputFormatterTest.php +++ b/Tests/Formatter/OutputFormatterTest.php @@ -200,7 +200,7 @@ public static function provideInlineStyleOptionsCases() ]; } - public function provideInlineStyleTagsWithUnknownOptions() + public static function provideInlineStyleTagsWithUnknownOptions() { return [ ['', 'abc'], From 97f0e2dde8f3566d251d507d32656d32fa004018 Mon Sep 17 00:00:00 2001 From: fritzmg Date: Fri, 20 Sep 2024 11:40:42 +0100 Subject: [PATCH 39/65] suppress proc_open errors --- Terminal.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.php b/Terminal.php index 948ced4ad..ee178327a 100644 --- a/Terminal.php +++ b/Terminal.php @@ -158,7 +158,7 @@ private static function readFromProcess(string $command): ?string $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; - if (!$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) { + if (!$process = @proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) { return null; } From e57e6e0355bf231a6befd5d8ff2940308f0005eb Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 19 Sep 2024 14:29:18 +0200 Subject: [PATCH 40/65] [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 41/65] 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 42/65] 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 807379c78145021515afa38e03c2d12f8e7979db Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 24 Sep 2024 11:46:17 +0200 Subject: [PATCH 43/65] Tweak error/exception handler registration --- Application.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Application.php b/Application.php index bb5341882..fbb3b0eb0 100644 --- a/Application.php +++ b/Application.php @@ -165,9 +165,9 @@ public function run(?InputInterface $input = null, ?OutputInterface $output = nu } } - $this->configureIO($input, $output); - try { + $this->configureIO($input, $output); + $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { if (!$this->catchExceptions) { From 31ed6535ed20330440c05eda3962b6b0118a88e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Mon, 23 Sep 2024 11:24:18 +0200 Subject: [PATCH 44/65] Add PR template and auto-close PR on subtree split repositories --- .gitattributes | 3 +-- .github/PULL_REQUEST_TEMPLATE.md | 8 ++++++++ .github/workflows/close-pull-request.yml | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/close-pull-request.yml 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 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..4689c4dad --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +Please do not submit any Pull Requests here. They will be closed. +--- + +Please submit your PR here instead: +https://github.com/symfony/symfony + +This repository is what we call a "subtree split": a read-only subset of that main repository. +We're looking forward to your PR there! diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml new file mode 100644 index 000000000..e55b47817 --- /dev/null +++ b/.github/workflows/close-pull-request.yml @@ -0,0 +1,20 @@ +name: Close Pull Request + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: | + Thanks for your Pull Request! We love contributions. + + However, you should instead open your PR on the main repository: + https://github.com/symfony/symfony + + This repository is what we call a "subtree split": a read-only subset of that main repository. + We're looking forward to your PR there! From dbccd36c99ceffc024f8ef557187b6f62b2058d2 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Thu, 26 Sep 2024 10:09:09 +0200 Subject: [PATCH 45/65] 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 46/65] 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 47/65] 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 48/65] 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 49/65] [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 50/65] [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 51/65] 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 108d436c2af470858bdaba3257baab3a74172017 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Oct 2024 09:23:06 +0200 Subject: [PATCH 52/65] minor #58472 CS: clean some whitespaces/indentation (keradus) This PR was squashed before being merged into the 7.2 branch. Discussion ---------- CS: clean some whitespaces/indentation | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | no | Deprecations? | no | Issues | Fix CS | License | MIT Commits ------- d0f63b8afa1 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 e7822a456..b41c65a2c 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, - ], + ], ]; } @@ -1289,7 +1289,7 @@ public static function renderSetTitle() TABLE , true, - ], + ], 'header contains multiple lines' => [ 'Multiline'."\n".'header'."\n".'here', 'footer', @@ -1559,18 +1559,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 53/65] 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 54/65] 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 55/65] 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 56/65] 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: Tue, 5 Nov 2024 10:27:50 +0100 Subject: [PATCH 57/65] fix detecting anonymous exception classes on Windows and PHP 7 --- Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application.php b/Application.php index fbb3b0eb0..1a7e50388 100644 --- a/Application.php +++ b/Application.php @@ -858,7 +858,7 @@ protected function doRenderThrowable(\Throwable $e, OutputInterface $output): vo } if (str_contains($message, "@anonymous\0")) { - $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } From c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 5 Nov 2024 15:13:27 +0100 Subject: [PATCH 58/65] skip autocomplete test when stty is not available --- Tests/Helper/QuestionHelperTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/Helper/QuestionHelperTest.php b/Tests/Helper/QuestionHelperTest.php index 74315d898..06c89183e 100644 --- a/Tests/Helper/QuestionHelperTest.php +++ b/Tests/Helper/QuestionHelperTest.php @@ -914,6 +914,10 @@ public function testTraversableMultiselectAutocomplete() public function testAutocompleteMoveCursorBackwards() { + if (!Terminal::hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + // F $inputStream = $this->getInputStream("F\t\177\177\177"); From 67191f7f1d85ea8fa7598787e1e26b722acdb5e9 Mon Sep 17 00:00:00 2001 From: Sven Nolting Date: Mon, 2 Dec 2024 14:51:36 +0100 Subject: [PATCH 59/65] [Console] Fix division by 0 error --- Helper/ProgressBar.php | 2 +- Tests/Helper/ProgressBarTest.php | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Helper/ProgressBar.php b/Helper/ProgressBar.php index b406292b4..23157e3c7 100644 --- a/Helper/ProgressBar.php +++ b/Helper/ProgressBar.php @@ -229,7 +229,7 @@ public function getEstimated(): float public function getRemaining(): float { - if (!$this->step) { + if (0 === $this->step || $this->step === $this->startingStep) { return 0; } diff --git a/Tests/Helper/ProgressBarTest.php b/Tests/Helper/ProgressBarTest.php index a5a0eca24..c32307720 100644 --- a/Tests/Helper/ProgressBarTest.php +++ b/Tests/Helper/ProgressBarTest.php @@ -110,6 +110,14 @@ public function testRegularTimeEstimation() ); } + public function testRegularTimeRemainingWithDifferentStartAtAndCustomDisplay() + { + ProgressBar::setFormatDefinition('custom', ' %current%/%max% [%bar%] %percent:3s%% %remaining% %estimated%'); + $bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0); + $bar->setFormat('custom'); + $bar->start(1_200, 600); + } + public function testResumedTimeEstimation() { $bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0); From 799445db3f15768ecc382ac5699e6da0520a0a04 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 7 Dec 2024 13:07:30 +0100 Subject: [PATCH 60/65] 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 61/65] [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() From 2e4af9c952617cc3f9559ff706aee420a8464c36 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Thu, 27 Feb 2025 11:59:51 +0100 Subject: [PATCH 62/65] fix(console): fix progress bar messing output in section when there is an EOL --- Helper/ProgressBar.php | 9 ++++ Tests/Helper/ProgressBarTest.php | 75 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/Helper/ProgressBar.php b/Helper/ProgressBar.php index 23157e3c7..3dc06d7b4 100644 --- a/Helper/ProgressBar.php +++ b/Helper/ProgressBar.php @@ -486,12 +486,21 @@ private function overwrite(string $message): void if ($this->output instanceof ConsoleSectionOutput) { $messageLines = explode("\n", $this->previousMessage); $lineCount = \count($messageLines); + + $lastLineWithoutDecoration = Helper::removeDecoration($this->output->getFormatter(), end($messageLines) ?? ''); + + // When the last previous line is empty (without formatting) it is already cleared by the section output, so we don't need to clear it again + if ('' === $lastLineWithoutDecoration) { + --$lineCount; + } + foreach ($messageLines as $messageLine) { $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine)); if ($messageLineLength > $this->terminal->getWidth()) { $lineCount += floor($messageLineLength / $this->terminal->getWidth()); } } + $this->output->clear($lineCount); } else { $lineCount = substr_count($this->previousMessage, "\n"); diff --git a/Tests/Helper/ProgressBarTest.php b/Tests/Helper/ProgressBarTest.php index a1db94583..615237f1f 100644 --- a/Tests/Helper/ProgressBarTest.php +++ b/Tests/Helper/ProgressBarTest.php @@ -416,6 +416,81 @@ public function testOverwriteWithSectionOutput() ); } + public function testOverwriteWithSectionOutputAndEol() + { + $sections = []; + $stream = $this->getOutputStream(true); + $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); + + $bar = new ProgressBar($output, 50, 0); + $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%' . PHP_EOL); + $bar->setMessage(''); + $bar->start(); + $bar->display(); + $bar->setMessage('Doing something...'); + $bar->advance(); + $bar->setMessage('Doing something foo...'); + $bar->advance(); + + rewind($output->getStream()); + $this->assertEquals(escapeshellcmd( + '[>---------------------------] 0%'.\PHP_EOL.\PHP_EOL. + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL. 'Doing something...' . \PHP_EOL . + "\x1b[2A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. 'Doing something foo...' . \PHP_EOL), + escapeshellcmd(stream_get_contents($output->getStream())) + ); + } + + public function testOverwriteWithSectionOutputAndEolWithEmptyMessage() + { + $sections = []; + $stream = $this->getOutputStream(true); + $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); + + $bar = new ProgressBar($output, 50, 0); + $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%'); + $bar->setMessage('Start'); + $bar->start(); + $bar->display(); + $bar->setMessage(''); + $bar->advance(); + $bar->setMessage('Doing something...'); + $bar->advance(); + + rewind($output->getStream()); + $this->assertEquals(escapeshellcmd( + '[>---------------------------] 0%'.\PHP_EOL.'Start'.\PHP_EOL. + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL . + "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. 'Doing something...' . \PHP_EOL), + escapeshellcmd(stream_get_contents($output->getStream())) + ); + } + + public function testOverwriteWithSectionOutputAndEolWithEmptyMessageComment() + { + $sections = []; + $stream = $this->getOutputStream(true); + $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); + + $bar = new ProgressBar($output, 50, 0); + $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%'); + $bar->setMessage('Start'); + $bar->start(); + $bar->display(); + $bar->setMessage(''); + $bar->advance(); + $bar->setMessage('Doing something...'); + $bar->advance(); + + rewind($output->getStream()); + $this->assertEquals(escapeshellcmd( + '[>---------------------------] 0%'.\PHP_EOL."\x1b[33mStart\x1b[39m".\PHP_EOL. + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL . + "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. "\x1b[33mDoing something...\x1b[39m" . \PHP_EOL), + escapeshellcmd(stream_get_contents($output->getStream())) + ); + } + public function testOverwriteWithAnsiSectionOutput() { // output has 43 visible characters plus 2 invisible ANSI characters From a3011c7b7adb58d89f6c0d822abb641d7a5f9719 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Mon, 7 Apr 2025 16:42:41 +0100 Subject: [PATCH 63/65] Correctly convert SIGSYS to its name --- SignalRegistry/SignalMap.php | 2 +- Tests/SignalRegistry/SignalMapTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SignalRegistry/SignalMap.php b/SignalRegistry/SignalMap.php index de419bda7..2f9aa67c1 100644 --- a/SignalRegistry/SignalMap.php +++ b/SignalRegistry/SignalMap.php @@ -27,7 +27,7 @@ public static function getSignalName(int $signal): ?string if (!isset(self::$map)) { $r = new \ReflectionExtension('pcntl'); $c = $r->getConstants(); - $map = array_filter($c, fn ($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_'), \ARRAY_FILTER_USE_KEY); + $map = array_filter($c, fn ($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_') && 'SIGBABY' !== $k, \ARRAY_FILTER_USE_KEY); self::$map = array_flip($map); } diff --git a/Tests/SignalRegistry/SignalMapTest.php b/Tests/SignalRegistry/SignalMapTest.php index 887c5d7af..f4e320477 100644 --- a/Tests/SignalRegistry/SignalMapTest.php +++ b/Tests/SignalRegistry/SignalMapTest.php @@ -22,6 +22,7 @@ class SignalMapTest extends TestCase * @testWith [2, "SIGINT"] * [9, "SIGKILL"] * [15, "SIGTERM"] + * [31, "SIGSYS"] */ public function testSignalExists(int $signal, string $expected) { From d40c92e16775427254c5e7e5562ee2db9627592e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 6 May 2025 11:08:27 +0200 Subject: [PATCH 64/65] don't hardcode OS-depending constant values The values of the SIG* constants depend on the OS. --- Tests/SignalRegistry/SignalMapTest.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Tests/SignalRegistry/SignalMapTest.php b/Tests/SignalRegistry/SignalMapTest.php index f4e320477..73619049d 100644 --- a/Tests/SignalRegistry/SignalMapTest.php +++ b/Tests/SignalRegistry/SignalMapTest.php @@ -18,17 +18,21 @@ class SignalMapTest extends TestCase { /** * @requires extension pcntl - * - * @testWith [2, "SIGINT"] - * [9, "SIGKILL"] - * [15, "SIGTERM"] - * [31, "SIGSYS"] + * @dataProvider provideSignals */ public function testSignalExists(int $signal, string $expected) { $this->assertSame($expected, SignalMap::getSignalName($signal)); } + public function provideSignals() + { + yield [\SIGINT, 'SIGINT']; + yield [\SIGKILL, 'SIGKILL']; + yield [\SIGTERM, 'SIGTERM']; + yield [\SIGSYS, 'SIGSYS']; + } + public function testSignalDoesNotExist() { $this->assertNull(SignalMap::getSignalName(999999)); From 7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 7 May 2025 09:05:04 +0200 Subject: [PATCH 65/65] properly skip signal test if the pcntl extension is not installed --- Tests/SignalRegistry/SignalMapTest.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Tests/SignalRegistry/SignalMapTest.php b/Tests/SignalRegistry/SignalMapTest.php index 73619049d..3a0c49bb0 100644 --- a/Tests/SignalRegistry/SignalMapTest.php +++ b/Tests/SignalRegistry/SignalMapTest.php @@ -18,19 +18,13 @@ class SignalMapTest extends TestCase { /** * @requires extension pcntl - * @dataProvider provideSignals */ - public function testSignalExists(int $signal, string $expected) + public function testSignalExists() { - $this->assertSame($expected, SignalMap::getSignalName($signal)); - } - - public function provideSignals() - { - yield [\SIGINT, 'SIGINT']; - yield [\SIGKILL, 'SIGKILL']; - yield [\SIGTERM, 'SIGTERM']; - yield [\SIGSYS, 'SIGSYS']; + $this->assertSame('SIGINT', SignalMap::getSignalName(\SIGINT)); + $this->assertSame('SIGKILL', SignalMap::getSignalName(\SIGKILL)); + $this->assertSame('SIGTERM', SignalMap::getSignalName(\SIGTERM)); + $this->assertSame('SIGSYS', SignalMap::getSignalName(\SIGSYS)); } public function testSignalDoesNotExist()