Skip to content

Commit

Permalink
feature #22181 [Console] Allow to catch CommandNotFoundException (cha…
Browse files Browse the repository at this point in the history
…lasr)

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 | #22144 (comment)
| 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
-------

b21ce85 [Console] Allow to catch CommandNotFoundException
  • Loading branch information
fabpot committed Apr 5, 2017
2 parents b65ebc7 + b21ce85 commit 54495b2
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/Symfony/Component/Console/Application.php
Expand Up @@ -128,8 +128,8 @@ public function run(InputInterface $input = null, OutputInterface $output = null
$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();
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Component/Console/CHANGELOG.md
Expand Up @@ -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
------
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Console/Event/ConsoleErrorEvent.php
Expand Up @@ -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)));
Expand Down
Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions src/Symfony/Component/Console/Tests/ApplicationTest.php
Expand Up @@ -1066,6 +1066,26 @@ public function testRunAllowsErrorListenersToSilenceTheException()
$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.
Expand Down
Expand Up @@ -111,7 +111,7 @@ private function getLogger()

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)
Expand Down

0 comments on commit 54495b2

Please sign in to comment.