Skip to content

Commit

Permalink
bug #22322 [Console] Fix fatal error when logging console.error witho…
Browse files Browse the repository at this point in the history
…ut command (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Console] Fix fatal error when logging console.error without command

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #22449
| License       | MIT
| Doc PR        | n/a

Happens now that the console.error event is dispatched on command not found, I  ran into using `server:run` on 3.3 without `web-server-bundle` enabled:

> PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Call to a member function getName() on null

In this case, this first tries to cast the event input as string (less good than when the command name is available, there're extra quotes around the command name) and, if can't be casted, uses a generic message.

Commits
-------

97129fc Fix fatal error when logging console.error without a command
  • Loading branch information
fabpot committed Apr 19, 2017
2 parents a84f59e + 97129fc commit 9c0067b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 7 deletions.
20 changes: 16 additions & 4 deletions src/Symfony/Component/Console/EventListener/ExceptionListener.php
Expand Up @@ -39,7 +39,11 @@ public function onConsoleError(ConsoleErrorEvent $event)

$error = $event->getError();

$this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $this->getInputString($event), 'message' => $error->getMessage()));
if (!$inputString = $this->getInputString($event)) {
return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage()));
}

$this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage()));
}

public function onConsoleTerminate(ConsoleTerminateEvent $event)
Expand All @@ -54,7 +58,11 @@ public function onConsoleTerminate(ConsoleTerminateEvent $event)
return;
}

$this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $this->getInputString($event), 'code' => $exitCode));
if (!$inputString = $this->getInputString($event)) {
return $this->logger->error('The console exited with code "{code}"', array('code' => $exitCode));
}

$this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode));
}

public static function getSubscribedEvents()
Expand All @@ -67,11 +75,15 @@ public static function getSubscribedEvents()

private static function getInputString(ConsoleEvent $event)
{
$commandName = $event->getCommand()->getName();
$commandName = $event->getCommand() ? $event->getCommand()->getName() : null;
$input = $event->getInput();

if (method_exists($input, '__toString')) {
return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input);
if ($commandName) {
return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input);
}

return (string) $input;
}

return $commandName;
Expand Down
Expand Up @@ -19,6 +19,7 @@
use Symfony\Component\Console\EventListener\ExceptionListener;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\Input;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -37,7 +38,22 @@ public function testOnConsoleError()
;

$listener = new ExceptionListener($logger);
$listener->onConsoleError($this->getConsoleErrorEvent($exception, new ArgvInput(array('console.php', 'test:run', '--foo=baz', 'buzz')), 1));
$listener->onConsoleError($this->getConsoleErrorEvent($exception, new ArgvInput(array('console.php', 'test:run', '--foo=baz', 'buzz')), 1, new Command('test:run')));
}

public function testOnConsoleErrorWithNoCommandAndNoInputString()
{
$exception = new \RuntimeException('An error occurred');

$logger = $this->getLogger();
$logger
->expects($this->once())
->method('error')
->with('An error occurred while using the console. Message: "{message}"', array('error' => $exception, 'message' => 'An error occurred'))
;

$listener = new ExceptionListener($logger);
$listener->onConsoleError($this->getConsoleErrorEvent($exception, new NonStringInput(), 1));
}

public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog()
Expand Down Expand Up @@ -109,9 +125,9 @@ private function getLogger()
return $this->getMockForAbstractClass(LoggerInterface::class);
}

private function getConsoleErrorEvent(\Exception $exception, InputInterface $input, $exitCode)
private function getConsoleErrorEvent(\Exception $exception, InputInterface $input, $exitCode, Command $command = null)
{
return new ConsoleErrorEvent($input, $this->getOutput(), $exception, $exitCode, new Command('test:run'));
return new ConsoleErrorEvent($input, $this->getOutput(), $exception, $exitCode, $command);
}

private function getConsoleTerminateEvent(InputInterface $input, $exitCode)
Expand All @@ -124,3 +140,22 @@ private function getOutput()
return $this->getMockBuilder(OutputInterface::class)->getMock();
}
}

class NonStringInput extends Input
{
public function getFirstArgument()
{
}

public function hasParameterOption($values, $onlyParams = false)
{
}

public function getParameterOption($values, $default = false, $onlyParams = false)
{
}

public function parse()
{
}
}

0 comments on commit 9c0067b

Please sign in to comment.