8000 [Console] Fix dispatching throwables from ConsoleEvents::COMMAND · symfony/symfony@8823232 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8823232

Browse files
[Console] Fix dispatching throwables from ConsoleEvents::COMMAND
1 parent 5742958 commit 8823232

File tree

2 files changed

+86
-64
lines changed

2 files changed

+86
-64
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,17 @@ public function run(InputInterface $input = null, OutputInterface $output = null
117117
$this->configureIO($input, $output);
118118

119119
try {
120+
$e = null;
120121
$exitCode = $this->doRun($input, $output);
121-
} catch (\Exception $e) {
122+
} catch (\Exception $x) {
123+
$e = $x;
124+
} catch (\Throwable $x) {
125+
$e = new FatalThrowableError($x);
126+
}
127+
128+
if (null !== $e) {
122129
if (!$this->catchExceptions) {
123-
throw $e;
130+
throw $x;
124131
}
125132

126133
if ($output instanceof ConsoleOutputInterface) {
@@ -182,6 +189,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
182189
$input = new ArrayInput(array('command' => $this->defaultCommand));
183190
}
184191

192+
$this->runningCommand = null;
185193
// the command name MUST be the first element of the input
186194
$command = $this->find($name);
187195

@@ -839,47 +847,42 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
839847
}
840848

841849
if (null === $this->dispatcher) {
842-
try {
843-
return $command->run($input, $output);
844-
} catch (\Exception $e) {
845-
throw $e;
846-
} catch (\Throwable $e) {
847-
throw new FatalThrowableError($e);
848-
}
850+
return $command->run($input, $output);
849851
}
850852

851853
$event = new ConsoleCommandEvent($command, $input, $output);
852-
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
854+
$e = null;
853855

854-
if ($event->commandShouldRun()) {
855-
try {
856-
$e = null;
856+
try {
857+
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
858+
859+
if ($event->commandShouldRun()) {
857860
$exitCode = $command->run($input, $output);
858-
} catch (\Exception $x) {
859-
$e = $x;
860-
} catch (\Throwable $x) {
861-
$e = new FatalThrowableError($x);
861+
} else {
862+
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
862863
}
863-
if (null !== $e) {
864-
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
865-
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
866-
867-
if ($e !== $event->getException()) {
868-
$x = $e = $event->getException();
869-
}
870-
871-
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
872-
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
864+
} catch (\Exception $x) {
865+
$e = $x;
866+
} catch (\Throwable $x) {
867+
$e = new FatalThrowableError($x);
868+
}
869+
if (null !== $e) {
870+
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
871+
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
873872

874-
throw $x;
873+
if ($e !== $event->getException()) {
874+
$x = $e = $event->getException();
875875
}
876-
} else {
877-
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
876+
$exitCode = $e->getCode();
878877
}
879878

880879
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
881880
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
882881

882+
if (null !== $e) {
883+
throw $x;
884+
}
885+
883886
return $event->getExitCode();
884887
}
885888

src/Symfony/Component/Console/Tests/ApplicationTest.php

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -977,15 +977,28 @@ public function testRunDispatchesAllEventsWithException()
977977
$this->assertContains('before.foo.caught.after.', $tester->getDisplay());
978978
}
979979

980-
public function testRunWithError()
980+
public function testRunDispatchesAllEventsWithExceptionInListener()
981981
{
982-
if (method_exists($this, 'expectException')) {
983-
$this->expectException('Exception');
984-
$this->expectExceptionMessage('dymerr');
985-
} else {
986-
$this->setExpectedException('Exception', 'dymerr');
987-
}
982+
$dispatcher = $this->getDispatcher();
983+
$dispatcher->addListener('console.command', function () {
984+
throw new \RuntimeException('foo');
985+
});
986+
987+
$application = new Application();
988+
$application->setDispatcher($dispatcher);
989+
$application->setAutoExit(false);
988990

991+
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
992+
$output->write('foo.');
993+
});
994+
995+
$tester = new ApplicationTester($application);
996+
$tester->run(array('command' => 'foo'));
997+
$this->assertContains('before.caught.after.', $tester->getDisplay());
998+
}
999+
1000+
public function testRunWithError()
1001+
{
9891002
$application = new Application();
9901003
$application->setAutoExit(false);
9911004
$application->setCatchExceptions(false);
@@ -997,7 +1010,13 @@ public function testRunWithError()
9971010
});
9981011

9991012
$tester = new ApplicationTester($application);
1000-
$tester->run(array('command' => 'dym'));
1013+
1014+
try {
1015+
$tester->run(array('command' => 'dym'));
1016+
$this->fail('Error expected.');
1017+
} catch (\Error $e) {
1018+
$this->assertSame('dymerr', $e->getMessage());
1019+
}
10011020
}
10021021

10031022
/**
@@ -1087,32 +1106,6 @@ public function testTerminalDimensions()
10871106
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
10881107
}
10891108

1090-
protected function getDispatcher($skipCommand = false)
1091-
{
1092-
$dispatcher = new EventDispatcher();
1093-
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
1094-
$event->getOutput()->write('before.');
1095-
1096-
if ($skipCommand) {
1097-
$event->disableCommand();
1098-
}
1099-
});
1100-
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
1101-
$event->getOutput()->writeln('after.');
1102-
1103-
if (!$skipCommand) {
1104-
$event->setExitCode(113);
1105-
}
1106-
});
1107-
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
1108-
$event->getOutput()->write('caught.');
1109-
1110-
$event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
1111-
});
1112-
1113-
return $dispatcher;
1114-
}
1115-
11161109
public function testSetRunCustomDefaultCommand()
11171110
{
11181111
$command = new \FooCommand();
@@ -1151,6 +1144,32 @@ public function testCanCheckIfTerminalIsInteractive()
11511144
$inputStream = $application->getHelperSet()->get('question')->getInputStream();
11521145
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
11531146
}
1147+
1148+
protected function getDispatcher($skipCommand = false)
1149+
{
1150+
$dispatcher = new EventDispatcher();
1151+
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
1152+
$event->getOutput()->write('before.');
1153+
1154+
if ($skipCommand) {
1155+
$event->disableCommand();
1156+
}
1157+
});
1158+
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
1159+
$event->getOutput()->writeln('after.');
1160+
1161+
if (!$skipCommand) {
1162+
$event->setExitCode(113);
1163+
}
1164+
});
1165+
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
1166+
$event->getOutput()->write('caught.');
1167+
1168+
$event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
1169+
});
1170+
1171+
return $dispatcher;
1172+
}
11541173
}
11551174

11561175
class CustomApplication extends Application

0 commit comments

Comments
 (0)
0