[Console] Simplify using invokable commands when the component is used standalone

This commit is contained in:
HypeMC
2025-06-09 17:40:54 +02:00
parent 5e7cd96684
commit 32c3794a26
15 changed files with 207 additions and 106 deletions

View File

@@ -11,6 +11,7 @@
namespace Symfony\Component\Console;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\CompleteCommand;
use Symfony\Component\Console\Command\DumpCompletionCommand;
@@ -28,6 +29,7 @@ use Symfony\Component\Console\Event\ConsoleSignalEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\NamespaceNotFoundException;
use Symfony\Component\Console\Exception\RuntimeException;
@@ -512,7 +514,7 @@ class Application implements ResetInterface
*/
public function register(string $name): Command
{
return $this->add(new Command($name));
return $this->addCommand(new Command($name));
}
/**
@@ -520,25 +522,50 @@ class Application implements ResetInterface
*
* If a Command is not enabled it will not be added.
*
* @param Command[] $commands An array of commands
* @param callable[]|Command[] $commands An array of commands
*/
public function addCommands(array $commands): void
{
foreach ($commands as $command) {
$this->add($command);
$this->addCommand($command);
}
}
/**
* @deprecated since Symfony 7.4, use Application::addCommand() instead
*/
public function add(Command $command): ?Command
{
trigger_deprecation('symfony/console', '7.4', 'The "%s()" method is deprecated and will be removed in Symfony 8.0, use "%s::addCommand()" instead.', __METHOD__, self::class);
return $this->addCommand($command);
}
/**
* Adds a command object.
*
* If a command with the same name already exists, it will be overridden.
* If the command is not enabled it will not be added.
*/
public function add(Command $command): ?Command
public function addCommand(callable|Command $command): ?Command
{
$this->init();
if (!$command instanceof Command) {
if (!\is_object($command) || $command instanceof \Closure) {
throw new InvalidArgumentException(\sprintf('The command must be an instance of "%s" or an invokable object.', Command::class));
}
/** @var AsCommand $attribute */
$attribute = ((new \ReflectionObject($command))->getAttributes(AsCommand::class)[0] ?? null)?->newInstance()
?? throw new LogicException(\sprintf('The command must use the "%s" attribute.', AsCommand::class));
$command = (new Command($attribute->name))
->setDescription($attribute->description ?? '')
->setHelp($attribute->help ?? '')
->setCode($command);
}
$command->setApplication($this);
if (!$command->isEnabled()) {
@@ -604,7 +631,7 @@ class Application implements ResetInterface
{
$this->init();
return isset($this->commands[$name]) || ($this->commandLoader?->has($name) && $this->add($this->commandLoader->get($name)));
return isset($this->commands[$name]) || ($this->commandLoader?->has($name) && $this->addCommand($this->commandLoader->get($name)));
}
/**
@@ -1322,7 +1349,7 @@ class Application implements ResetInterface
$this->initialized = true;
foreach ($this->getDefaultCommands() as $command) {
$this->add($command);
$this->addCommand($command);
}
}
}

View File

@@ -5,6 +5,8 @@ CHANGELOG
---
* Allow setting aliases and the hidden flag via the command name passed to the constructor
* Introduce `Symfony\Component\Console\Application::addCommand()` to simplify using invokable commands when the component is used standalone
* Deprecate `Symfony\Component\Console\Application::add()` in favor of `Symfony\Component\Console\Application::addCommand()`
7.3
---

View File

@@ -57,7 +57,7 @@ class SingleCommandApplication extends Command
$application->setAutoExit($this->autoExit);
// Fix the usage of the command displayed with "--help"
$this->setName($_SERVER['argv'][0]);
$application->add($this);
$application->addCommand($this);
$application->setDefaultCommand($this->getName(), true);
$this->running = true;

View File

@@ -16,6 +16,7 @@ use Symfony\Component\Console\Application;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\InvokableCommand;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\Command\SignalableCommandInterface;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
@@ -28,6 +29,8 @@ use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleSignalEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\NamespaceNotFoundException;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\HelperSet;
@@ -163,7 +166,7 @@ class ApplicationTest extends TestCase
$commands = $application->all();
$this->assertInstanceOf(HelpCommand::class, $commands['help'], '->all() returns the registered commands');
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$commands = $application->all('foo');
$this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
}
@@ -174,7 +177,7 @@ class ApplicationTest extends TestCase
$commands = $application->all();
$this->assertInstanceOf(HelpCommand::class, $commands['help'], '->all() returns the registered commands');
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$commands = $application->all('foo');
$this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
@@ -221,7 +224,7 @@ class ApplicationTest extends TestCase
public function testAdd()
{
$application = new Application();
$application->add($foo = new \FooCommand());
$application->addCommand($foo = new \FooCommand());
$commands = $application->all();
$this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command');
@@ -236,7 +239,60 @@ class ApplicationTest extends TestCase
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.');
(new Application())->add(new \Foo5Command());
(new Application())->addCommand(new \Foo5Command());
}
public function testAddCommandWithExtendedCommand()
{
$application = new Application();
$application->addCommand($foo = new \FooCommand());
$commands = $application->all();
$this->assertEquals($foo, $commands['foo:bar']);
}
public function testAddCommandWithInvokableCommand()
{
$application = new Application();
$application->addCommand($foo = new InvokableTestCommand());
$commands = $application->all();
$this->assertInstanceOf(Command::class, $command = $commands['invokable']);
$this->assertEquals(new InvokableCommand($command, $foo), (new \ReflectionObject($command))->getProperty('code')->getValue($command));
}
public function testAddCommandWithInvokableExtendedCommand()
{
$application = new Application();
$application->addCommand($foo = new InvokableExtendedTestCommand());
$commands = $application->all();
$this->assertEquals($foo, $commands['invokable-extended']);
}
/**
* @dataProvider provideInvalidInvokableCommands
*/
public function testAddCommandThrowsExceptionOnInvalidCommand(callable $command, string $expectedException, string $expectedExceptionMessage)
{
$application = new Application();
$this->expectException($expectedException);
$this->expectExceptionMessage($expectedExceptionMessage);
$application->addCommand($command);
}
public static function provideInvalidInvokableCommands(): iterable
{
yield 'a function' => ['strlen', InvalidArgumentException::class, \sprintf('The command must be an instance of "%s" or an invokable object.', Command::class)];
yield 'a closure' => [function () {
}, InvalidArgumentException::class, \sprintf('The command must be an instance of "%s" or an invokable object.', Command::class)];
yield 'without the #[AsCommand] attribute' => [new class {
public function __invoke()
{
}
}, LogicException::class, \sprintf('The command must use the "%s" attribute.', AsCommand::class)];
}
public function testHasGet()
@@ -245,13 +301,13 @@ class ApplicationTest extends TestCase
$this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
$this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');
$application->add($foo = new \FooCommand());
$application->addCommand($foo = new \FooCommand());
$this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
$this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
$this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');
$application = new Application();
$application->add($foo = new \FooCommand());
$application->addCommand($foo = new \FooCommand());
// simulate --help
$r = new \ReflectionObject($application);
$p = $r->getProperty('wantHelps');
@@ -266,7 +322,7 @@ class ApplicationTest extends TestCase
$this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
$this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');
$application->add($foo = new \FooCommand());
$application->addCommand($foo = new \FooCommand());
$this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
$this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
$this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');
@@ -307,35 +363,35 @@ class ApplicationTest extends TestCase
public function testGetNamespaces()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$this->assertEquals(['foo'], $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces');
}
public function testFindNamespace()
{
$application = new Application();
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
$this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation');
$application->add(new \Foo2Command());
$application->addCommand(new \Foo2Command());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
}
public function testFindNamespaceWithSubnamespaces()
{
$application = new Application();
$application->add(new \FooSubnamespaced1Command());
$application->add(new \FooSubnamespaced2Command());
$application->addCommand(new \FooSubnamespaced1Command());
$application->addCommand(new \FooSubnamespaced2Command());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces');
}
public function testFindAmbiguousNamespace()
{
$application = new Application();
$application->add(new \BarBucCommand());
$application->add(new \FooCommand());
$application->add(new \Foo2Command());
$application->addCommand(new \BarBucCommand());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo2Command());
$expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1";
@@ -348,8 +404,8 @@ class ApplicationTest extends TestCase
public function testFindNonAmbiguous()
{
$application = new Application();
$application->add(new \TestAmbiguousCommandRegistering());
$application->add(new \TestAmbiguousCommandRegistering2());
$application->addCommand(new \TestAmbiguousCommandRegistering());
$application->addCommand(new \TestAmbiguousCommandRegistering2());
$this->assertEquals('test-ambiguous', $application->find('test')->getName());
}
@@ -364,9 +420,9 @@ class ApplicationTest extends TestCase
public function testFindUniqueNameButNamespaceName()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
$this->expectException(CommandNotFoundException::class);
$this->expectExceptionMessage('Command "foo1" is not defined');
@@ -377,7 +433,7 @@ class ApplicationTest extends TestCase
public function testFind()
{
$application = new Application();
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$this->assertInstanceOf(\FooCommand::class, $application->find('foo:bar'), '->find() returns a command if its name exists');
$this->assertInstanceOf(HelpCommand::class, $application->find('h'), '->find() returns a command if its name exists');
@@ -389,8 +445,8 @@ class ApplicationTest extends TestCase
public function testFindCaseSensitiveFirst()
{
$application = new Application();
$application->add(new \FooSameCaseUppercaseCommand());
$application->add(new \FooSameCaseLowercaseCommand());
$application->addCommand(new \FooSameCaseUppercaseCommand());
$application->addCommand(new \FooSameCaseLowercaseCommand());
$this->assertInstanceOf(\FooSameCaseUppercaseCommand::class, $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case');
$this->assertInstanceOf(\FooSameCaseUppercaseCommand::class, $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case');
@@ -401,7 +457,7 @@ class ApplicationTest extends TestCase
public function testFindCaseInsensitiveAsFallback()
{
$application = new Application();
$application->add(new \FooSameCaseLowercaseCommand());
$application->addCommand(new \FooSameCaseLowercaseCommand());
$this->assertInstanceOf(\FooSameCaseLowercaseCommand::class, $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case');
$this->assertInstanceOf(\FooSameCaseLowercaseCommand::class, $application->find('f:B'), '->find() will fallback to case insensitivity');
@@ -411,8 +467,8 @@ class ApplicationTest extends TestCase
public function testFindCaseInsensitiveSuggestions()
{
$application = new Application();
$application->add(new \FooSameCaseLowercaseCommand());
$application->add(new \FooSameCaseUppercaseCommand());
$application->addCommand(new \FooSameCaseLowercaseCommand());
$application->addCommand(new \FooSameCaseUppercaseCommand());
$this->expectException(CommandNotFoundException::class);
$this->expectExceptionMessage('Command "FoO:BaR" is ambiguous');
@@ -444,9 +500,9 @@ class ApplicationTest extends TestCase
$this->expectExceptionMessage($expectedExceptionMessage);
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
$application->find($abbreviation);
}
@@ -476,8 +532,8 @@ class ApplicationTest extends TestCase
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \FooHiddenCommand());
$application->addCommand(new \FooCommand());
$application->addCommand(new \FooHiddenCommand());
$this->assertInstanceOf(\FooCommand::class, $application->find('foo:'));
}
@@ -485,8 +541,8 @@ class ApplicationTest extends TestCase
public function testFindCommandEqualNamespace()
{
$application = new Application();
$application->add(new \Foo3Command());
$application->add(new \Foo4Command());
$application->addCommand(new \Foo3Command());
$application->addCommand(new \Foo4Command());
$this->assertInstanceOf(\Foo3Command::class, $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name');
$this->assertInstanceOf(\Foo4Command::class, $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name');
@@ -495,8 +551,8 @@ class ApplicationTest extends TestCase
public function testFindCommandWithAmbiguousNamespacesButUniqueName()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \FoobarCommand());
$application->addCommand(new \FooCommand());
$application->addCommand(new \FoobarCommand());
$this->assertInstanceOf(\FoobarCommand::class, $application->find('f:f'));
}
@@ -504,7 +560,7 @@ class ApplicationTest extends TestCase
public function testFindCommandWithMissingNamespace()
{
$application = new Application();
$application->add(new \Foo4Command());
$application->addCommand(new \Foo4Command());
$this->assertInstanceOf(\Foo4Command::class, $application->find('f::t'));
}
@@ -515,7 +571,7 @@ class ApplicationTest extends TestCase
public function testFindAlternativeExceptionMessageSingle($name)
{
$application = new Application();
$application->add(new \Foo3Command());
$application->addCommand(new \Foo3Command());
$this->expectException(CommandNotFoundException::class);
$this->expectExceptionMessage('Did you mean this');
@@ -526,7 +582,7 @@ class ApplicationTest extends TestCase
public function testDontRunAlternativeNamespaceName()
{
$application = new Application();
$application->add(new \Foo1Command());
$application->addCommand(new \Foo1Command());
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->run(['command' => 'foos:bar1'], ['decorated' => false]);
@@ -536,7 +592,7 @@ class ApplicationTest extends TestCase
public function testCanRunAlternativeCommandName()
{
$application = new Application();
$application->add(new \FooWithoutAliasCommand());
$application->addCommand(new \FooWithoutAliasCommand());
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->setInputs(['y']);
@@ -550,7 +606,7 @@ class ApplicationTest extends TestCase
public function testDontRunAlternativeCommandName()
{
$application = new Application();
$application->add(new \FooWithoutAliasCommand());
$application->addCommand(new \FooWithoutAliasCommand());
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->setInputs(['n']);
@@ -574,9 +630,9 @@ class ApplicationTest extends TestCase
putenv('COLUMNS=120');
$application = new Application();
$application->setAutoExit(false);
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
$tester = new ApplicationTester($application);
$tester->run(['command' => 'foo'], ['decorated' => false]);
$display = trim($tester->getDisplay(true));
@@ -589,9 +645,9 @@ class ApplicationTest extends TestCase
{
putenv('COLUMNS=120');
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
// Command + plural
try {
@@ -614,8 +670,8 @@ class ApplicationTest extends TestCase
$this->assertMatchesRegularExpression('/foo1/', $e->getMessage());
}
$application->add(new \Foo3Command());
$application->add(new \Foo4Command());
$application->addCommand(new \Foo3Command());
$application->addCommand(new \Foo4Command());
// Subnamespace + plural
try {
@@ -632,9 +688,9 @@ class ApplicationTest extends TestCase
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
try {
$application->find($commandName = 'Unknown command');
@@ -669,7 +725,7 @@ class ApplicationTest extends TestCase
$application->setCommandLoader(new FactoryCommandLoader([
'foo3' => static fn () => $fooCommand,
]));
$application->add($fooCommand);
$application->addCommand($fooCommand);
$result = $application->find('foo');
@@ -680,10 +736,10 @@ class ApplicationTest extends TestCase
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->add(new \Foo3Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
$application->addCommand(new \Foo3Command());
try {
$application->find('Unknown-namespace:Unknown-command');
@@ -715,11 +771,11 @@ class ApplicationTest extends TestCase
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->add(new \Foo3Command());
$application->add(new \FooHiddenCommand());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo1Command());
$application->addCommand(new \Foo2Command());
$application->addCommand(new \Foo3Command());
$application->addCommand(new \FooHiddenCommand());
$expectedAlternatives = [
'afoobar',
@@ -755,8 +811,8 @@ class ApplicationTest extends TestCase
public function testFindWithDoubleColonInNameThrowsException()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo4Command());
$application->addCommand(new \FooCommand());
$application->addCommand(new \Foo4Command());
$this->expectException(CommandNotFoundException::class);
$this->expectExceptionMessage('Command "foo::bar" is not defined.');
@@ -767,7 +823,7 @@ class ApplicationTest extends TestCase
public function testFindHiddenWithExactName()
{
$application = new Application();
$application->add(new \FooHiddenCommand());
$application->addCommand(new \FooHiddenCommand());
$this->assertInstanceOf(\FooHiddenCommand::class, $application->find('foo:hidden'));
$this->assertInstanceOf(\FooHiddenCommand::class, $application->find('afoohidden'));
@@ -777,8 +833,8 @@ class ApplicationTest extends TestCase
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \FooHiddenCommand());
$application->addCommand(new \FooCommand());
$application->addCommand(new \FooHiddenCommand());
$this->assertInstanceOf(\FooCommand::class, $application->find('foo:'));
}
@@ -824,7 +880,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions($catchExceptions);
$application->add((new Command('boom'))->setCode(fn () => throw new \Error('This is an error.')));
$application->addCommand((new Command('boom'))->setCode(fn () => throw new \Error('This is an error.')));
putenv('COLUMNS=120');
$tester = new ApplicationTester($application);
@@ -870,7 +926,7 @@ class ApplicationTest extends TestCase
$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');
$application->add(new \Foo3Command());
$application->addCommand(new \Foo3Command());
$tester = new ApplicationTester($application);
$tester->run(['command' => 'foo3:bar'], ['decorated' => false, 'capture_stderr_separately' => true]);
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
@@ -1031,7 +1087,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->add($command = new \Foo1Command());
$application->addCommand($command = new \Foo1Command());
$_SERVER['argv'] = ['cli.php', 'foo:bar1'];
ob_start();
@@ -1116,7 +1172,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$tester = new ApplicationTester($application);
$tester->run(['command' => 'foo:bar', '--no-interaction' => true], ['decorated' => false]);
@@ -1151,7 +1207,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$output = new StreamOutput(fopen('php://memory', 'w', false));
@@ -1762,7 +1818,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->add($command);
$application->addCommand($command);
$application->setDefaultCommand($command->getName());
$tester = new ApplicationTester($application);
@@ -1784,7 +1840,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->add($command);
$application->addCommand($command);
$application->setDefaultCommand($command->getName());
$tester = new ApplicationTester($application);
@@ -1799,7 +1855,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->add($command);
$application->addCommand($command);
$application->setDefaultCommand($command->getName(), true);
$tester = new ApplicationTester($application);
@@ -2150,7 +2206,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setDispatcher($dispatcher);
$application->add($command);
$application->addCommand($command);
$this->assertSame(0, $application->run(new ArrayInput(['signal'])));
}
@@ -2186,7 +2242,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setDispatcher($dispatcher);
$application->add($command);
$application->addCommand($command);
$this->assertSame(129, $application->run(new ArrayInput(['signal'])));
}
@@ -2208,7 +2264,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setDispatcher($dispatcher);
$application->add($command);
$application->addCommand($command);
$tester = new ApplicationTester($application);
$this->assertSame(51, $tester->run(['signal']));
$expected = <<<EOTXT
@@ -2378,7 +2434,7 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->setDispatcher($dispatcher);
$application->add($command);
$application->addCommand($command);
$this->assertSame(0, $application->run(new ArrayInput(['alarm'])));
$this->assertFalse($command->signaled);
@@ -2459,7 +2515,7 @@ class ApplicationTest extends TestCase
if ($dispatcher) {
$application->setDispatcher($dispatcher);
}
$application->add(new LazyCommand($command->getName(), [], '', false, fn () => $command, true));
$application->addCommand(new LazyCommand($command->getName(), [], '', false, fn () => $command, true));
return $application;
}
@@ -2491,7 +2547,7 @@ class CustomDefaultCommandApplication extends Application
parent::__construct();
$command = new \FooCommand();
$this->add($command);
$this->addCommand($command);
$this->setDefaultCommand($command->getName());
}
}
@@ -2514,6 +2570,22 @@ class DisabledCommand extends Command
}
}
#[AsCommand(name: 'invokable')]
class InvokableTestCommand
{
public function __invoke(): int
{
}
}
#[AsCommand(name: 'invokable-extended')]
class InvokableExtendedTestCommand extends Command
{
public function __invoke(): int
{
}
}
#[AsCommand(name: 'signal')]
class BaseSignableCommand extends Command
{

View File

@@ -50,7 +50,7 @@ class CommandTest extends TestCase
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('The command defined in "Symfony\Component\Console\Command\Command" cannot have an empty name.');
(new Application())->add(new Command());
(new Application())->addCommand(new Command());
}
public function testSetApplication()
@@ -190,7 +190,7 @@ class CommandTest extends TestCase
$command = new \TestCommand();
$command->setHelp('The %command.name% command does... Example: %command.full_name%.');
$application = new Application();
$application->add($command);
$application->addCommand($command);
$application->setDefaultCommand('namespace:name', true);
$this->assertStringContainsString('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly in single command applications');
$this->assertStringNotContainsString('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name% in single command applications');

View File

@@ -33,7 +33,7 @@ class CompleteCommandTest extends TestCase
$this->command = new CompleteCommand();
$this->application = new Application();
$this->application->add(new CompleteCommandTest_HelloCommand());
$this->application->addCommand(new CompleteCommandTest_HelloCommand());
$this->command->setApplication($this->application);
$this->tester = new CommandTester($this->command);

View File

@@ -77,7 +77,7 @@ class HelpCommandTest extends TestCase
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$tester = new CommandCompletionTester($application->get('help'));
$suggestions = $tester->complete($input, 2);
$this->assertSame($expectedSuggestions, $suggestions);

View File

@@ -54,7 +54,7 @@ EOF;
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), 'namespace' => 'foo', '--raw' => true]);
$output = <<<'EOF'
@@ -69,7 +69,7 @@ EOF;
{
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
$application = new Application();
$application->add(new \Foo6Command());
$application->addCommand(new \Foo6Command());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName()], ['decorated' => false]);
$output = <<<'EOF'
@@ -102,7 +102,7 @@ EOF;
{
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
$application = new Application();
$application->add(new \Foo6Command());
$application->addCommand(new \Foo6Command());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), '--raw' => true]);
$output = <<<'EOF'
@@ -122,7 +122,7 @@ EOF;
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$application->addCommand(new \FooCommand());
$tester = new CommandCompletionTester($application->get('list'));
$suggestions = $tester->complete($input, 2);
$this->assertSame($expectedSuggestions, $suggestions);

View File

@@ -58,7 +58,7 @@ class ConsoleEventsTest extends TestCase
->setPublic(true)
->addMethodCall('setAutoExit', [false])
->addMethodCall('setDispatcher', [new Reference('event_dispatcher')])
->addMethodCall('add', [new Reference('failing_command')])
->addMethodCall('addCommand', [new Reference('failing_command')])
;
$container->compile();

View File

@@ -25,7 +25,7 @@ final class ApplicationDescriptionTest extends TestCase
{
$application = new TestApplication();
foreach ($names as $name) {
$application->add(new Command($name));
$application->addCommand(new Command($name));
}
$this->assertSame($expected, array_keys((new ApplicationDescription($application))->getNamespaces()));

View File

@@ -18,9 +18,9 @@ class DescriptorApplication2 extends Application
public function __construct()
{
parent::__construct('My Symfony application', 'v1.0');
$this->add(new DescriptorCommand1());
$this->add(new DescriptorCommand2());
$this->add(new DescriptorCommand3());
$this->add(new DescriptorCommand4());
$this->addCommand(new DescriptorCommand1());
$this->addCommand(new DescriptorCommand2());
$this->addCommand(new DescriptorCommand3());
$this->addCommand(new DescriptorCommand4());
}
}

View File

@@ -19,6 +19,6 @@ class DescriptorApplicationMbString extends Application
{
parent::__construct('MbString åpplicätion');
$this->add(new DescriptorCommandMbString());
$this->addCommand(new DescriptorCommandMbString());
}
}

View File

@@ -104,7 +104,7 @@ class CommandTesterTest extends TestCase
return 0;
});
$application->add($command);
$application->addCommand($command);
$tester = new CommandTester($application->find('foo'));

View File

@@ -53,7 +53,7 @@ class MyCommand extends Command
$app = new Application();
$app->setDispatcher(new \Symfony\Component\EventDispatcher\EventDispatcher());
$app->add(new MyCommand('foo'));
$app->addCommand(new MyCommand('foo'));
$app
->setDefaultCommand('foo', true)

View File

@@ -45,7 +45,7 @@ class MyCommand extends Command
$app = new Application();
$app->setDispatcher(new \Symfony\Component\EventDispatcher\EventDispatcher());
$app->add(new MyCommand('foo'));
$app->addCommand(new MyCommand('foo'));
$app
->setDefaultCommand('foo', true)