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); $exception = new FatalThrowableError($e);
} }
if (null !== $this->runningCommand && null !== $e && null !== $this->dispatcher) { if (null !== $e && null !== $this->dispatcher) {
$event = new ConsoleErrorEvent($this->runningCommand, $input, $output, $e, $e->getCode()); $event = new ConsoleErrorEvent($input, $output, $e, $e->getCode(), $this->runningCommand);
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
$e = $event->getError(); $e = $event->getError();

View File

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

View File

@ -27,7 +27,7 @@ class ConsoleErrorEvent extends ConsoleExceptionEvent
private $error; private $error;
private $handled = false; 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) { 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))); 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 $exception;
private $exitCode; 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) { 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); @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()); $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 * @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. * @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) 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) private function getConsoleTerminateEvent(InputInterface $input, $exitCode)