Skip to content

Commit a45428c

Browse files
committed
feature #20054 [Console] Different approach on merging application definition (ro0NL)
This PR was merged into the 5.2-dev branch. Discussion ---------- [Console] Different approach on merging application definition | Q | A | | --- | --- | | Branch? | "master" | | Bug fix? | yes | | New feature? | not really (refactoring) | | BC breaks? | no | | Deprecations? | no | | Tests pass? | yes | | Fixed tickets | #19181, #17804, #19909, partially #20030 | | License | MIT | | Doc PR | reference to the documentation PR, if any | Before/After: ``` diff $ bin/console list -h Usage: list [options] [--] [<namespace>] Arguments: namespace The namespace name Options: --raw To output raw command list --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] + -h, --help Display this help message + -q, --quiet Do not output any message + -V, --version Display this application version + --ansi Force ANSI output + --no-ansi Disable ANSI output + -n, --no-interaction Do not ask any interactive question + -e, --env=ENV The environment name [default: "dev"] + --no-debug Switches off debug mode + -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Help: The list command lists all commands: php bin/console list You can also display the commands for a specific namespace: php bin/console list test You can also output the information in other formats by using the --format option: php bin/console list --format=xml It's also possible to get raw list of commands (useful for embedding command runner): php bin/console list --raw ``` This could deprecate `getNativeDefinition` or make it a feature as right now it's internal and unused. edit: resolved the BC break. edit2: question is.. should this target 2.7? Commits ------- 553b173 [Console] Different approach on merging application definition
2 parents acda2dc + 553b173 commit a45428c

17 files changed

+449
-58
lines changed

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

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ class Command
4545
private $hidden = false;
4646
private $help = '';
4747
private $description = '';
48+
private $fullDefinition;
4849
private $ignoreValidationErrors = false;
49-
private $applicationDefinitionMerged = false;
50-
private $applicationDefinitionMergedWithArgs = false;
5150
private $code;
5251
private $synopsis = [];
5352
private $usages = [];
@@ -98,6 +97,8 @@ public function setApplication(Application $application = null)
9897
} else {
9998
$this->helperSet = null;
10099
}
100+
101+
$this->fullDefinition = null;
101102
}
102103

103104
public function setHelperSet(HelperSet $helperSet)
@@ -205,16 +206,12 @@ protected function initialize(InputInterface $input, OutputInterface $output)
205206
*/
206207
public function run(InputInterface $input, OutputInterface $output)
207208
{
208-
// force the creation of the synopsis before the merge with the app definition
209-
$this->getSynopsis(true);
210-
$this->getSynopsis(false);
211-
212209
// add the application arguments and options
213210
$this->mergeApplicationDefinition();
214211

215212
// bind the input against the command specific arguments/options
216213
try {
217-
$input->bind($this->definition);
214+
$input->bind($this->getDefinition());
218215
} catch (ExceptionInterface $e) {
219216
if (!$this->ignoreValidationErrors) {
220217
throw $e;
@@ -302,20 +299,19 @@ public function setCode(callable $code)
302299
*/
303300
public function mergeApplicationDefinition(bool $mergeArgs = true)
304301
{
305-
if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
302+
if (null === $this->application) {
306303
return;
307304
}
308305

309-
$this->definition->addOptions($this->application->getDefinition()->getOptions());
310-
311-
$this->applicationDefinitionMerged = true;
306+
$this->fullDefinition = new InputDefinition();
307+
$this->fullDefinition->setOptions($this->definition->getOptions());
308+
$this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
312309

313310
if ($mergeArgs) {
314-
$currentArguments = $this->definition->getArguments();
315-
$this->definition->setArguments($this->application->getDefinition()->getArguments());
316-
$this->definition->addArguments($currentArguments);
317-
318-
$this->applicationDefinitionMergedWithArgs = true;
311+
$this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
312+
$this->fullDefinition->addArguments($this->definition->getArguments());
313+
} else {
314+
$this->fullDefinition->setArguments($this->definition->getArguments());
319315
}
320316
}
321317

@@ -334,7 +330,7 @@ public function setDefinition($definition)
334330
$this->definition->setDefinition($definition);
335331
}
336332

337-
$this->applicationDefinitionMerged = false;
333+
$this->fullDefinition = null;
338334

339335
return $this;
340336
}
@@ -346,11 +342,7 @@ public function setDefinition($definition)
346342
*/
347343
public function getDefinition()
348344
{
349-
if (null === $this->definition) {
350-
throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
351-
}
352-
353-
return $this->definition;
345+
return $this->fullDefinition ?? $this->getNativeDefinition();
354346
}
355347

356348
/**
@@ -365,7 +357,11 @@ public function getDefinition()
365357
*/
366358
public function getNativeDefinition()
367359
{
368-
return $this->getDefinition();
360+
if (null === $this->definition) {
361+
throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
362+
}
363+
364+
return $this->definition;
369365
}
370366

371367
/**
@@ -381,6 +377,9 @@ public function getNativeDefinition()
381377
public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
382378
{
383379
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
380+
if (null !== $this->fullDefinition) {
381+
$this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default));
382+
}
384383

385384
return $this;
386385
}
@@ -399,6 +398,9 @@ public function addArgument(string $name, int $mode = null, string $description
399398
public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
400399
{
401400
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
401+
if (null !== $this->fullDefinition) {
402+
$this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
403+
}
402404

403405
return $this;
404406
}

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

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Component\Console\Helper\DescriptorHelper;
1515
use Symfony\Component\Console\Input\InputArgument;
16-
use Symfony\Component\Console\Input\InputDefinition;
1716
use Symfony\Component\Console\Input\InputInterface;
1817
use Symfony\Component\Console\Input\InputOption;
1918
use Symfony\Component\Console\Output\OutputInterface;
@@ -32,7 +31,11 @@ protected function configure()
3231
{
3332
$this
3433
->setName('list')
35-
->setDefinition($this->createDefinition())
34+
->setDefinition([
35+
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
36+
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
37+
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
38+
])
3639
->setDescription('Lists commands')
3740
->setHelp(<<<'EOF'
3841
The <info>%command.name%</info> command lists all commands:
@@ -55,14 +58,6 @@ protected function configure()
5558
;
5659
}
5760

58-
/**
59-
* {@inheritdoc}
60-
*/
61-
public function getNativeDefinition()
62-
{
63-
return $this->createDefinition();
64-
}
65-
6661
/**
6762
* {@inheritdoc}
6863
*/
@@ -77,13 +72,4 @@ protected function execute(InputInterface $input, OutputInterface $output)
7772

7873
return 0;
7974
}
80-
81-
private function createDefinition(): InputDefinition
82-
{
83-
return new InputDefinition([
84-
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
85-
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
86-
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
87-
]);
88-
}
8975
}

src/Symfony/Component/Console/Descriptor/JsonDescriptor.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,14 @@ private function getInputDefinitionData(InputDefinition $definition): array
141141

142142
private function getCommandData(Command $command): array
143143
{
144-
$command->getSynopsis();
145144
$command->mergeApplicationDefinition(false);
146145

147146
return [
148147
'name' => $command->getName(),
149148
'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()),
150149
'description' => $command->getDescription(),
151150
'help' => $command->getProcessedHelp(),
152-
'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
151+
'definition' => $this->getInputDefinitionData($command->getDefinition()),
153152
'hidden' => $command->isHidden(),
154153
];
155154
}

src/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ protected function describeInputDefinition(InputDefinition $definition, array $o
118118
*/
119119
protected function describeCommand(Command $command, array $options = [])
120120
{
121-
$command->getSynopsis();
122121
$command->mergeApplicationDefinition(false);
123122

124123
$this->write(
@@ -136,9 +135,10 @@ protected function describeCommand(Command $command, array $options = [])
136135
$this->write($help);
137136
}
138137

139-
if ($command->getNativeDefinition()) {
138+
$definition = $command->getDefinition();
139+
if ($definition->getOptions() || $definition->getArguments()) {
140140
$this->write("\n\n");
141-
$this->describeInputDefinition($command->getNativeDefinition());
141+
$this->describeInputDefinition($definition);
142142
}
143143
}
144144

src/Symfony/Component/Console/Descriptor/TextDescriptor.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ protected function describeInputDefinition(InputDefinition $definition, array $o
136136
*/
137137
protected function describeCommand(Command $command, array $options = [])
138138
{
139-
$command->getSynopsis(true);
140-
$command->getSynopsis(false);
141139
$command->mergeApplicationDefinition(false);
142140

143141
if ($description = $command->getDescription()) {
@@ -154,7 +152,7 @@ protected function describeCommand(Command $command, array $options = [])
154152
}
155153
$this->writeText("\n");
156154

157-
$definition = $command->getNativeDefinition();
155+
$definition = $command->getDefinition();
158156
if ($definition->getOptions() || $definition->getArguments()) {
159157
$this->writeText("\n");
160158
$this->describeInputDefinition($definition, $options);

src/Symfony/Component/Console/Descriptor/XmlDescriptor.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public function getCommandDocument(Command $command): \DOMDocument
4949
$dom = new \DOMDocument('1.0', 'UTF-8');
5050
$dom->appendChild($commandXML = $dom->createElement('command'));
5151

52-
$command->getSynopsis();
5352
$command->mergeApplicationDefinition(false);
5453

5554
$commandXML->setAttribute('id', $command->getName());
@@ -68,7 +67,7 @@ public function getCommandDocument(Command $command): \DOMDocument
6867
$commandXML->appendChild($helpXML = $dom->createElement('help'));
6968
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
7069

71-
$definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
70+
$definitionXML = $this->getInputDefinitionDocument($command->getDefinition());
7271
$this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
7372

7473
return $dom;

src/Symfony/Component/Console/Tests/ApplicationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,12 @@ public function testRun()
10091009
$tester->run(['command' => 'list', '-vvv' => true]);
10101010
$this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');
10111011

1012+
$tester->run(['command' => 'help', '--help' => true], ['decorated' => false]);
1013+
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run5.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed');
1014+
1015+
$tester->run(['command' => 'help', '-h' => true], ['decorated' => false]);
1016+
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run5.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed');
1017+
10121018
$application = new Application();
10131019
$application->setAutoExit(false);
10141020
$application->setCatchExceptions(false);

src/Symfony/Component/Console/Tests/Fixtures/application_1.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,69 @@
139139
"is_multiple": false,
140140
"description": "The output format (txt, xml, json, or md)",
141141
"default": "txt"
142+
},
143+
"help": {
144+
"name": "--help",
145+
"shortcut": "-h",
146+
"accept_value": false,
147+
"is_value_required": false,
148+
"is_multiple": false,
149+
"description": "Display this help message",
150+
"default": false
151+
},
152+
"quiet": {
153+
"name": "--quiet",
154+
"shortcut": "-q",
155+
"accept_value": false,
156+
"is_value_required": false,
157+
"is_multiple": false,
158+
"description": "Do not output any message",
159+
"default": false
160+
},
161+
"verbose": {
162+
"name": "--verbose",
163+
"shortcut": "-v|-vv|-vvv",
164+
"accept_value": false,
165+
"is_value_required": false,
166+
"is_multiple": false,
167+
"description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug",
168+
"default": false
169+
},
170+
"version": {
171+
"name": "--version",
172+
"shortcut": "-V",
173+
"accept_value": false,
174+
"is_value_required": false,
175+
"is_multiple": false,
176+
"description": "Display this application version",
177+
"default": false
178+
},
179+
"ansi": {
180+
"name": "--ansi",
181+
"shortcut": "",
182+
"accept_value": false,
183+
"is_value_required": false,
184+
"is_multiple": false,
185+
"description": "Force ANSI output",
186+
"default": false
187+
},
188+
"no-ansi": {
189+
"name": "--no-ansi",
190+
"shortcut": "",
191+
"accept_value": false,
192+
"is_value_required": false,
193+
"is_multiple": false,
194+
"description": "Disable ANSI output",
195+
"default": false
196+
},
197+
"no-interaction": {
198+
"name": "--no-interaction",
199+
"shortcut": "-n",
200+
"accept_value": false,
201+
"is_value_required": false,
202+
"is_multiple": false,
203+
"description": "Do not ask any interactive question",
204+
"default": false
142205
}
143206
}
144207
}

src/Symfony/Component/Console/Tests/Fixtures/application_1.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,66 @@ The output format (txt, xml, json, or md)
170170
* Is value required: yes
171171
* Is multiple: no
172172
* Default: `'txt'`
173+
174+
#### `--help|-h`
175+
176+
Display this help message
177+
178+
* Accept value: no
179+
* Is value required: no
180+
* Is multiple: no
181+
* Default: `false`
182+
183+
#### `--quiet|-q`
184+
185+
Do not output any message
186+
187+
* Accept value: no
188+
* Is value required: no
189+
* Is multiple: no
190+
* Default: `false`
191+
192+
#### `--verbose|-v|-vv|-vvv`
193+
194+
Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
195+
196+
* Accept value: no
197+
* Is value required: no
198+
* Is multiple: no
199+
* Default: `false`
200+
201+
#### `--version|-V`
202+
203+
Display this application version
204+
205+
* Accept value: no
206+
* Is value required: no
207+
* Is multiple: no
208+
* Default: `false`
209+
210+
#### `--ansi`
211+
212+
Force ANSI output
213+
214+
* Accept value: no
215+
* Is value required: no
216+
* Is multiple: no
217+
* Default: `false`
218+
219+
#### `--no-ansi`
220+
221+
Disable ANSI output
222+
223+
* Accept value: no
224+
* Is value required: no
225+
* Is multiple: no
226+
* Default: `false`
227+
228+
#### `--no-interaction|-n`
229+
230+
Do not ask any interactive question
231+
232+
* Accept value: no
233+
* Is value required: no
234+
* Is multiple: no
235+
* Default: `false`

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy