Permalink
Browse files

refactored the implementation of how a console application can handle…

… events
  • Loading branch information...
1 parent 4edf29d commit 4f9a55a03a1442487a26dbcb84c3dcfbffef8141 @fabpot fabpot committed Mar 24, 2013
@@ -4,7 +4,6 @@ CHANGELOG
2.3.0
-----
- * added an init and terminate event dispatched by CLI commands
* added `--clean` option the the `translation:update` command
* added `http_method_override` option
@@ -11,7 +11,6 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -24,10 +23,8 @@
* @author Francis Besset <francis.besset@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
*/
-class CacheClearCommand extends Command
+class CacheClearCommand extends ContainerAwareCommand
{
- private $container;
-
/**
* {@inheritdoc}
*/
@@ -200,16 +197,4 @@ public function getRootDir()
return new $class($parent->getEnvironment(), $parent->isDebug());
}
-
- /**
- * @return ContainerInterface
- */
- protected function getContainer()
- {
- if (null === $this->container) {
- $this->container = $this->getApplication()->getKernel()->getContainer();
- }
-
- return $this->container;
- }
}
@@ -11,12 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
-use Symfony\Bundle\FrameworkBundle\Console\ConsoleEvents;
-use Symfony\Bundle\FrameworkBundle\Event\ConsoleEvent;
-use Symfony\Bundle\FrameworkBundle\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@@ -33,27 +28,6 @@
private $container;
/**
- * {@inheritdoc}
- */
- public function run(InputInterface $input, OutputInterface $output)
- {
- $dispatcher = $this->getContainer()->get('event_dispatcher');
- $helperSet = $this->getHelperSet();
-
- $initEvent = new ConsoleEvent($input, $output);
- $initEvent->setHelperSet($helperSet);
- $dispatcher->dispatch(ConsoleEvents::INIT, $initEvent);
-
- $exitCode = parent::run($input, $output);
-
- $terminateEvent = new ConsoleTerminateEvent($input, $output, $exitCode);
- $terminateEvent->setHelperSet($helperSet);
- $dispatcher->dispatch(ConsoleEvents::TERMINATE, $terminateEvent);
-
- return $exitCode;
- }
-
- /**
* @return ContainerInterface
*/
protected function getContainer()
@@ -1,43 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Console;
-
-/**
- * Contains all events thrown during Console commands execution
- *
- * @author Francesco Levorato <git@flevour.net>
- */
-final class ConsoleEvents
-{
- /**
- * The INIT event allows you to attach listeners before any command is
- * executed by the console. It also allows you to modify the input and output
- * before they are handled to the command.
- *
- * The event listener method receives a \Symfony\Bundle\FrameworkBundle\Event\ConsoleEvent
- * instance.
- *
- * @var string
- */
- const INIT = 'console.init';
-
- /**
- * The TERMINATE event allows you to attach listeners after a command is
- * executed by the console.
- *
- * The event listener method receives a \Symfony\Bundle\FrameworkBundle\Event\ConsoleTerminateEvent
- * instance.
- *
- * @var string
- */
- const TERMINATE = 'console.terminate';
-}
@@ -12,9 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Console;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
-use Symfony\Bundle\FrameworkBundle\Tests\Console\Fixtures\FooCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
-use Symfony\Bundle\FrameworkBundle\Console\ConsoleEvents;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
@@ -24,7 +22,7 @@ public function testBundleInterfaceImplementation()
{
$bundle = $this->getMock("Symfony\Component\HttpKernel\Bundle\BundleInterface");
- $kernel = $this->getKernel(array($bundle), $this->never());
+ $kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
$application->doRun(new ArrayInput(array('list')), new NullOutput());
@@ -35,66 +33,20 @@ public function testBundleCommandsAreRegistered()
$bundle = $this->getMock("Symfony\Component\HttpKernel\Bundle\Bundle");
$bundle->expects($this->once())->method('registerCommands');
- $kernel = $this->getKernel(array($bundle), $this->never());
+ $kernel = $this->getKernel(array($bundle));
$application = new Application($kernel);
$application->doRun(new ArrayInput(array('list')), new NullOutput());
}
- public function testCommandDispatchEvents()
- {
- $kernel = $this->getKernel(array(), $this->once());
-
- $application = new Application($kernel);
- $application->add(new FooCommand('foo'));
-
- $application->doRun(new ArrayInput(array('foo')), new NullOutput());
- }
-
- private function getKernel(array $bundles, $dispatcherExpected = null)
+ private function getKernel(array $bundles)
{
$kernel = $this->getMock("Symfony\Component\HttpKernel\KernelInterface");
$kernel
->expects($this->any())
->method('getBundles')
->will($this->returnValue($bundles))
;
-
- $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
-
- $dispatcherExpected = $dispatcherExpected ?: $this->any();
- if ($this->never() == $dispatcherExpected) {
- $container
- ->expects($dispatcherExpected)
- ->method('get');
- } else {
- $eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
- $eventDispatcher
- ->expects($this->at(0))
- ->method('dispatch')
- ->with(
- $this->equalTo(ConsoleEvents::INIT),
- $this->isInstanceOf('Symfony\Bundle\FrameworkBundle\Event\ConsoleEvent')
- );
- $eventDispatcher
- ->expects($this->at(1))
- ->method('dispatch')
- ->with(
- $this->equalTo(ConsoleEvents::TERMINATE),
- $this->isInstanceOf('Symfony\Bundle\FrameworkBundle\Event\ConsoleTerminateEvent')
- );
- $container
- ->expects($dispatcherExpected)
- ->method('get')
- ->with($this->equalTo('event_dispatcher'))
- ->will($this->returnValue($eventDispatcher));
- }
-
- $kernel
- ->expects($this->any())
- ->method('getContainer')
- ->will($this->returnValue($container))
- ;
return $kernel;
}
@@ -27,6 +27,10 @@
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\ProgressHelper;
+use Symfony\Component\Console\Event\ConsoleCommandEvent;
+use Symfony\Component\Console\Event\ConsoleForExceptionEvent;
+use Symfony\Component\Console\Event\ConsoleTerminateEvent;
+use Symfony\Component\EventDispatcher\EventDispatcher;
/**
* An Application is the container for a collection of commands.
@@ -56,6 +60,7 @@ class Application
private $autoExit;
private $definition;
private $helperSet;
+ private $dispatcher;
/**
* Constructor.
@@ -80,6 +85,11 @@ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
}
}
+ public function setDispatcher(EventDispatcher $dispatcher)
+ {
+ $this->dispatcher = $dispatcher;
+ }
+
/**
* Runs the current application.
*
@@ -103,7 +113,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null
}
try {
- $statusCode = $this->doRun($input, $output);
+ $exitCode = $this->doRun($input, $output);
} catch (\Exception $e) {
if (!$this->catchExceptions) {
throw $e;
@@ -114,21 +124,21 @@ public function run(InputInterface $input = null, OutputInterface $output = null
} else {
$this->renderException($e, $output);
}
- $statusCode = $e->getCode();
+ $exitCode = $e->getCode();
- $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
+ $exitCode = is_numeric($exitCode) && $exitCode ? $exitCode : 1;
}
if ($this->autoExit) {
- if ($statusCode > 255) {
- $statusCode = 255;
+ if ($exitCode > 255) {
+ $exitCode = 255;
}
// @codeCoverageIgnoreStart
- exit($statusCode);
+ exit($exitCode);
// @codeCoverageIgnoreEnd
}
- return $statusCode;
+ return $exitCode;
}
/**
@@ -190,10 +200,10 @@ public function doRun(InputInterface $input, OutputInterface $output)
$command = $this->find($name);
$this->runningCommand = $command;
- $statusCode = $command->run($input, $output);
+ $exitCode = $this->doRunCommand($command, $input, $output);
$this->runningCommand = null;
- return is_numeric($statusCode) ? $statusCode : 0;
+ return is_numeric($exitCode) ? $exitCode : 0;
}
/**
@@ -912,6 +922,45 @@ public function getTerminalDimensions()
}
/**
+ * Runs the current command.
+ *
+ * If an event dispatcher has been attached to the application,
+ * events are also dispatched during the life-cycle of the command.
+ *
+ * @param Command $command A Command instance
+ * @param InputInterface $input An Input instance
+ * @param OutputInterface $output An Output instance
+ *
+ * @return integer 0 if everything went fine, or an error code
+ */
+ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
+ {
+ if (null === $this->dispatcher) {
+ return $command->run($input, $output);
+ }
+
+ $event = new ConsoleCommandEvent($command, $input, $output);
+ $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
+
+ try {
+ $exitCode = $command->run($input, $output);
+ } catch (\Exception $e) {
+ $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
+ $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
+
+ $event = new ConsoleForExceptionEvent($command, $input, $output, $e, $event->getExitCode());
+ $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
+
+ throw $event->getException();
+ }
+
+ $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
+ $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
+
+ return $event->getExitCode();
+ }
+
+ /**
* Gets the name of the command based on input.
*
* @param InputInterface $input The input interface
@@ -4,6 +4,7 @@ CHANGELOG
2.3.0
-----
+ * added support for events in `Application`
* added a way to set the progress bar progress via the `setCurrent` method
2.2.0
Oops, something went wrong.

0 comments on commit 4f9a55a

Please sign in to comment.