8000 [Console] Review console.ERROR related behavior · symfony/symfony@a7c67c9 · GitHub
[go: up one dir, main page]

Skip to content

Commit a7c67c9

Browse files
[Console] Review console.ERROR related behavior
1 parent b9ee33f commit a7c67c9

File tree

9 files changed

+114
-149
lines changed

9 files changed

+114
-149
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<services>
88

9-
<service id="console.exception_listener" class="Symfony\Component\Console\EventListener\ExceptionListener" public="false">
9+
<service id="console.error_listener" class="Symfony\Component\Console\EventListener\ErrorListener" public="false">
1010
<argument type="service" id="logger" on-invalid="null" />
1111
<tag name="kernel.event_subscriber" />
1212
<tag name="monolog.logger" channel="console" />

src/Symfony/Component/Console/Application.php

Lines changed: 58 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -119,46 +119,30 @@ public function run(InputInterface $input = null, OutputInterface $output = null
119119
$output = new ConsoleOutput();
120120
}
121121

122+
if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) {
123+
@trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED);
124+
}
125+
122126
$this->configureIO($input, $output);
123127

124128
try {
125129
$e = null;
126130
$exitCode = $this->doRun($input, $output);
127-
} catch (\Exception $e) {
128-
$exception = $e;
129-
} catch (\Throwable $e) {
130-
$exception = new FatalThrowableError($e);
131-
}
132-
133-
if (null !== $e && null !== $this->dispatcher) {
134-
$event = new ConsoleErrorEvent($input, $output, $e, $e->getCode(), $this->runningCommand);
135-
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
136-
137-
$e = $event->getError();
138-
139-
if ($event->isErrorHandled()) {
140-
$e = null;
141-
$exitCode = 0;
142-
} else {
143-
if (!$e instanceof \Exception) {
144-
throw $e;
145-
}
146-
$exitCode = $e->getCode();
147-
}
148-
149-
$event = new ConsoleTerminateEvent($this->runningCommand, $input, $output, $exitCode);
150-
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
131+
} catch (\Exception $x) {
132+
$e = $x;
133+
} catch (\Throwable $x) {
134+
$e = new FatalThrowableError($x);
151135
}
152136

153137
if (null !== $e) {
154138
if (!$this->catchExceptions) {
155-
throw $e;
139+
throw $x;
156140
}
157141

158142
if ($output instanceof ConsoleOutputInterface) {
159-
$this->renderException($exception, $output->getErrorOutput());
143+
$this->renderException($e, $output->getErrorOutput());
160144
} else {
161-
$this->renderException($exception, $output);
145+
$this->renderException($e, $output);
162146
}
163147

164148
$exitCode = $e->getCode();
@@ -214,8 +198,26 @@ public function doRun(InputInterface $input, OutputInterface $output)
214198
$input = new ArrayInput(array('command' => $this->defaultCommand));
215199
}
216200

217-
// the command name MUST be the first element of the input
218-
$command = $this->find($name);
201+
try {
202+
$e = $this->runningCommand = null;
203+
// the command name MUST be the first element of the input
204+
$command = $this->find($name);
205+
} catch (\Exception $e) {
206+
} catch (\Throwable $e) {
207+
}
208+
if (null !== $e) {
209+
if (null !== $this->dispatcher) {
210+
$event = new ConsoleErrorEvent($input, $output, $e);
211+
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
212+
$e = $event->getError();
213+
214+
if (0 === $event->getExitCode()) {
215+
return 0;
216+
}
217+
}
218+
219+
throw $e;
220+
}
219221

220222
$this->runningCommand = $command;
221223
$exitCode = $this->doRunCommand($command, $input, $output);
@@ -864,13 +866,7 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
864866
}
865867

866868
if (null === $this->dispatcher) {
867-
try {
868-
return $command->run($input, $output);
869-
} catch (\Exception $e) {
870-
throw $e;
871-
} catch (\Throwable $e) {
872-
throw new FatalThrowableError($e);
873-
}
869+
return $command->run($input, $output);
874870
}
875871

876872
// bind before the console.command event, so the listeners have access to input options/arguments
@@ -882,37 +878,45 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
882878
}
883879

884880
$event = new ConsoleCommandEvent($command, $input, $output);
885-
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
886881

887-
if ($event->commandShouldRun()) {
888-
try {
889-
$e = null;
882+
try {
883+
$e = null;
884+
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
885+
886+
if ($event->commandShouldRun()) {
890887
$exitCode = $command->run($input, $output);
891-
} catch (\Exception $x) {
892-
$e = $x;
893-
} catch (\Throwable $x) {
894-
$e = new FatalThrowableError($x);
888+
} else {
889+
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
895890
}
896-
897-
if (null !== $e) {
898-
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode(), false);
891+
} catch (\Exception $e) {
892+
} catch (\Throwable $e) {
893+
}
894+
if (null !== $e) {
895+
if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) {
896+
$x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
897+
$event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
899898
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
900899

901-
if ($e !== $event->getException()) {
902-
@trigger_error('The "console.exception" event is deprecated since version 3.3 and will be removed in 4.0. Use the "console.error" event instead.', E_USER_DEPRECATED);
903-
904-
$x = $e = $event->getException();
900+
if ($x !== $event->getException()) {
901+
$e = $event->getException();
905902
}
903+
}
904+
$event = new ConsoleErrorEvent($input, $output, $e, $command);
905+
$this->dispatcher->dispatch(ConsoleEvents::ERROR, $event);
906+
$e = $event->getError();
906907

907-
throw $x;
908+
if (0 === $exitCode = $event->getExitCode()) {
909+
$e = null;
908910
}
909-
} else {
910-
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
911911
}
912912

913913
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
914914
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
915915

916+
if (null !== $e) {
917+
throw $e;
918+
}
919+
916920
return $event->getExitCode();
917921
}
918922

src/Symfony/Component/Console/ConsoleEvents.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ final class ConsoleEvents
5555
const EXCEPTION = 'console.exception';
5656

5757
/**
58-
* The ERROR event occurs when an uncaught exception appears or
59-
* a throwable error.
58+
* The ERROR event occurs when an uncaught exception or error appears.
6059
*
6160
* This event allows you to deal with the exception/error or
6261
* to modify the thrown exception.

src/Symfony/Component/Console/Event/ConsoleErrorEvent.php

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,22 @@
1515
use Symfony\Component\Console\Exception\InvalidArgumentException;
1616
use Symfony\Component\Console\Input\InputInterface;
1717
use Symfony\Component\Console\Output\OutputInterface;
18-
use Symfony\Component\Debug\Exception\FatalThrowableError;
1918

2019
/**
2120
* Allows to handle throwables thrown while running a command.
2221
*
2322
* @author Wouter de Jong <wouter@wouterj.nl>
2423
*/
25-
class ConsoleErrorEvent extends ConsoleExceptionEvent
24+
final class ConsoleErrorEvent extends ConsoleEvent
2625
{
2726
private $error;
28-
private $handled = false;
27+
private $exitCode;
2928

30-
public function __construct(InputInterface $input, OutputInterface $output, $error, $exitCode, Command $command = null)
29+
public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null)
3130
{
32-
if (!$error instanceof \Throwable && !$error instanceof \Exception) {
33-
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)));
34-
}
35-
36-
$exception = $error;
37-
if (!$error instanceof \Exception) {
38-
$exception = new FatalThrowableError($error);
39-
}
40-
parent::__construct($command, $input, $output, $exception, $exitCode, false);
31+
parent::__construct($command, $input, $output);
4132

42-
$this->error = $error;
33+
$this->setError($error);
4334
}
4435

4536
/**
@@ -67,46 +58,26 @@ public function setError($error)
6758
}
6859

6960
/**
70-
* Marks the error/exception as handled.
71-
*
72-
* If it is not marked as handled, the error/exception will be displayed in
73-
* the command output.
74-
*/
75-
public function markErrorAsHandled()
76-
{
77-
$this->handled = true;
78-
}
79-
80-
/**
81-
* Whether the error/exception is handled by a listener or not.
82-
*
83-
* If it is not yet handled, the error/exception will be displayed in the
84-
* command output.
61+
* Sets the exit code.
8562
*
86-
* @return bool
87-
*/
88-
public function isErrorHandled()
89-
{
90-
return $this->handled;
91-
}
92-
93-
/**
94-
* @deprecated Since version 3.3, to be removed in 4.0. Use getError() instead
63+
* @param int $exitCode The command exit code
9564
*/
96-
public function getException()
65+
public function setExitCode($exitCode)
9766
{
98-
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use ConsoleErrorEvent::getError() instead.', __METHOD__), E_USER_DEPRECATED);
67+
$this->exitCode = (int) $exitCode;
9968

100-
return parent::getException();
69+
$r = new \ReflectionProperty($this->error, 'code');
70+
$r->setAccessible(true);
71+
$r->setValue($this->error, $this->exitCode);
10172
}
10273

10374
/**
104-
* @deprecated Since version 3.3, to be removed in 4.0. Use setError() instead
75+
* Gets the exit code.
76+
*
77+
* @return int The command exit code
10578
*/
106-
public function setException(\Exception $exception)
79+
public function getExitCode()
10780
{
108-
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use ConsoleErrorEvent::setError() instead.', __METHOD__), E_USER_DEPRECATED);
109-
110-
parent::setException($exception);
81+
return null !== $this->exitCode ? $this->exitCode : ($this->error->getCode() ?: 1);
11182
}
11283
}

src/Symfony/Component/Console/Event/ConsoleExceptionEvent.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Console\Event;
1313

14+
@trigger_error(sprintf('The "%s" class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED);
15+
1416
use Symfony\Component\Console\Command\Command;
1517
use Symfony\Component\Console\Input\InputInterface;
1618
use Symfony\Component\Console\Output\OutputInterface;
@@ -20,22 +22,18 @@
2022
*
2123
* @author Fabien Potencier <fabien@symfony.com>
2224
*
23-
* @deprecated ConsoleExceptionEvent is deprecated since version 3.3 and will be removed in 4.0. Use ConsoleErrorEvent instead.
25+
* @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead.
2426
*/
2527
class ConsoleExceptionEvent extends ConsoleEvent
2628
{
2729
private $exception;
2830
private $exitCode;
2931

30-
public function __construct(Command $command = null, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode, $deprecation = true)
32+
public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
3133
{
32-
if ($deprecation) {
33-
@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);
34-
}
35-
3634
parent::__construct($command, $input, $output);
3735

38-
$this->exception = $exception;
36+
$this->setException($exception);
3937
$this->exitCode = (int) $exitCode;
4038
}
4139

src/Symfony/Component/Console/Event/ConsoleTerminateEvent.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ConsoleTerminateEvent extends ConsoleEvent
2929
*/
3030
private $exitCode;
3131

32-
public function __construct(Command $command = null, InputInterface $input, OutputInterface $output, $exitCode)
32+
public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
3333
{
3434
parent::__construct($command, $input, $output);
3535

src/Symfony/Component/Console/EventListener/ExceptionListener.php renamed to src/Symfony/Component/Console/EventListener/ErrorListener.php

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

1414
use Psr\Log\LoggerInterface;
15-
use Symfony\Component\Console\Event\ConsoleEvent;
1615
use Symfony\Component\Console\ConsoleEvents;
1716
use Symfony\Component\Console\Event\ConsoleErrorEvent;
17+
use Symfony\Component\Console\Event\ConsoleEvent;
1818
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
1919
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
2020

2121
/**
2222
* @author James Halsall <james.t.halsall@googlemail.com>
2323
* @author Robin Chalas <robin.chalas@gmail.com>
2424
*/
25-
class ExceptionListener implements EventSubscriberInterface
25+
class ErrorListener implements EventSubscriberInterface
2626
{
2727
private $logger;
2828

0 commit comments

Comments
 (0)
0