bug #23909 [Console] Initialize lazily to render exceptions properly (nicolas-grekas)

This PR was merged into the 2.7 branch.

Discussion
----------

[Console] Initialize lazily to render exceptions properly

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

When an exception occurs in the constructor of an `Application`, exception handling is not yet set up.
This typically happens when the container cannot be build for some reason, where calling `$this->add()` builds the container and fails.

This PR makes initialization lazy so that it happens later on, when exception handling might be OK.

Before:
![before](https://user-images.githubusercontent.com/243674/29403397-7f7a1fce-8338-11e7-8e62-b6302ff0a65e.png)

After:
![after](https://user-images.githubusercontent.com/243674/29403403-83f7b5c0-8338-11e7-9a22-0c5ee702f1ff.png)

Commits
-------

62174fd [Console] Initialize lazily to render exceptions properly
This commit is contained in:
Robin Chalas 2017-08-17 13:45:57 +02:00
commit d22d924c3b
1 changed files with 35 additions and 9 deletions

View File

@ -72,6 +72,7 @@ class Application
private $dispatcher;
private $terminalDimensions;
private $defaultCommand;
private $initialized;
/**
* Constructor.
@ -84,12 +85,6 @@ class Application
$this->name = $name;
$this->version = $version;
$this->defaultCommand = 'list';
$this->helperSet = $this->getDefaultHelperSet();
$this->definition = $this->getDefaultInputDefinition();
foreach ($this->getDefaultCommands() as $command) {
$this->add($command);
}
}
public function setDispatcher(EventDispatcherInterface $dispatcher)
@ -189,10 +184,11 @@ class Application
if (!$name) {
$name = $this->defaultCommand;
$this->definition->setArguments(array_merge(
$this->definition->getArguments(),
$definition = $this->getDefinition();
$definition->setArguments(array_merge(
$definition->getArguments(),
array(
'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
)
));
}
@ -225,6 +221,10 @@ class Application
*/
public function getHelperSet()
{
if (!$this->helperSet) {
$this->helperSet = $this->getDefaultHelperSet();
}
return $this->helperSet;
}
@ -245,6 +245,10 @@ class Application
*/
public function getDefinition()
{
if (!$this->definition) {
$this->definition = $this->getDefaultInputDefinition();
}
return $this->definition;
}
@ -374,6 +378,8 @@ class Application
*/
public function add(Command $command)
{
$this->init();
$command->setApplication($this);
if (!$command->isEnabled()) {
@ -406,6 +412,8 @@ class Application
*/
public function get($name)
{
$this->init();
if (!isset($this->commands[$name])) {
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
}
@ -433,6 +441,8 @@ class Application
*/
public function has($name)
{
$this->init();
return isset($this->commands[$name]);
}
@ -510,6 +520,8 @@ class Application
*/
public function find($name)
{
$this->init();
$allCommands = array_keys($this->commands);
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
$commands = preg_grep('{^'.$expr.'}', $allCommands);
@ -565,6 +577,8 @@ class Application
*/
public function all($namespace = null)
{
$this->init();
if (null === $namespace) {
return $this->commands;
}
@ -1151,4 +1165,16 @@ class Application
return $namespaces;
}
private function init()
{
if ($this->initialized) {
return;
}
$this->initialized = true;
foreach ($this->getDefaultCommands() as $command) {
$this->add($command);
}
}
}