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

Skip to content

Commit 9fa9fc7

Browse files
author
Robin Chalas
committed
Add support for command lazy-loading
1 parent 66ead2e commit 9fa9fc7

File tree

17 files changed

+449
-48
lines changed

17 files changed

+449
-48
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ CHANGELOG
1818
`Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead
1919
* Deprecated `TranslatorPass`, use
2020
`Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead
21+
* Added `command` attribute to the `console.command` tag which takes the command
22+
name as value, using it makes the command lazy
2123

2224
3.3.0
2325
-----

src/Symfony/Bundle/FrameworkBundle/Console/Application.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
6868
{
6969
$this->kernel->boot();
7070

71-
$container = $this->kernel->getContainer();
72-
73-
foreach ($this->all() as $command) {
74-
if ($command instanceof ContainerAwareInterface) {
75-
$command->setContainer($container);
76-
}
77-
}
78-
79-
$this->setDispatcher($container->get('event_dispatcher'));
71+
$this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher'));
8072

8173
return parent::doRun($input, $output);
8274
}
@@ -98,7 +90,13 @@ public function get($name)
9890
{
9991
$this->registerCommands();
10092

101-
return parent::get($name);
93+
$command = parent::get($name);
94+
95+
if ($command instanceof ContainerAwareInterface) {
96+
$command->setContainer($this->kernel->getContainer());
97+
}
98+
99+
return $command;
102100
}
103101

104102
/**
@@ -144,9 +142,15 @@ protected function registerCommands()
144142
}
145143
}
146144

145+
if ($container->has('console.command_loader')) {
146+
$this->setCommandLoader($container->get('console.command_loader'));
147+
}
148+
147149
if ($container->hasParameter('console.command.ids')) {
148150
foreach ($container->getParameter('console.command.ids') as $id) {
149-
$this->add($container->get($id));
151+
if (false !== $id) {
152+
$this->add($container->get($id));
153+
}
150154
}
151155
}
152156
}

src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,15 @@ private function getKernel()
7777

7878
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
7979
$container
80-
->expects($this->once())
80+
->expects($this->atLeastOnce())
8181
->method('has')
82-
->with('router')
83-
->will($this->returnValue(true))
82+
->will($this->returnCallback(function ($id) {
83+
if ('console.command_loader' === $id) {
84+
return false;
85+
}
86+
87+
return true;
88+
}))
8489
;
8590
$container
8691
->expects($this->any())

src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,14 @@ private function getKernel()
7878
$container
7979
->expects($this->atLeastOnce())
8080
->method('has')
81-
->with('router')
82-
->will($this->returnValue(true));
81+
->will($this->returnCallback(function ($id) {
82+
if ('console.command_loader' === $id) {
83+
return false;
84+
}
85+
86+
return true;
87+
}))
88+
;
8389
$container
8490
->expects($this->any())
8591
->method('get')

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"fig/link-util": "^1.0",
3636
"symfony/asset": "~3.3|~4.0",
3737
"symfony/browser-kit": "~2.8|~3.0|~4.0",
38-
"symfony/console": "~3.3|~4.0",
38+
"symfony/console": "~3.4|~4.0",
3939
"symfony/css-selector": "~2.8|~3.0|~4.0",
4040
"symfony/dom-crawler": "~2.8|~3.0|~4.0",
4141
"symfony/polyfill-intl-icu": "~1.0",
@@ -64,7 +64,7 @@
6464
"phpdocumentor/type-resolver": "<0.2.0",
6565
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
6666
"symfony/asset": "<3.3",
67-
"symfony/console": "<3.3",
67+
"symfony/console": "<3.4",
6868
"symfony/form": "<3.3",
6969
"symfony/property-info": "<3.3",
7070
"symfony/serializer": "<3.3",

src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<service id="security.console.user_password_encoder_command" class="Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand">
1111
<argument type="service" id="security.encoder_factory"/>
1212
<argument type="collection" /> <!-- encoders' user classes -->
13-
<tag name="console.command" />
13+
<tag name="console.command" command="security:encode-password" />
1414
</service>
1515
</services>
1616
</container>

src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,21 @@
1010
<service id="web_server.command.server_run" class="Symfony\Bundle\WebServerBundle\Command\ServerRunCommand">
1111
<argument>%kernel.project_dir%/web</argument>
1212
<argument>%kernel.environment%</argument>
13-
<tag name="console.command" />
13+
<tag name="console.command" command="server:run" />
1414
</service>
1515

1616
<service id="web_server.command.server_start" class="Symfony\Bundle\WebServerBundle\Command\ServerStartCommand">
1717
<argument>%kernel.project_dir%/web</argument>
1818
<argument>%kernel.environment%</argument>
19-
<tag name="console.command" />
19+
<tag name="console.command" command="server:start" />
2020
</service>
2121

2222
<service id="web_server.command.server_stop" class="Symfony\Bundle\WebServerBundle\Command\ServerStopCommand">
23-
<tag name="console.command" />
23+
<tag name="console.command" command="server:stop" />
2424
</service>
2525

2626
<service id="web_server.command.server_status" class="Symfony\Bundle\WebServerBundle\Command\ServerStatusCommand">
27-
<tag name="console.command" />
27+
<tag name="console.command" command="server:status" />
2828
</service>
2929
</services>
3030
</container>

src/Symfony/Component/Console/Application.php

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Console;
1313

14+
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
1415
use Symfony\Component\Console\Exception\ExceptionInterface;
1516
use Symfony\Component\Console\Formatter\OutputFormatter;
1617
use Symfony\Component\Console\Helper\DebugFormatterHelper;
@@ -64,6 +65,7 @@ class Application
6465
private $runningCommand;
6566
private $name;
6667
private $version;
68+
private $commandLoader;
6769
private $catchExceptions = true;
6870
private $autoExit = true;
6971
private $definition;
@@ -96,6 +98,11 @@ public function setDispatcher(EventDispatcherInterface $dispatcher)
9698
$this->dispatcher = $dispatcher;
9799
}
98100

101+
public function setCommandLoader(CommandLoaderInterface $commandLoader)
102+
{
103+
$this->commandLoader = $commandLoader;
104+
}
105+
99106
/**
100107
* Runs the current application.
101108
*
@@ -431,6 +438,10 @@ public function add(Command $command)
431438
throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
432439
}
433440

441+
if (!$command->getName()) {
442+
throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command)));
443+
}
444+
434445
$this->commands[$command->getName()] = $command;
435446

436447
foreach ($command->getAliases() as $alias) {
@@ -451,12 +462,16 @@ public function add(Command $command)
451462
*/
452463
public function get($name)
453464
{
454-
if (!isset($this->commands[$name])) {
465+
if (isset($this->commands[$name])) {
466+
$command = $this->commands[$name];
467+
} elseif ($this->commandLoader && $this->commandLoader->has($name)) {
468+
$command = $this->commandLoader->get($name);
469+
$command->setName($name);
470+
$this->add($command);
471+
} else {
455472
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
456473
}
457474

458-
$command = $this->commands[$name];
459-
460475
if ($this->wantHelps) {
461476
$this->wantHelps = false;
462477

@@ -478,7 +493,7 @@ public function get($name)
478493
*/
479494
public function has($name)
480495
{
481-
return isset($this->commands[$name]);
496+
return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name));
482497
}
483498

484499
/**
@@ -555,7 +570,7 @@ public function findNamespace($namespace)
555570
*/
556571
public function find($name)
557572
{
558-
$allCommands = array_keys($this->commands);
573+
$allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
559574
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
560575
$commands = preg_grep('{^'.$expr.'}', $allCommands);
561576

@@ -581,12 +596,12 @@ public function find($name)
581596

582597
// filter out aliases for commands which are already on the list
583598
if (count($commands) > 1) {
584-
$commandList = $this->commands;
585-
$commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
586-
$commandName = $commandList[$nameOrAlias]->getName();
599+
$commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
600+
$commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
601+
$commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
587602

588603
return $commandName === $nameOrAlias || !in_array($commandName, $commands);
589-
});
604+
}));
590605
}
591606

592607
$exact = in_array($name, $commands, true);
@@ -598,6 +613,9 @@ public function find($name)
598613
$maxLen = max(Helper::strlen($abbrev), $maxLen);
599614
}
600615
$abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) {
616+
if (!$commandList[$cmd] instanceof Command) {
617+
return $cmd;
618+
}
601619
$abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();
602620

603621
return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
@@ -622,7 +640,18 @@ public function find($name)
622640
public function all($namespace = null)
623641
{
624642
if (null === $namespace) {
625-
return $this->commands;
643+
if (!$this->commandLoader) {
644+
return $this->commands;
645+
}
646+
647+
$commands = $this->commands;
648+
foreach ($this->commandLoader->getNames() as $name) {
649+
if (!isset($commands[$name])) {
650+
$commands[$name] = $this->commandLoader->get($name);
651+
}
652+
}
653+
654+
return $commands;
626655
}
627656

628657
$commands = array();
@@ -632,6 +661,14 @@ public function all($namespace = null)
632661
}
633662
}
634663

664+
if ($this->commandLoader) {
665+
foreach ($this->commandLoader->getNames() as $name) {
666+
if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
667+
$commands[$name] = $this->commandLoader->get($name);
668+
}
669+
}
670+
}
671+
635672
return $commands;
636673
}
637674

src/Symfony/Component/Console/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.4.0
5+
-----
6+
7+
* added `CommandLoaderInterface` and PSR-11 `ContainerCommandLoader`
8+
49
3.3.0
510
-----
611

src/Symfony/Component/Console/Command/Command.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ public function __construct($name = null)
6161
}
6262

6363
$this->configure();
64-
65-
if (!$this->name) {
66-
throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
67-
}
6864
}
6965

7066
/**
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Symfony\Component\Console\CommandLoader;
4+
5+
use Symfony\Component\Console\Command\Command;
6+
use Symfony\Component\Console\Exception\CommandNotFoundException;
7+
8+
/**
9+
* @author Robin Chalas <[email protected]>
10+
*/
11+
interface CommandLoaderInterface
12+
{
13+
/**
14+
* Loads a command.
15+
*
16+
* @param string $name
17+
*
18+
* @return Command
19+
*
20+
* @throws CommandNotFoundException
21+
*/
22+
public function get($name);
23+
24+
/**
25+
* Checks if a command exists.
26+
*
27+
* @param string $name
28+
*
29+
* @return bool
30+
*/
31+
public function has($name);
32+
33+
/**
34+
* @return iterable All registered commands mapped by names
35+
*/
36+
public function all();
37+
38+
/**
39+
* @return string[] All registered command names
40+
*/
41+
public function getNames();
42+
}

0 commit comments

Comments
 (0)