8000 merged branch jfsimon/console-descriptor (PR #7454) · symfony/symfony@61c56fc · GitHub
[go: up one dir, main page]

Skip to content

Commit 61c56fc

Browse files
committed
merged branch jfsimon/console-descriptor (PR #7454)
This PR was squashed before being merged into the master branch (closes #7454). Discussion ---------- [Console] application/command as text/xml/whatever decoupling This PR removes description generation from `Command`, `Application` and `InputDefinition` classes and delegate it to specialized descriptor classes, making it dead simple to add new output formats. **Maybe this could include other commands, like `router:debug` or `container:debug` (see #5740)?** - [x] Add a `DescriptorProvider` which uses `DescriptorInterface` objects to describe things. - [x] Add `txt` descriptors. - [x] Add `xml` descriptors. - [x] Add `json` descriptors. - [x] Add `md` descriptors. - [x] Remove obsolete methods. - [x] Repair tests. | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #6339 Commits ------- 51512e6 [Console] application/command as text/xml/whatever decoupling
2 parents bdc0734 + 51512e6 commit 61c56fc

File tree

89 files changed

+2729
-316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+2729
-316
lines changed

src/Symfony/Component/Console/Application.php

Lines changed: 14 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Console;
1313

14+
use Symfony\Component\Console\Descriptor\TextDescriptor;
15+
use Symfony\Component\Console\Descriptor\XmlDescriptor;
1416
use Symfony\Component\Console\Input\InputInterface;
1517
use Symfony\Component\Console\Input\ArgvInput;
1618
use Symfony\Component\Console\Input\ArrayInput;
@@ -687,47 +689,14 @@ public static function getAbbreviations($names)
687689
* @param boolean $raw Whether to return raw command list
688690
*
689691
* @return string A string representing the Application
692+
*
693+
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
690694
*/
691695
public function asText($namespace = null, $raw = false)
692696
{
693-
$commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
694-
695-
$width = 0;
696-
foreach ($commands as $command) {
697-
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
698-
}
699-
$width += 2;
700-
701-
if ($raw) {
702-
$messages = array();
703-
foreach ($this->sortCommands($commands) as $space => $commands) {
704-
foreach ($commands as $name => $command) {
705-
$messages[] = sprintf("%-${width}s %s", $name, $command->getDescription());
706-
}
707-
}
708-
709-
return implode(PHP_EOL, $messages);
710-
}
697+
$descriptor = new TextDescriptor();
711698

712-
$messages = array($this->getHelp(), '');
713-
if ($namespace) {
714-
$messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $namespace);
715-
} else {
716-
$messages[] = '<comment>Available commands:</comment>';
717-
}
718-
719-
// add commands by namespace
720-
foreach ($this->sortCommands($commands) as $space => $commands) {
721-
if (!$namespace && '_global' !== $space) {
722-
$messages[] = '<comment>'.$space.'</comment>';
723-
}
724-
725-
foreach ($commands as $name => $command) {
726-
$messages[] = sprintf(" <info>%-${width}s</info> %s", $name, $command->getDescription());
727-
}
728-
}
729-
730-
return implode(PHP_EOL, $messages);
699+
return $descriptor->describe($this, array('namespace' => $namespace, 'raw_text' => $raw));
731700
}
732701

733702
/**
@@ -736,52 +705,15 @@ public function asText($namespace = null, $raw = false)
736705
* @param string $namespace An optional namespace name
737706
* @param Boolean $asDom Whether to return a DOM or an XML string
738707
*
739-
* @return string|DOMDocument An XML string representing the Application
708+
* @return string|\DOMDocument An XML string representing the Application
709+
*
710+
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
740711
*/
741712
public function asXml($namespace = null, $asDom = false)
742713
{
743-
$commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands;
744-
745-
$dom = new \DOMDocument('1.0', 'UTF-8');
746-
$dom->formatOutput = true;
747-
$dom->appendChild($xml = $dom->createElement('symfony'));
748-
749-
$xml->appendChild($commandsXML = $dom->createElement('commands'));
750-
751-
if ($namespace) {
752-
$commandsXML->setAttribute('namespace', $namespace);
753-
} else {
754-
$namespacesXML = $dom->createElement('namespaces');
755-
$xml->appendChild($namespacesXML);
756-
}
757-
758-
// add commands by namespace
759-
foreach ($this->sortCommands($commands) as $space => $commands) {
760-
if (!$namespace) {
761-
$namespaceArrayXML = $dom->createElement('namespace');
762-
$namespacesXML->appendChild($namespaceArrayXML);
763-
$namespaceArrayXML->setAttribute('id', $space);
764-
}
765-
766-
foreach ($commands as $name => $command) {
767-
if ($name !== $command->getName()) {
768-
continue;
769-
}
770-
771-
if (!$namespace) {
772-
$commandXML = $dom->createElement('command');
773-
$namespaceArrayXML->appendChild($commandXML);
774-
$commandXML->appendChild($dom->createTextNode($name));
775-
}
776-
777-
$node = $command->asXml(true)->getElementsByTagName('command')->item(0);
778-
$node = $dom->importNode($node, true);
714+
$descriptor = new XmlDescriptor();
779715

780-
$commandsXML->appendChild($node);
781-
}
782-
}
783-
784-
return $asDom ? $dom : $dom->saveXml();
716+
return $descriptor->describe($this, array('namespace' => $namespace, 'as_dom' => $asDom));
785717
}
786718

787719
/**
@@ -1066,33 +998,6 @@ private function getConsoleMode()
1066998
}
1067999
}
10681000

1069-
/**
1070-
* Sorts commands in alphabetical order.
1071-
*
1072-
* @param array $commands An associative array of commands to sort
1073-
*
1074-
* @return array A sorted array of commands
1075-
*/
1076-
private function sortCommands($commands)
1077-
{
1078-
$namespacedCommands = array();
1079-
foreach ($commands as $name => $command) {
1080-
$key = $this->extractNamespace($name, 1);
1081-
if (!$key) {
1082-
$key = '_global';
1083-
}
1084-
1085-
$namespacedCommands[$key][$name] = $command;
1086-
}
1087-
ksort($namespacedCommands);
1088-
1089-
foreach ($namespacedCommands as &$commands) {
1090-
ksort($commands);
1091-
}
1092-
1093-
return $namespacedCommands;
1094-
}
1095-
10961001
/**
10971002
* Returns abbreviated suggestions in string format.
10981003
*
@@ -1108,12 +1013,14 @@ private function getAbbreviationSuggestions($abbrevs)
11081013
/**
11091014
* Returns the namespace part of the command name.
11101015
*
1016+
* This method is not part of public API and should not be used directly.
1017+
*
11111018
* @param string $name The full name of the command
11121019
* @param string $limit The maximum number of parts of the namespace
11131020
*
11141021
* @return string The namespace of the command
11151022
*/
1116-
private function extractNamespace($name, $limit = null)
1023+
public function extractNamespace($name, $limit = null)
11171024
{
11181025
$parts = explode(':', $name);
11191026
array_pop($parts);

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

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Console\Command;
1313

14+
use Symfony\Component\Console\Descriptor\TextDescriptor;
15+
use Symfony\Component\Console\Descriptor\XmlDescriptor;
1416
use Symfony\Component\Console\Input\InputDefinition;
1517
use Symfony\Component\Console\Input\InputOption;
1618
use Symfony\Component\Console\Input\InputArgument;
@@ -275,9 +277,11 @@ public function setCode($code)
275277
/**
276278
* Merges the application definition with the command definition.
277279
*
280+
* This method is not part of public API and should not be used directly.
281+
*
278282
* @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
279283
*/
280-
private function mergeApplicationDefinition($mergeArgs = true)
284+
public function mergeApplicationDefinition($mergeArgs = true)
281285
{
282286
if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
283287
return;
@@ -337,9 +341,11 @@ public function getDefinition()
337341
* Can be overridden to provide the original command representation when it would otherwise
338342
* be changed by merging with the application InputDefinition.
339343
*
344+
* This method is not part of public API and should not be used directly.
345+
*
340346
* @return InputDefinition An InputDefinition instance
341347
*/
342-
protected function getNativeDefinition()
348+
public function getNativeDefinition()
343349
{
344350
return $this->getDefinition();
345351
}
@@ -564,74 +570,30 @@ public function getHelper($name)
564570
* Returns a text representation of the command.
565571
*
566572
* @return string A string representing the command
573+
*
574+
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
567575
*/
568576
public function asText()
569577
{
570-
if ($this->application && !$this->applicationDefinitionMerged) {
571-
$this->getSynopsis();
572-
$this->mergeApplicationDefinition(false);
573-
}
574-
575-
$messages = array(
576-
10000 '<comment>Usage:</comment>',
577-
' '.$this->getSynopsis(),
578-
'',
579-
);
580-
581-
if ($this->getAliases()) {
582-
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
583-
}
584-
585-
$messages[] = $this->getNativeDefinition()->asText();
586-
587-
if ($help = $this->getProcessedHelp()) {
588-
$messages[] = '<comment>Help:</comment>';
589-
$messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
590-
}
578+
$descriptor = new TextDescriptor();
591579

592-
return implode("\n", $messages);
580+
return $descriptor->describe($this);
593581
}
594582

595583
/**
596584
* Returns an XML representation of the command.
597585
*
598586
* @param Boolean $asDom Whether to return a DOM or an XML string
599587
*
600-
* @return string|DOMDocument An XML string representing the command
588+
* @return string|\DOMDocument An XML string representing the command
589+
*
590+
* @deprecated Deprecated since version 2.3, to be removed in 3.0.
601591
*/
602592
public function asXml($asDom = false)
603593
{
604-
if ($this->application && !$this->applicationDefinitionMerged) {
605-
$this->getSynopsis();
606-
$this->mergeApplicationDefinition(false);
607-
}
608-
609-
$dom = new \DOMDocument('1.0', 'UTF-8');
610-
$dom->formatOutput = true;
611-
$dom->appendChild($commandXML = $dom->createElement('command'));
612-
$commandXML->setAttribute('id', $this->name);
613-
$commandXML->setAttribute('name', $this->name);
614-
615-
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
616-
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
617-
618-
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
619-
$descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getDescription())));
620-
621-
$commandXML->appendChild($helpXML = $dom->createElement('help'));
622-
$helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getProcessedHelp())));
623-
624-
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
625-
foreach ($this->getAliases() as $alias) {
626-
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
627-
$aliasXML->appendChild($dom->createTextNode($alias));
628-
}
629-
630-
$definition = $this->getNativeDefinition()->asXml(true);
631-
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
632-
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
594+
$descriptor = new XmlDescriptor();
633595

634-
return $asDom ? $dom : $dom->saveXml();
596+
return $descriptor->describe($this, array('as_dom' => $asDom));
635597
}
636598

637599
private function validateName($name)

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

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

1212
namespace Symfony\Component\Console\Command;
1313

14+
use Symfony\Component\Console\Helper\DescriptorHelper;
1415
use Symfony\Component\Console\Input\InputArgument;
1516
use Symfony\Component\Console\Input\InputOption;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Output\OutputInterface;
18-
use Symfony\Component\Console\Command\Command;
1919

2020
/**
2121
* HelpCommand displays the help for a given command.
@@ -38,16 +38,18 @@ protected function configure()
3838
->setDefinition(array(
3939
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
4040
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
41+
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats'),
42+
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
4143
))
4244
->setDescription('Displays help for a command')
4345
->setHelp(<<<EOF
4446
The <info>%command.name%</info> command displays help for a given command:
4547
4648
<info>php %command.full_name% list</info>
4749
48-
You can also output the help as XML by using the <comment>--xml</comment> option:
50+
You can also output the help in other formats by using the <comment>--format</comment> option:
4951
50-
<info>php %command.full_name% --xml list</info>
52+
<info>php %command.full_name% --format=xml list</info>
5153
5254
To display the list of available commands, please use the <info>list</info> command.
5355
EOF
@@ -75,11 +77,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
7577
}
7678

7779
if ($input->getOption('xml')) {
78-
$output->writeln($this->command->asXml(), OutputInterface::OUTPUT_RAW);
79-
} else {
80-
$output->writeln($this->command->asText());
80+
$input->setOption('format', 'xml');
8181
}
8282

83+
$helper = new DescriptorHelper();
84+
$helper->describe($output, $this->command, $input->getOption('format'), $input->getOption('raw'));
8385
$this->command = null;
8486
}
8587
}

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111

1212
namespace Symfony\Component\Console\Command;
1313

14+
use Symfony\Component\Console\Helper\DescriptorHelper;
1415
use Symfony\Component\Console\Input\InputArgument;
1516
use Symfony\Component\Console\Input\InputOption;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Output\OutputInterface;
18-
use Symfony\Component\Console\Command\Command;
1919
use Symfony\Component\Console\Input\InputDefinition;
2020

2121
/**
@@ -43,9 +43,9 @@ protected function configure()
4343
4444
<info>php %command.full_name% test</info>
4545
46-
You can also output the information as XML by using the <comment>--xml</comment> option:
46+
You can also output the information in other formats by using the <comment>--format</comment> option:
4747
48-
<info>php %command.full_name% --xml</info>
48+
<info>php %command.full_name% --format=xml</info>
4949
5050
It's also possible to get raw list of commands (useful for embedding command runner):
5151
@@ -58,7 +58,7 @@ protected function configure()
5858
/**
5959
* {@inheritdoc}
6060
*/
61-
protected function getNativeDefinition()
61+
public function getNativeDefinition()
6262
{
6363
return $this->createDefinition();
6464
}
@@ -69,18 +69,23 @@ protected function getNativeDefinition()
6969
protected function execute(InputInterface $input, OutputInterface $output)
7070
{
7171
if ($input->getOption('xml')) {
72-
$output->writeln($this->getApplication()->asXml($input->getArgument('namespace')), OutputInterface::OUTPUT_RAW);
73-
} else {
74-
$output->writeln($this->getApplication()->asText($input->getArgument('namespace'), $input->getOption('raw')));
72+
$input->setOption('format', 'xml');
7573
}
74+
75+
$helper = new DescriptorHelper();
76+
$helper->describe($output, $this->getApplication(), $input->getOption('format'), $input->getOption('raw'));
7677
}
7778

79+
/**
80+
* {@inheritdoc}
81+
*/
7882
private function createDefinition()
7983
{
8084
return new InputDefinition(array(
8185
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
82-
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
86+
new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
8387
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
88+
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats'),
8489
));
8590
}
8691
}

0 commit comments

Comments
 (0)
0