Skip to content

Commit a5d09c3

Browse files
committed
feature #9235 [Console] Skip commands from ConsoleCommandEvent (tPl0ch)
This PR was merged into the 2.6-dev branch. Discussion ---------- [Console] Skip commands from ConsoleCommandEvent Use case: We have different variations of the same application, for which only certain commands are allowed. Right now this is done in a custom Application class, but it would be much easier to just be able to skip commands from a listener, where you can disable commands via the Event object. This patch provides this feature and corresponding test cases. | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes - for Console tests | Fixed tickets | None | License | MIT | Doc PR | symfony/symfony-docs#4058 Commits ------- acb1ae6 [Console] Skip commands from ConsoleCommandEvent
2 parents 1bbbcdc + eba9c95 commit a5d09c3

File tree

3 files changed

+80
-13
lines changed

3 files changed

+80
-13
lines changed

Application.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -894,16 +894,20 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
894894
$event = new ConsoleCommandEvent($command, $input, $output);
895895
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
896896

897-
try {
898-
$exitCode = $command->run($input, $output);
899-
} catch (\Exception $e) {
900-
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
901-
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
897+
if ($event->commandShouldRun()) {
898+
try {
899+
$exitCode = $command->run($input, $output);
900+
} catch (\Exception $e) {
901+
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
902+
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
902903

903-
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
904-
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
904+
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
905+
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
905906

906-
throw $event->getException();
907+
throw $event->getException();
908+
}
909+
} else {
910+
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
907911
}
908912

909913
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);

Event/ConsoleCommandEvent.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,51 @@
1212
namespace Symfony\Component\Console\Event;
1313

1414
/**
15-
* Allows to do things before the command is executed.
15+
* Allows to do things before the command is executed, like skipping the command or changing the input.
1616
*
1717
* @author Fabien Potencier <[email protected]>
1818
*/
1919
class ConsoleCommandEvent extends ConsoleEvent
2020
{
21+
/**
22+
* The return code for skipped commands, this will also be passed into the terminate event
23+
*/
24+
const RETURN_CODE_DISABLED = 113;
25+
26+
/**
27+
* Indicates if the command should be run or skipped
28+
*
29+
* @var bool
30+
*/
31+
private $commandShouldRun = true;
32+
33+
/**
34+
* Disables the command, so it won't be run
35+
*
36+
* @return bool
37+
*/
38+
public function disableCommand()
39+
{
40+
return $this->commandShouldRun = false;
41+
}
42+
43+
/**
44+
* Enables the command
45+
*
46+
* @return bool
47+
*/
48+
public function enableCommand()
49+
{
50+
return $this->commandShouldRun = true;
51+
}
52+
53+
/**
54+
* Returns true if the command is runnable, false otherwise
55+
*
56+
* @return bool
57+
*/
58+
public function commandShouldRun()
59+
{
60+
return $this->commandShouldRun;
61+
}
2162
}

Tests/ApplicationTest.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,22 @@ public function testRunDispatchesAllEventsWithException()
891891
$this->assertContains('before.foo.after.caught.', $tester->getDisplay());
892892
}
893893

894+
public function testRunWithDispatcherSkippingCommand()
895+
{
896+
$application = new Application();
897+
$application->setDispatcher($this->getDispatcher(true));
898+
$application->setAutoExit(false);
899+
900+
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
901+
$output->write('foo.');
902+
});
903+
904+
$tester = new ApplicationTester($application);
905+
$exitCode = $tester->run(array('command' => 'foo'));
906+
$this->assertContains('before.after.', $tester->getDisplay());
907+
$this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode);
908+
}
909+
894910
public function testTerminalDimensions()
895911
{
896912
$application = new Application();
@@ -906,16 +922,22 @@ public function testTerminalDimensions()
906922
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
907923
}
908924

909-
protected function getDispatcher()
925+
protected function getDispatcher($skipCommand = false)
910926
{
911927
$dispatcher = new EventDispatcher();
912-
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
928+
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
913929
$event->getOutput()->write('before.');
930+
931+
if ($skipCommand) {
932+
$event->disableCommand();
933+
}
914934
});
915-
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) {
935+
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
916936
$event->getOutput()->write('after.');
917937

918-
$event->setExitCode(128);
938+
if (!$skipCommand) {
939+
$event->setExitCode(113);
940+
}
919941
});
920942
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
921943
$event->getOutput()->writeln('caught.');

0 commit comments

Comments
 (0)