-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Console] Add console.ERROR event and deprecate console.EXCEPTION #18140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
*/ | ||
public function setException(\Exception $exception) | ||
public function setException(\Exception $exception = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly speaking, this is a BC break. But only the public API is important for event classes, so I don't think we should consider this a BC break.
$this->renderException($e, $output->getErrorOutput()); | ||
} else { | ||
$this->renderException($e, $output); | ||
$e = $event->getException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize that you want a listener to ERROR to be able to "handle" the exception so that things don't continue. To do this, the listener will call $event->setException(null)
, which just looks like a weird way to do it.
Perhaps a $event->setExceptionAsHandled()
or something to signal that the Application shouldn't continue and render the exception? It would also simplify the $exitCode
code below, since there will be an exception still.
@wouterj Are you able to address the comments here? |
c0dbc95
to
741c752
Compare
Updated this PR:
|
Fabbot.io failures should be ignored, this is a bug in the CS fixer config |
*/ | ||
public function getException() | ||
{ | ||
@trigger_error('The ConsoleExceptionEvent::'.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use ConsoleErrorEvent::getError() instead.', E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use sprintf
and __METHOD__
already contains the namespace.
@@ -19,17 +19,24 @@ | |||
* Allows to handle exception thrown in a command. | |||
* | |||
* @author Fabien Potencier <[email protected]> | |||
* | |||
* @deprecated ConsoleExceptionEvent is deprecated since version 3.2 and will be removed in 4.0. Use ConsoleErrorEvent instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since 3.3
{ | ||
if ($deprecation) { | ||
@trigger_error('The '.__CLASS__.' class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sprintf
Thanks for the quick review. PR is now updated (also added related UPGRADE and CHANGELOG notes). |
UPGRADE-3.3.md
Outdated
Console | ||
------- | ||
|
||
* The `console.exception` event and related `ConsoleExceptionEvent` class have been deprecated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] and the related [...]
UPGRADE-3.3.md
Outdated
------- | ||
|
||
* The `console.exception` event and related `ConsoleExceptionEvent` class have been deprecated | ||
in favor of the `console.error` event and `ConsoleErrorEvent` class. The deprecated event and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] and the ConsoleErrorEvent
[...]
UPGRADE-4.0.md
Outdated
@@ -13,6 +13,9 @@ Console | |||
* Setting unknown style options is not supported anymore and throws an | |||
exception. | |||
|
|||
* The `console.exception` event and related `ConsoleExceptionEvent` class have |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] and the related [...]
UPGRADE-4.0.md
Outdated
@@ -13,6 +13,9 @@ Console | |||
* Setting unknown style options is not supported anymore and throws an | |||
exception. | |||
|
|||
* The `console.exception` event and related `ConsoleExceptionEvent` class have | |||
been removed in favor of the `console.error` event and `ConsoleErrorEvent` class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] and the ConsoleErrorEvent
[...]
@@ -38,7 +38,7 @@ public function __construct(Command $command, InputInterface $input, OutputInter | |||
/** | |||
* Gets the command that is executed. | |||
* | |||
* @return Command A Command instance | |||
* @return Command|null A Command instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, this is a BC break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah see #18140 (comment) :
Strictly speaking, this is a BC break. But only the public API is important for event classes, so I don't think we should consider this a BC break.
Yeah, but this only happends on the new console.error event. All other events behave the same.
Updated the PR. Should be ready to merge now (finally). |
8be9f16
to
d25f8e4
Compare
* a Symfony\Component\Console\Event\ConsoleExceptionEvent | ||
* instance. | ||
* | ||
* @Event |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent")
* | ||
* This event allows you to deal with the exception/error or | ||
* to modify the thrown exception. The event listener method receives | ||
* a Symfony\Component\Console\Event\ConsoleExceptionEvent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment can be removed if you fix the @Event
annotation (see below).
* If it is not marked as handled, the error/exception will be displayed in | ||
* the command output. | ||
*/ | ||
public function markErrorAsHandled() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having this marker, can't we just set the error as null to signify that error handling is done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it that way before, but @weaverryan suggested to use a marker:
I realize that you want a listener to ERROR to be able to "handle" the exception so that things don't continue. To do this, the listener will call $event->setException(null), which just looks like a weird way to do it.
Perhaps a $event->setExceptionAsHandled() or something to signal that the Application shouldn't continue and render the exception?
So, what's the decision here:
I'm getting a bit tired of rebasing my PRs each month, so I would like to have some quick decision making on this. Happy to close as well. |
Thank you @wouterj. |
…e.EXCEPTION (wouterj) This PR was merged into the 3.3-dev branch. Discussion ---------- [Console] Add console.ERROR event and deprecate console.EXCEPTION | Q | A | | --- | --- | | Branch | master | | Bug fix? | yes | | New feature? | yes | | BC breaks? | no | | Deprecations? | yes | | Tests pass? | yes | | Fixed tickets | - | | License | MIT | | Doc PR | todo | ## The Problem The current `console.EXCEPTION` event is only dispatched for exceptions during the execution of `Command#execute()`. All other exceptions (e.g. the ones thrown by listeners to events) are catched by the `try ... catch` loop in `Application#doRunCommand()`. This means that there is _no way to override exception handling_. ## The Solution This PR adds a `console.ERROR` event which has the same scope as the default `try ... catch` loop. This allows to customize all exception handling. In order to keep BC, a new event was created and `console.EXCEPTION` was deprecated. Commits ------- c02a4c9 Added a console.ERROR event
*/ | ||
class ConsoleExceptionEvent extends ConsoleEvent | ||
{ | ||
private $exception; | ||
private $exitCode; | ||
private $handled = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wouterj this prop doesn't seem to be used, should we remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, seems to be a left-over of the previous implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 2ad5923
} | ||
|
||
if (null !== $e && null !== $this->dispatcher) { | ||
$event = new ConsoleErrorEvent($this->runningCommand, $input, $output, $e, $e->getCode()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With everything on master, if you run: bin/console mldsqlkmldmksq
you got this:
Fatal error: Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Type error: Argument 1 passed to Symfony\Component\Console\Event\ConsoleErrorEvent::__construct() must be an instance of Symfony\Component\Console\Command\Command, null given, called in /home/greg/dev/github.com/lyrixx/symfony/src/Symfony/Component/Console/Application.php on line 131 in /home/greg/dev/github.com/lyrixx/symfony/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php:30
Stack trace:
#0 /home/greg/dev/github.com/lyrixx/symfony/src/Symfony/Component/Console/Application.php(131): Symfony\Component\Console\Event\ConsoleErrorEvent->__construct(NULL, Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput), Object(Symfony\Component\Console\Exception\CommandNotFoundException), 0)
#1 /home/greg/dev/github.com/lyrixx/symfony-standard/bin/console(28): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#2 {main}
thrown in /home/greg/dev/github.com/lyrixx/symfony/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php on line 30
It's weird nobody notice that. May be I'm missing something but I really doubt, because all my repository are clean.
- Do you experience this behaviour too?
- How to patch that ? I can do a PR, but I'm not sure about the how to solve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran into this yesterday, I believe the same occurs on 2.7 with ConsoleExceptionEvent. Not sure about the better approach to fix it yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My attempts to fix that: #22144
I believe the ability for the application to catch |
@renan it already does. What this PR provides is access to the original throwable (they are cast to FatalErrorException before), and dispatching for exceptions thrown when a command is found/not found. |
@nicolas-grekas Indeed I can't reproduce it with a minimalist script. Looks like there's a bad mix of PS: Sorry for the noise. |
…as-grekas) This PR was merged into the 3.3-dev branch. Discussion ---------- [Console] Review console.ERROR related behavior | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This PR is a follow up of #18140 that I wanted to do since a few weeks. It enhances this work with fixes and behavior changes. It embeds #22435 and resolves issues like the one described in #20808. - makes ConsoleErrorEvent *not* extend the deprecated ConsoleExceptionEvent - replace ConsoleErrorEvent::markErrorAsHandled by ConsoleErrorEvent::setExitCode - triggers the deprecation in a more appropriate moment - renames ExceptionListener to ErrorListener - tweaks the behavior in relation to #22435 Commits ------- a7c67c9 [Console] Review console.ERROR related behavior
The Problem
The current
console.EXCEPTION
event is only dispatched for exceptions during the execution ofCommand#execute()
. All other exceptions (e.g. the ones thrown by listeners to events) are catched by thetry ... catch
loop inApplication#doRunCommand()
. This means that there is no way to override exception handling.The Solution
This PR adds a
console.ERROR
event which has the same scope as the defaulttry ... catch
loop. This allows to customize all exception handling.In order to keep BC, a new event was created and
console.EXCEPTION
was deprecated.