diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 722045091ff49..d7df29f120c3a 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.4 --- + * A new `Command::getCode()` method enables getting the invokable object. * 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()` diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 1d2e12bdcce25..d8f6d7358029b 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -356,6 +356,14 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti } } + /** + * Get the code that is executed by the command. + */ + public function getCode(): ?callable + { + return $this->code?->getCode(); + } + /** * Sets the code to execute when running this command. * diff --git a/src/Symfony/Component/Console/Command/InvokableCommand.php b/src/Symfony/Component/Console/Command/InvokableCommand.php index 72ff407c81fdf..b497f4df73bfc 100644 --- a/src/Symfony/Component/Console/Command/InvokableCommand.php +++ b/src/Symfony/Component/Console/Command/InvokableCommand.php @@ -30,18 +30,20 @@ */ class InvokableCommand implements SignalableCommandInterface { - private readonly \Closure $code; + private readonly \Closure $closure; private readonly ?SignalableCommandInterface $signalableCommand; private readonly \ReflectionFunction $reflection; private bool $triggerDeprecations = false; + private $code; public function __construct( private readonly Command $command, callable $code, ) { - $this->code = $this->getClosure($code); + $this->code = $code; + $this->closure = $this->getClosure($code); $this->signalableCommand = $code instanceof SignalableCommandInterface ? $code : null; - $this->reflection = new \ReflectionFunction($this->code); + $this->reflection = new \ReflectionFunction($this->closure); } /** @@ -49,7 +51,7 @@ public function __construct( */ public function __invoke(InputInterface $input, OutputInterface $output): int { - $statusCode = ($this->code)(...$this->getParameters($input, $output)); + $statusCode = ($this->closure)(...$this->getParameters($input, $output)); if (!\is_int($statusCode)) { if ($this->triggerDeprecations) { @@ -81,6 +83,11 @@ public function configure(InputDefinition $definition): void } } + public function getCode(): callable + { + return $this->code; + } + private function getClosure(callable $code): \Closure { if (!$code instanceof \Closure) { diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index a4a719b3d10ab..fd7755ca381c5 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -469,6 +469,8 @@ public function testCommandAttribute() $this->assertStringContainsString('usage1', $command->getUsages()[0]); $this->assertTrue($command->isHidden()); $this->assertSame(['f'], $command->getAliases()); + // Standard commands don't have code. + $this->assertNull($command->getCode()); } /** diff --git a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php index 8bd0dceb4425e..241af475d0034 100644 --- a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php @@ -26,6 +26,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tests\Fixtures\InvokableTestCommand; class InvokableCommandTest extends TestCase { @@ -292,6 +293,16 @@ public function __invoke() $command->run(new ArrayInput([]), new NullOutput()); } + public function testGetCode() + { + // Create a command from an invokable class. + $invokableTestCommand = new InvokableTestCommand(); + $command = new Command(null, $invokableTestCommand); + + // Ensure that the invokable class can be retrieved from the Command. + $this->assertSame($invokableTestCommand, $command->getCode()); + } + /** * @dataProvider provideInputArguments */
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: