Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 518a4d3

Browse files
committed
Add Console ExceptionListener
Handle non string-castable inputs Cleanup input for display Naming changes InputInterface doesnt have a toString() Logger must be private Remove useless doc blocks Tweak tests
1 parent d94a1bf commit 518a4d3

File tree

4 files changed

+83
-62
lines changed

4 files changed

+83
-62
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
66

77
<services>
8+
89
<service id="console.exception_listener" class="Symfony\Component\Console\EventListener\ExceptionListener">
9-
<tag name="kernel.event_subscriber" />
1010
<argument type="service" id="logger" on-invalid="null" />
11+
<tag name="kernel.event_subscriber" />
12+
<tag name="monolog.logger" channel="console" />
1113
</service>
14+
1215
</services>
1316
</container>

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"require-dev": {
3535
"symfony/asset": "~2.8|~3.0",
3636
"symfony/browser-kit": "~2.8|~3.0",
37-
"symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2",
37+
"symfony/console": "~3.3",
3838
"symfony/css-selector": "~2.8|~3.0",
3939
"symfony/dom-crawler": "~2.8|~3.0",
4040
"symfony/polyfill-intl-icu": "~1.0",

src/Symfony/Component/Console/EventListener/ExceptionListener.php

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Console\EventListener;
1313

1414
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Console\Event\ConsoleEvent;
1516
use Symfony\Component\Console\ConsoleEvents;
1617
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
1718
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
@@ -20,71 +21,61 @@
2021
/**
2122
* Console exception listener.
2223
*
23-
* Attempts to log exceptions or abnormal terminations of console commands.
24-
*
2524
* @author James Halsall <[email protected]>
25+
* @author Robin Chalas <[email protected]>
2626
*/
2727
class ExceptionListener implements EventSubscriberInterface
2828
{
29-
/**
30-
* @var LoggerInterface
31-
*/
32-
protected $logger;
33-
34-
/**
35-
* Constructor.
36-
*
37-
* @param LoggerInterface $logger A logger
38-
*/
29+
private $logger;
30+
3931
public function __construct(LoggerInterface $logger = null)
4032
{
4133
$this->logger = $logger;
4234
}
4335

44-
/**
45-
* Handles console command exception.
46-
*
47-
* @param ConsoleExceptionEvent $event Console event
48-
*/
49-
public function onKernelException(ConsoleExceptionEvent $event)
36+
public function onConsoleException(ConsoleExceptionEvent $event)
5037
{
5138
if (null === $this->logger) {
5239
return;
5340
}
5441

5542
$exception = $event->getException();
56-
$input = (string) $event->getInput();
5743

58-
$this->logger->error('Exception thrown while running command: "{command}". Message: "{message}"', array('exception' => $exception, 'command' => $input, 'message' => $exception->getMessage()));
44+
$this->logger->error('Exception thrown while running command "{command}". Message: "{message}"', array('exception' => $exception, 'command' => $this->getInputString($event), 'message' => $exception->getMessage()));
5945
}
6046

61-
/**
62-
* Handles termination of console command.
63-
*
64-
* @param ConsoleTerminateEvent $event Console event
65-
*/
66-
public function onKernelTerminate(ConsoleTerminateEvent $event)
47+
public function onConsoleTerminate(ConsoleTerminateEvent $event)
6748
{
6849
if (null === $this->logger) {
6950
return;
7051
}
7152

7253
$exitCode = $event->getExitCode();
7354

74-
if ($exitCode === 0) {
55+
if (0 === $exitCode) {
7556
return;
7657
}
7758

78-
$input = (string) $event->getInput();
79-
80-
$this->logger->error('Command "{command}" exited with status code "{code}"', array('command' => (string) $input, 'code' => $exitCode));
59+
$this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $this->getInputString($event), 'code' => $exitCode));
8160
}
8261

8362
public static function getSubscribedEvents()
8463
{
8564
return array(
86-
ConsoleEvents::EXCEPTION => array('onKernelException', -128),
87-
ConsoleEvents::TERMINATE => array('onKernelTerminate', -128),
65+
ConsoleEvents::EXCEPTION => array('onConsoleException', -128),
66+
ConsoleEvents::TERMINATE => array('onConsoleTerminate', -128),
8867
);
8968
}
69+
70+
private static function getInputString(ConsoleEvent $event)
71+
{
72+
$commandName = $event->getCommand()->getName();
73+
$input = $event->getInput();
74+
75+
if (method_exists($input, '__toString')) {
76+
return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input);
77+
}
78+
79+
return $commandName;
80+
}
9081
}

src/Symfony/Component/Console/Tests/EventListener/ExceptionListenerTest.php

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,83 +16,110 @@
1616
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
1717
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
1818
use Symfony\Component\Console\EventListener\ExceptionListener;
19+
use Symfony\Component\Console\Input\ArgvInput;
1920
use Symfony\Component\Console\Input\ArrayInput;
20-
use Symfony\Component\Console\Tests\Output\TestOutput;
21+
use Symfony\Component\Console\Input\StringInput;
22+
use Symfony\Component\Console\Input\InputInterface;
23+
use Symfony\Component\Console\Output\OutputInterface;
2124

2225
class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
2326
{
24-
public function testOnKernelException()
27+
public function testOnConsoleException()
2528
{
26-
$logger = $this->getLogger();
27-
$listener = new ExceptionListener($logger);
28-
2929
$exception = new \RuntimeException('An error occurred');
3030

31+
$logger = $this->getLogger();
3132
$logger
3233
->expects($this->once())
3334
->method('error')
34-
->with('Exception thrown while running command: "{command}". Message: "{message}"', array('exception' => $exception, 'command' => '\'test:run\' --foo=baz buzz', 'message' => 'An error occurred'))
35+
->with('Exception thrown while running command "{command}". Message: "{message}"', array('exception' => $exception, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred'))
3536
;
3637

37-
$input = array(
38-
'name' => 'test:run',
39-
'--foo' => 'baz',
40-
'bar' => 'buzz'
41-
);
42-
43-
$listener->onKernelException($this->getConsoleExceptionEvent($exception, $input, 1));
38+
$listener = new ExceptionListener($logger);
39+
$listener->onConsoleException($this->getConsoleExceptionEvent($exception, new ArgvInput(array('console.php', 'test:run', '--foo=baz', 'buzz')), 1));
4440
}
4541

46-
public function testOnKernelTerminateForNonZeroExitCodeWritesToLog()
42+
public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog()
4743
{
4844
$logger = $this->getLogger();
49-
$listener = new ExceptionListener($logger);
50-
5145
$logger
5246
->expects($this->once())
5347
->method('error')
54-
->with('Command "{command}" exited with status code "{code}"', array('command' => '\'test:run\'', 'code' => 255))
48+
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255))
5549
;
5650

57-
$listener->onKernelTerminate($this->getConsoleTerminateEvent(array('name' => 'test:run'), 255));
51+
$listener = new ExceptionListener($logger);
52+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 255));
5853
}
5954

60-
public function testOnKernelTerminateForZeroExitCodeDoesNotWriteToLog()
55+
public function testOnConsoleTerminateForZeroExitCodeDoesNotWriteToLog()
6156
{
6257
$logger = $this->getLogger();
63-
$listener = new ExceptionListener($logger);
64-
6558
$logger
6659
->expects($this->never())
6760
->method('error')
6861
;
6962

70-
$listener->onKernelTerminate($this->getConsoleTerminateEvent(array('name' => 'test:run'), 0));
63+
$listener = new ExceptionListener($logger);
64+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 0));
7165
}
7266

7367
public function testGetSubscribedEvents()
7468
{
7569
$this->assertEquals(
7670
array(
77-
'console.exception' => array('onKernelException', -128),
78-
'console.terminate' => array('onKernelTerminate', -128),
71+
'console.exception' => array('onConsoleException', -128),
72+
'console.terminate' => array('onConsoleTerminate', -128),
7973
),
8074
ExceptionListener::getSubscribedEvents()
8175
);
8276
}
8377

78+
public function testAllKindsOfInputCanBeLogged()
79+
{
80+
$logger = $this->getLogger();
81+
$logger
82+
->expects($this->exactly(3))
83+
->method('error')
84+
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run --foo=bar', 'code' => 255))
85+
;
86+
87+
$listener = new ExceptionListener($logger);
88+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run', '--foo=bar')), 255));
89+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArrayInput(array('name' => 'test:run', '--foo' => 'bar')), 255));
90+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent(new StringInput('test:run --foo=bar'), 255));
91+
}
92+
93+
public function testCommandNameIsDisplayedForNonStringableInput()
94+
{
95+
$logger = $this->getLogger();
96+
$logger
97+
->expects($this->once())
98+
->method('error')
99+
->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255))
100+
;
101+
102+
$listener = new ExceptionListener($logger);
103+
$listener->onConsoleTerminate($this->getConsoleTerminateEvent($this->getMockBuilder(InputInterface::class)->getMock(), 255));
104+
}
105+
84106
private function getLogger()
85107
{
86108
return $this->getMockForAbstractClass(LoggerInterface::class);
87109
}
88110

89-
private function getConsoleExceptionEvent(\Exception $exception, $input, $exitCode)
111+
private function getConsoleExceptionEvent(\Exception $exception, InputInterface $input, $exitCode)
112+
{
113+
return new ConsoleExceptionEvent(new Command('test:run'), $input, $this->getOutput(), $exception, $exitCode);
114+
}
115+
116+
private function getConsoleTerminateEvent(InputInterface $input, $exitCode)
90117
{
91-
return new ConsoleExceptionEvent(new Command('test:run'), new ArrayInput($input), new TestOutput(), $exception, $exitCode);
118+
return new ConsoleTerminateEvent(new Command('test:run'), $input, $this->getOutput(), $exitCode);
92119
}
93120

94-
private function getConsoleTerminateEvent($input, $exitCode)
121+
private function getOutput()
95122
{
96-
return new ConsoleTerminateEvent(new Command('test:run'), new ArrayInput($input), new TestOutput(), $exitCode);
123+
return $this->getMockBuilder(OutputInterface::class)->getMock();
97124
}
98125
}

0 commit comments

Comments
 (0)