[Console] Command::execute() should always return int - deprecate returning null

- added deprecation message for non-int return value in Command::execute()
- fixed all core commands to return proper int values
- added proper return type-hint to Command::execute() method in all core Commands
This commit is contained in:
Jan Schädlich 2019-09-30 20:52:02 +02:00 committed by Nicolas Grekas
parent 3354bacc02
commit 98c4f6a06c
50 changed files with 128 additions and 54 deletions

View File

@ -10,6 +10,7 @@ Console
-------
* Deprecated finding hidden commands using an abbreviation, use the full name instead
* Deprecated returning `null` from `Command::execute()`, return `0` instead
Debug
-----

View File

@ -37,6 +37,7 @@ Console
* Removed the `getHorizontalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* Removed the `setVerticalBorderChar()` method in favor of the `setVerticalBorderChars()` method in `TableStyle`.
* Removed the `getVerticalBorderChar()` method in favor of the `getBorderChars()` method in `TableStyle`.
* Removed support for returning `null` from `Command::execute()`, return `0` instead
* The `ProcessHelper::run()` method takes the command as an array of arguments.
Before:

View File

@ -111,12 +111,16 @@ EOF
switch ($input->getOption('format')) {
case 'text':
return $name ? $this->displayPathsText($io, $name) : $this->displayGeneralText($io, $filter);
$name ? $this->displayPathsText($io, $name) : $this->displayGeneralText($io, $filter);
break;
case 'json':
return $name ? $this->displayPathsJson($io, $name) : $this->displayGeneralJson($io, $filter);
$name ? $this->displayPathsJson($io, $name) : $this->displayGeneralJson($io, $filter);
break;
default:
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
}
return 0;
}
private function displayPathsText(SymfonyStyle $io, string $name)

View File

@ -54,7 +54,7 @@ EOT
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
@ -100,6 +100,8 @@ EOT
}
$io->table([], $rows);
return 0;
}
private static function formatPath(string $path, string $baseDir): string

View File

@ -72,7 +72,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$fs = $this->filesystem;
$io = new SymfonyStyle($input, $output);
@ -175,6 +175,8 @@ EOF
}
$io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
return 0;
}
private function warmup(string $warmupDir, string $realCacheDir, bool $enableOptionalWarmers = true)

View File

@ -60,7 +60,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$kernel = $this->getApplication()->getKernel();
@ -99,5 +99,7 @@ EOF
}
$io->success('Cache was successfully cleared.');
return 0;
}
}

View File

@ -59,7 +59,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$pool = $input->getArgument('pool');
@ -69,7 +69,7 @@ EOF
if (!$cachePool->hasItem($key)) {
$io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool));
return;
return 0;
}
if (!$cachePool->deleteItem($key)) {
@ -77,5 +77,7 @@ EOF
}
$io->success(sprintf('Cache item "%s" was successfully deleted.', $key));
return 0;
}
}

View File

@ -51,12 +51,14 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->table(['Pool name'], array_map(function ($pool) {
return [$pool];
}, $this->poolNames));
return 0;
}
}

View File

@ -57,7 +57,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
@ -67,5 +67,7 @@ EOF
}
$io->success('Successfully pruned cache pool(s).');
return 0;
}
}

View File

@ -66,7 +66,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
@ -80,5 +80,7 @@ EOF
$this->cacheWarmer->warmUp($kernel->getContainer()->getParameter('kernel.cache_dir'));
$io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
return 0;
}
}

View File

@ -63,7 +63,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$errorIo = $io->getErrorStyle();
@ -73,7 +73,7 @@ EOF
$errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. <comment>debug:config FrameworkBundle</comment>)');
$errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>debug:config FrameworkBundle serializer</comment> to dump the <comment>framework.serializer</comment> configuration)');
return;
return 0;
}
$extension = $this->findExtension($name);
@ -101,7 +101,7 @@ EOF
$io->writeln(Yaml::dump([$extensionAlias => $config], 10));
return;
return 0;
}
try {
@ -115,6 +115,8 @@ EOF
$io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path));
$io->writeln(Yaml::dump($config, 10));
return 0;
}
private function compileContainer(): ContainerBuilder

View File

@ -114,7 +114,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getOption('show-private')) {
@trigger_error('The "--show-private" option no longer has any effect and is deprecated since Symfony 4.1.', E_USER_DEPRECATED);
@ -184,6 +184,8 @@ EOF
$errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. <comment>debug:container log</comment>)');
}
}
return 0;
}
/**

View File

@ -69,7 +69,7 @@ EOF
*
* @throws \LogicException
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
@ -78,7 +78,7 @@ EOF
if (!$this->dispatcher->hasListeners($event)) {
$io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event));
return;
return 0;
}
$options = ['event' => $event];
@ -89,5 +89,7 @@ EOF
$options['raw_text'] = $input->getOption('raw');
$options['output'] = $io;
$helper->describe($io, $this->dispatcher, $options);
return 0;
}
}

View File

@ -73,7 +73,7 @@ EOF
*
* @throws InvalidArgumentException When route does not exist
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name');
@ -105,6 +105,8 @@ EOF
'output' => $io,
]);
}
return 0;
}
private function findRouteNameContaining(string $name, RouteCollection $routes): array

View File

@ -124,7 +124,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
@ -246,7 +246,7 @@ EOF
$io->getErrorStyle()->warning($outputMessage);
return;
return 0;
}
// Load the fallback catalogues
@ -295,6 +295,8 @@ EOF
}
$io->table($headers, $rows);
return 0;
}
private function formatState(int $state): string

View File

@ -59,7 +59,7 @@ EOF
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$container = $this->getApplication()->getKernel()->getContainer();
$serviceId = $input->getArgument('name');
@ -97,5 +97,7 @@ EOF
],
];
$output->writeln($dumper->dump($workflow->getDefinition(), $marking, $options));
return 0;
}
}

View File

@ -123,6 +123,8 @@ EOF
$this->displayLog($input, $output, $clientId, $record);
}
return 0;
}
private function getLogs($socket)

View File

@ -164,6 +164,6 @@ EOF
return 1;
}
return null;
return 0;
}
}

View File

@ -103,6 +103,6 @@ EOF
}
}
return null;
return 0;
}
}

View File

@ -77,6 +77,6 @@ EOF
return 1;
}
return null;
return 0;
}
}

View File

@ -10,6 +10,7 @@ CHANGELOG
* `Application` implements `ResetInterface`
* marked all dispatched event classes as `@final`
* added support for displaying table horizontally
* deprecated returning `null` from `Command::execute()`, return `0` instead
4.3.0
-----

View File

@ -150,7 +150,7 @@ class Command
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
* @return int|void void or 0 if everything went fine, or an exit code
* @return int 0 if everything went fine, or an exit code
*
* @throws LogicException When this abstract method is not implemented
*
@ -253,6 +253,10 @@ class Command
$statusCode = ($this->code)($input, $output);
} else {
$statusCode = $this->execute($input, $output);
if (!\is_int($statusCode)) {
@trigger_error(sprintf('A non numeric or nullable $statusCode returned by Command::execute() is deprecated since Symfony 4.4, return an integer value instead.'), E_USER_DEPRECATED);
}
}
return is_numeric($statusCode) ? (int) $statusCode : 0;

View File

@ -77,5 +77,7 @@ EOF
]);
$this->command = null;
return 0;
}
}

View File

@ -74,6 +74,8 @@ EOF
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
]);
return 0;
}
private function createDefinition(): InputDefinition

View File

@ -1837,9 +1837,11 @@ class CustomDefaultCommandApplication extends Application
class LazyCommand extends Command
{
public function execute(InputInterface $input, OutputInterface $output)
public function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('lazy-command called');
return 0;
}
}

View File

@ -300,20 +300,6 @@ class CommandTest extends TestCase
$tester->execute(['--bar' => true]);
}
public function testRunReturnsIntegerExitCode()
{
$command = new \TestCommand();
$exitCode = $command->run(new StringInput(''), new NullOutput());
$this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)');
$command = $this->getMockBuilder('TestCommand')->setMethods(['execute'])->getMock();
$command->expects($this->once())
->method('execute')
->willReturn('2.3');
$exitCode = $command->run(new StringInput(''), new NullOutput());
$this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)');
}
public function testRunWithApplication()
{
$command = new \TestCommand();

View File

@ -15,7 +15,8 @@ class BarHiddenCommand extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
return 0;
}
}

View File

@ -18,9 +18,11 @@ class Foo1Command extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
return 0;
}
}

View File

@ -15,7 +15,8 @@ class Foo2Command extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
return 0;
}
}

View File

@ -14,7 +14,7 @@ class Foo3Command extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
try {
@ -25,5 +25,7 @@ class Foo3Command extends Command
} catch (\Exception $e) {
throw new \Exception('Third exception <fg=blue;bg=red>comment</>', 404, $e);
}
return 0;
}
}

View File

@ -23,11 +23,13 @@ class FooCommand extends Command
$output->writeln('interact called');
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
$output->writeln('called');
return 0;
}
}

View File

@ -15,7 +15,8 @@ class FooHiddenCommand extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
return 0;
}
}

View File

@ -25,12 +25,14 @@ class FooOptCommand extends Command
$output->writeln('interact called');
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
$output->writeln('called');
$output->writeln($this->input->getOption('fooopt'));
return 0;
}
}

View File

@ -18,9 +18,11 @@ class FooSubnamespaced1Command extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
return 0;
}
}

View File

@ -18,9 +18,11 @@ class FooSubnamespaced2Command extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
return 0;
}
}

View File

@ -14,8 +14,10 @@ class FooWithoutAliasCommand extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('called');
return 0;
}
}

View File

@ -17,9 +17,11 @@ class FoobarCommand extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
return 0;
}
}

View File

@ -15,8 +15,10 @@ class TestAmbiguousCommandRegistering extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->write('test-ambiguous');
return 0;
}
}

View File

@ -14,8 +14,10 @@ class TestAmbiguousCommandRegistering2 extends Command
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->write('test-ambiguous2');
return 0;
}
}

View File

@ -19,6 +19,8 @@ class TestCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('execute called');
return 0;
}
protected function interact(InputInterface $input, OutputInterface $output)

View File

@ -95,6 +95,8 @@ EOF
$io->newLine();
$io->table(['Format', 'Class'], $tableRows);
}
return 0;
}
private function formatClassLink(string $class): string

View File

@ -152,6 +152,8 @@ EOF
$options['format'] = $input->getOption('format');
$options['show_deprecated'] = $input->getOption('show-deprecated');
$helper->describe($io, $object, $options);
return 0;
}
private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, string $shortClassName)

View File

@ -227,6 +227,8 @@ EOF
$worker->run([
'sleep' => $input->getOption('sleep') * 1000000,
]);
return 0;
}
private function convertToBytes(string $memoryLimit): int

View File

@ -96,6 +96,8 @@ EOF
$io->warning(sprintf('No handled message found in bus "%s".', $bus));
}
}
return 0;
}
private function formatConditions(array $options): string

View File

@ -61,6 +61,8 @@ EOF
$shouldForce = $input->getOption('force');
$this->removeSingleMessage($input->getArgument('id'), $receiver, $io, $shouldForce);
return 0;
}
private function removeSingleMessage(string $id, ReceiverInterface $receiver, SymfonyStyle $io, bool $shouldForce)

View File

@ -110,11 +110,13 @@ EOF
$this->runInteractive($io, $shouldForce);
return;
return 0;
}
$this->retrySpecificIds($ids, $io, $shouldForce);
$io->success('All done!');
return 0;
}
private function runInteractive(SymfonyStyle $io, bool $shouldForce)

View File

@ -71,6 +71,8 @@ EOF
} else {
$this->showMessage($id, $io);
}
return 0;
}
private function listMessages(SymfonyStyle $io, int $max)

View File

@ -76,5 +76,7 @@ EOF
$io->note(sprintf('The "%s" transport does not support setup.', $transportName));
}
}
return 0;
}
}

View File

@ -68,5 +68,7 @@ EOF
$this->restartSignalCachePool->save($cacheItem);
$io->success('Signal successfully sent to stop any running workers.');
return 0;
}
}

View File

@ -75,7 +75,7 @@ EOF
;
}
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$format = $input->getOption('format');