Skip to content

Commit

Permalink
[Console] add ExecuteCommand and ExecuteCommandHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Mar 27, 2023
1 parent 5e6ea11 commit 848bdb7
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
use Symfony\Component\Config\ResourceCheckerInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Messenger\ExecuteCommandHandler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ChildDefinition;
Expand Down Expand Up @@ -320,6 +321,11 @@ public function load(array $configs, ContainerBuilder $container)
if (!class_exists(DebugCommand::class)) {
$container->removeDefinition('console.command.dotenv_debug');
}

if (!class_exists(ExecuteCommandHandler::class)) {
$container->removeDefinition('console.messenger.application');
$container->removeDefinition('console.messenger.execute_command_handler');
}
}

// Load Cache configuration first as it is used by other components
Expand Down
14 changes: 14 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand;
use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand;
use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber;
use Symfony\Component\Console\EventListener\ErrorListener;
use Symfony\Component\Console\Messenger\ExecuteCommandHandler;
use Symfony\Component\Dotenv\Command\DebugCommand as DotenvDebugCommand;
use Symfony\Component\Messenger\Command\ConsumeMessagesCommand;
use Symfony\Component\Messenger\Command\DebugCommand as MessengerDebugCommand;
Expand Down Expand Up @@ -356,5 +358,17 @@
service('secrets.local_vault')->ignoreOnInvalid(),
])
->tag('console.command')

->set('console.messenger.application', Application::class)
->share(false)
->call('setAutoExit', [false])
->args([
service('kernel'),
])

->set('console.messenger.execute_command_handler', ExecuteCommandHandler::class)
->args([
service('console.messenger.application'),
])
;
};
1 change: 1 addition & 0 deletions src/Symfony/Component/Console/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGELOG
* Add support for choosing exit code while handling signal, or to not exit at all
* Add `ProgressBar::setPlaceholderFormatter` to set a placeholder attached to a instance, instead of being global.
* Add `ReStructuredTextDescriptor`
* Add `ExecuteCommand` and `ExecuteCommandHandler`

6.2
---
Expand Down
29 changes: 29 additions & 0 deletions src/Symfony/Component/Console/Messenger/ExecuteCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Messenger;

/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
final class ExecuteCommand implements \Stringable
{
public function __construct(
public readonly string $input,
public readonly bool $catchExceptions = false,
) {
}

public function __toString(): string
{
return $this->input;
}
}
37 changes: 37 additions & 0 deletions src/Symfony/Component/Console/Messenger/ExecuteCommandHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Messenger;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\BufferedOutput;

/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
final class ExecuteCommandHandler
{
public function __construct(private readonly Application $application)
{
}

public function __invoke(ExecuteCommand $message): BufferedOutput
{
$input = new StringInput($message->input);
$output = new BufferedOutput();

$this->application->setCatchExceptions($message->catchExceptions);
$this->application->run($input, $output);

return $output;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Console\Tests\Messenger;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Messenger\ExecuteCommand;
use Symfony\Component\Console\Messenger\ExecuteCommandHandler;
use Symfony\Component\Console\Output\OutputInterface;

/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
final class ExecuteCommandHandlerTest extends TestCase
{
public function testExecutesCommand()
{
$handler = new ExecuteCommandHandler($this->createApplicationWithCommand());
$output = $handler(new ExecuteCommand('test:command'))->fetch();

$this->assertStringContainsString('some message', $output);
}

public function testExecutesCommandThatThrowsException()
{
$handler = new ExecuteCommandHandler($this->createApplicationWithCommand());

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('exception message');

$handler(new ExecuteCommand('test:command --throw'));
}

public function testExecutesCommandThatCatchesThrownException()
{
$handler = new ExecuteCommandHandler($this->createApplicationWithCommand());
$output = $handler(new ExecuteCommand('test:command --throw -v', catchExceptions: true))->fetch();

$this->assertStringContainsString('[RuntimeException]', $output);
$this->assertStringContainsString('exception message', $output);
}

private function createApplicationWithCommand(): Application
{
$application = new Application();
$application->setAutoExit(false);
$application->addCommands([
new class() extends Command {
public function configure(): void
{
$this
->setName('test:command')
->addOption('throw')
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getOption('throw')) {
throw new \RuntimeException('exception message');
}

$output->write('some message');

return Command::SUCCESS;
}
},
]);

return $application;
}
}
1 change: 1 addition & 0 deletions src/Symfony/Component/Console/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/lock": "^5.4|^6.0",
"symfony/messenger": "^6.3",
"symfony/process": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0",
"psr/log": "^1|^2|^3"
Expand Down

0 comments on commit 848bdb7

Please sign in to comment.