[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 | None
This commit is contained in:
parent
bf140a8487
commit
acb1ae6616
@ -892,6 +892,7 @@ class Application
|
|||||||
$event = new ConsoleCommandEvent($command, $input, $output);
|
$event = new ConsoleCommandEvent($command, $input, $output);
|
||||||
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
|
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
|
||||||
|
|
||||||
|
if ($event->commandShouldRun()) {
|
||||||
try {
|
try {
|
||||||
$exitCode = $command->run($input, $output);
|
$exitCode = $command->run($input, $output);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -903,6 +904,9 @@ class Application
|
|||||||
|
|
||||||
throw $event->getException();
|
throw $event->getException();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
|
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
|
||||||
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
|
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
|
||||||
|
@ -12,10 +12,51 @@
|
|||||||
namespace Symfony\Component\Console\Event;
|
namespace Symfony\Component\Console\Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to do things before the command is executed.
|
* Allows to do things before the command is executed, like skipping the command or changing the input.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
class ConsoleCommandEvent extends ConsoleEvent
|
class ConsoleCommandEvent extends ConsoleEvent
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The return code for skipped commands, this will also be passed into the terminate event
|
||||||
|
*/
|
||||||
|
const RETURN_CODE_DISABLED = 113;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the command should be run or skipped
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $commandShouldRun = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the command, so it won't be run
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function disableCommand()
|
||||||
|
{
|
||||||
|
return $this->commandShouldRun = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the command
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function enableCommand()
|
||||||
|
{
|
||||||
|
return $this->commandShouldRun = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the command is runnable, false otherwise
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function commandShouldRun()
|
||||||
|
{
|
||||||
|
return $this->commandShouldRun;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -891,6 +891,22 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertContains('before.foo.after.caught.', $tester->getDisplay());
|
$this->assertContains('before.foo.after.caught.', $tester->getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRunWithDispatcherSkippingCommand()
|
||||||
|
{
|
||||||
|
$application = new Application();
|
||||||
|
$application->setDispatcher($this->getDispatcher(true));
|
||||||
|
$application->setAutoExit(false);
|
||||||
|
|
||||||
|
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
|
||||||
|
$output->write('foo.');
|
||||||
|
});
|
||||||
|
|
||||||
|
$tester = new ApplicationTester($application);
|
||||||
|
$exitCode = $tester->run(array('command' => 'foo'));
|
||||||
|
$this->assertContains('before.after.', $tester->getDisplay());
|
||||||
|
$this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
public function testTerminalDimensions()
|
public function testTerminalDimensions()
|
||||||
{
|
{
|
||||||
$application = new Application();
|
$application = new Application();
|
||||||
@ -906,16 +922,22 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
|
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDispatcher()
|
protected function getDispatcher($skipCommand = false)
|
||||||
{
|
{
|
||||||
$dispatcher = new EventDispatcher();
|
$dispatcher = new EventDispatcher();
|
||||||
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
|
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
|
||||||
$event->getOutput()->write('before.');
|
$event->getOutput()->write('before.');
|
||||||
|
|
||||||
|
if ($skipCommand) {
|
||||||
|
$event->disableCommand();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) {
|
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
|
||||||
$event->getOutput()->write('after.');
|
$event->getOutput()->write('after.');
|
||||||
|
|
||||||
$event->setExitCode(128);
|
if (!$skipCommand) {
|
||||||
|
$event->setExitCode(113);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
|
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
|
||||||
$event->getOutput()->writeln('caught.');
|
$event->getOutput()->writeln('caught.');
|
||||||
|
Reference in New Issue
Block a user