feature #22181 [Console] Allow to catch CommandNotFoundException (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Console] Allow to catch CommandNotFoundException

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | https://github.com/symfony/symfony/pull/22144#issuecomment-289200937
| License       | MIT
| Doc PR        | n/a

Basically reverts #22144, making the command argument optional in console.error event instead, so that `CommandNotFoundException` can be handled as any other console error.

Commits
-------

b21ce850e7 [Console] Allow to catch CommandNotFoundException
This commit is contained in:
Fabien Potencier 2017-04-05 08:05:16 -07:00
commit 54495b2bd6
6 changed files with 27 additions and 5 deletions

View File

@ -128,8 +128,8 @@ class Application
$exception = new FatalThrowableError($e);
}
if (null !== $this->runningCommand && null !== $e && null !== $this->dispatcher) {
$event = new ConsoleErrorEvent($this->runningCommand, $input, $output, $e, $e->getCode());
if (null !== $e && null !== $this->dispatcher) {
$event = new ConsoleErrorEvent($input, $output, $e, $e->getCode(), $this->runningCommand);
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
$e = $event->getError();

View File

@ -10,6 +10,8 @@ CHANGELOG
with value optional explicitly passed empty
* added console.error event to catch exceptions thrown by other listeners
* deprecated console.exception event in favor of console.error
* added ability to handle `CommandNotFoundException` through the
`console.error` event
3.2.0
------

View File

@ -27,7 +27,7 @@ class ConsoleErrorEvent extends ConsoleExceptionEvent
private $error;
private $handled = false;
public function __construct(Command $command, InputInterface $input, OutputInterface $output, $error, $exitCode)
public function __construct(InputInterface $input, OutputInterface $output, $error, $exitCode, Command $command = null)
{
if (!$error instanceof \Throwable && !$error instanceof \Exception) {
throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error)));

View File

@ -27,7 +27,7 @@ class ConsoleExceptionEvent extends ConsoleEvent
private $exception;
private $exitCode;
public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode, $deprecation = true)
public function __construct(Command $command = null, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode, $deprecation = true)
{
if ($deprecation) {
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', __CLASS__), E_USER_DEPRECATED);

View File

@ -1066,6 +1066,26 @@ class ApplicationTest extends TestCase
$this->assertEquals(0, $tester->getStatusCode());
}
public function testConsoleErrorEventIsTriggeredOnCommandNotFound()
{
$dispatcher = new EventDispatcher();
$dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) {
$this->assertNull($event->getCommand());
$this->assertInstanceOf(CommandNotFoundException::class, $event->getError());
$event->getOutput()->write('silenced command not found');
$event->markErrorAsHandled();
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'unknown'));
$this->assertContains('silenced command not found', $tester->getDisplay());
$this->assertEquals(0, $tester->getStatusCode());
}
/**
* @group legacy
* @expectedDeprecation The "console.exception" event is deprecated since version 3.3 and will be removed in 4.0. Use the "console.error" event instead.

View File

@ -111,7 +111,7 @@ class ExceptionListenerTest extends TestCase
private function getConsoleErrorEvent(\Exception $exception, InputInterface $input, $exitCode)
{
return new ConsoleErrorEvent(new Command('test:run'), $input, $this->getOutput(), $exception, $exitCode);
return new ConsoleErrorEvent($input, $this->getOutput(), $exception, $exitCode, new Command('test:run'));
}
private function getConsoleTerminateEvent(InputInterface $input, $exitCode)