Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f224102

Browse files
flevourfabpot
authored andcommitted
Added events for CLI commands
This adds an init and terminate event for commands. They are dispatched from ContainerAwareCommand. The cache:clear command can't implement this (cf. #3889 on Github).
1 parent ddd30d0 commit f224102

File tree

9 files changed

+282
-4
lines changed

9 files changed

+282
-4
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
2.3.0
55
-----
66

7+
* added an init and terminate event dispatched by CLI commands
78
* added `--clean` option the the `translation:update` command
89
* added `http_method_override` option
910

src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

14+
use Symfony\Component\Console\Command\Command;
1415
use Symfony\Component\Console\Input\InputInterface;
1516
use Symfony\Component\Console\Input\InputOption;
1617
use Symfony\Component\Console\Output\OutputInterface;
@@ -23,8 +24,10 @@
2324
* @author Francis Besset <[email protected]>
2425
* @author Fabien Potencier <[email protected]>
2526
*/
26-
class CacheClearCommand extends ContainerAwareCommand
27+
class CacheClearCommand extends Command
2728
{
29+
private $container;
30+
2831
/**
2932
* {@inheritdoc}
3033
*/
@@ -197,4 +200,16 @@ public function getRootDir()
197200

198201
return new $class($parent->getEnvironment(), $parent->isDebug());
199202
}
203+
204+
/**
205+
* @return ContainerInterface
206+
*/
207+
protected function getContainer()
208+
{
209+
if (null === $this->container) {
210+
$this->container = $this->getApplication()->getKernel()->getContainer();
211+
}
212+
213+
return $this->container;
214+
}
200215
}

src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

14+
use Symfony\Bundle\FrameworkBundle\Console\ConsoleEvents;
15+
use Symfony\Bundle\FrameworkBundle\Event\ConsoleEvent;
16+
use Symfony\Bundle\FrameworkBundle\Event\ConsoleTerminateEvent;
1417
use Symfony\Component\Console\Command\Command;
18+
use Symfony\Component\Console\Input\InputInterface;
19+
use Symfony\Component\Console\Output\OutputInterface;
1520
use Symfony\Component\DependencyInjection\ContainerInterface;
1621
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
1722

@@ -27,6 +32,24 @@ abstract class ContainerAwareCommand extends Command implements ContainerAwareIn
2732
*/
2833
private $container;
2934

35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function run(InputInterface $input, OutputInterface $output)
39+
{
40+
$dispatcher = $this->getContainer()->get('event_dispatcher');
41+
42+
$initEvent = new ConsoleEvent($input, $output);
43+
$dispatcher->dispatch(ConsoleEvents::INIT, $initEvent);
44+
45+
$exitCode = parent::run($input, $output);
46+
47+
$terminateEvent = new ConsoleTerminateEvent($input, $output, $exitCode);
48+
$dispatcher->dispatch(ConsoleEvents::TERMINATE, $terminateEvent);
49+
50+
return $exitCode;
51+
}
52+
3053
/**
3154
* @return ContainerInterface
3255
*/
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Console;
13+
14+
/**
15+
* Contains all events thrown during Console commands execution
16+
*
17+
* @author Francesco Levorato <[email protected]>
18+
*/
19+
final class ConsoleEvents
20+
{
21+
/**
22+
* The INIT event allows you to attach listeners before any command is
23+
* executed by the console. It also allows you to modify the input and output
24+
* before they are handled to the command.
25+
*
26+
* The event listener method receives a \Symfony\Bundle\FrameworkBundle\Event\ConsoleEvent
27+
* instance.
28+
*
29+
* @var string
30+
*/
31+
const INIT = 'console.init';
32+
33+
/**
34+
* The TERMINATE event allows you to attach listeners after a command is
35+
* executed by the console.
36+
*
37+
* The event listener method receives a \Symfony\Bundle\FrameworkBundle\Event\ConsoleTerminateEvent
38+
* instance.
39+
*
40+
* @var string
41+
*/
42+
const TERMINATE = 'console.terminate';
43+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Event;
13+
14+
use Symfony\Component\Console\Input\InputInterface;
15+
use Symfony\Component\Console\Output\OutputInterface;
16+
use Symfony\Component\EventDispatcher\Event;
17+
18+
/**
19+
* Allows to inspect input and output of a command.
20+
*
21+
* @author Francesco Levorato <[email protected]>
22+
*/
23+
class ConsoleEvent extends Event
24+
{
25+
private $input;
26+
27+
private $output;
28+
29+
public function __construct(InputInterface $input, OutputInterface $output)
30+
{
31+
$this->input = $input;
32+
$this->output = $output;
33+
}
34+
35+
/**
36+
* Returns the input object
37+
*
38+
* @return InputInterface
39+
*/
40+
public function getInput()
41+
{
42+
return $this->input;
43+
}
44+
45+
/**
46+
* Returns the output object
47+
*
48+
* @return OutputInterface
49+
*/
50+
public function getOutput()
51+
{
52+
return $this->output;
53+
}
54+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Event;
13+
14+
use Symfony\Component\Console\Input\InputInterface;
15+
use Symfony\Component\Console\Output\OutputInterface;
16+
17+
/**
18+
* Allows to receive the exit code of a command after its execution.
19+
*
20+
* @author Francesco Levorato <[email protected]>
21+
*/
22+
class ConsoleTerminateEvent extends ConsoleEvent
23+
{
24+
/**
25+
* The exit code of the command.
26+
*
27+
* @var integer
28+
*/
29+
private $exitCode;
30+
31+
public function __construct(InputInterface $input, OutputInterface $output, $exitCode)
32+
{
33+
parent::__construct($input, $output);
34+
$this->exitCode = $exitCode;
35+
}
36+
37+
/**
38+
* Returns the exit code.
39+
*
40+
* @return integer
41+
*/
42+
public function getExitCode()
43+
{
44+
return $this->exitCode;
45+
}
46+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Console;
1313

1414
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\Tests\Console\Fixtures\FooCommand;
16+
use Symfony\Bundle\FrameworkBundle\Tests\Console\Fixtures\SilentCommand;
1517
use Symfony\Bundle\FrameworkBundle\Console\Application;
1618
use Symfony\Component\Console\Input\ArrayInput;
1719
use Symfony\Component\Console\Output\NullOutput;
@@ -22,7 +24,7 @@ public function testBundleInterfaceImplementation()
2224
{
2325
$bundle = $this->getMock("Symfony\Component\HttpKernel\Bundle\BundleInterface");
2426

25-
$kernel = $this->getKernel(array($bundle));
27+
$kernel = $this->getKernel(array($bundle), $this->never());
2628

2729
$application = new Application($kernel);
2830
$application->doRun(new ArrayInput(array('list')), new NullOutput());
@@ -33,20 +35,65 @@ public function testBundleCommandsAreRegistered()
3335
$bundle = $this->getMock("Symfony\Component\HttpKernel\Bundle\Bundle");
3436
$bundle->expects($this->once())->method('registerCommands');
3537

36-
$kernel = $this->getKernel(array($bundle));
38+
$kernel = $this->getKernel(array($bundle), $this->never());
3739

3840
$application = new Application($kernel);
3941
$application->doRun(new ArrayInput(array('list')), new NullOutput());
4042
}
4143

42-
private function getKernel(array $bundles)
44+
public function testCommandDispatchEvents()
45+
{
46+
$kernel = $this->getKernel(array(), $this->once());
47+
48+
$application = new Application($kernel);
49+
$application->add(new FooCommand('foo'));
50+
51+
$application->doRun(new ArrayInput(array('foo')), new NullOutput());
52+
}
53+
54+
public function testSilentCommand()
55+
{
56+
$kernel = $this->getKernel(array(), $this->never());
57+
58+
$application = new Application($kernel);
59+
$application->add(new SilentCommand('chut'));
60+
61+
$application->doRun(new ArrayInput(array('chut')), new NullOutput());
62+
}
63+
64+
private function getKernel(array $bundles, $dispatcherExpected = null)
4365
{
4466
$kernel = $this->getMock("Symfony\Component\HttpKernel\KernelInterface");
4567
$kernel
4668
->expects($this->any())
4769
->method('getBundles')
4870
->will($this->returnValue($bundles))
4971
;
72+
73+
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
74+
75+
$dispatcherExpected = $dispatcherExpected ?: $this->any();
76+
if ($this->never() == $dispatcherExpected) {
77+
$container
78+
->expects($dispatcherExpected)
79+
->method('get');
80+
} else {
81+
$eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
82+
$eventDispatcher
83+
->expects($this->atLeastOnce())
84+
->method('dispatch');
85+
$container
86+
->expects($dispatcherExpected)
87+
->method('get')
88+
->with($this->equalTo('event_dispatcher'))
89+
->will($this->returnValue($eventDispatcher));
90+
}
91+
92+
$kernel
93+
->expects($this->any())
94+
->method('getContainer')
95+
->will($this->returnValue($container))
96+
;
5097

5198
return $kernel;
5299
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Fixtures;
13+
14+
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
17+
18+
class FooCommand extends ContainerAwareCommand
19+
{
20+
protected function execute(InputInterface $input, OutputInterface $output)
21+
{
22+
return 0;
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Fixtures;
13+
14+
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Output\OutputInterface;
18+
19+
class SilentCommand extends Command
20+
{
21+
protected function execute(InputInterface $input, OutputInterface $output)
22+
{
23+
return 0;
24+
}
25+
}

0 commit comments

Comments
 (0)