-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[Console][DescriptorHelper] plugs the docu for 2.3, a second PR follows after this is merged #3430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
cordoval
wants to merge
1
commit into
symfony:2.3
from
cordoval:2803-document-descriptors-and-descriptorhelper
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
.. index:: | ||
single: Descriptors and Descriptor Helper | ||
|
||
Descriptors | ||
=========== | ||
|
||
.. versionadded:: 2.3 | ||
Descriptors and Descriptor Helper were introduced in Symfony 2.3. | ||
|
||
Descriptors were introduced as a manner to refactor the self documenting | ||
logic found spread out in the ``Application`` and ``Command`` classes. The | ||
purpose of this logic is to format the help output information of an | ||
application, command, input definition, argument or option in various ways. | ||
|
||
The :namespace:`Symfony\\Component\\Console\\Descriptor` class | ||
family has functions to describe applications, commands, input | ||
definitions, arguments and options for console applications in various | ||
formats, namely xml, markdown, json, and txt. | ||
|
||
Descriptors act upon the flags passed to the console app commands:: | ||
|
||
$ php app.php some:command --format=json --raw=true | ||
|
||
You can create a custom descriptor to output these help options or | ||
other output to the user in a different format, like YAML. | ||
|
||
Descriptors usage is already built-in for console applications. You | ||
don't need to register the ``DescriptorHelper`` to benefit from the | ||
default descriptors: | ||
|
||
10000 * TextDescriptor | ||
* XmlDescriptor | ||
* MarkdownDescriptor | ||
* JsonDescriptor | ||
|
||
Whenever you need to use a custom descriptor for your custom application, | ||
you could use it directly. However, the family of Descriptors is meant | ||
to be used via its ``DescriptorHelper``. | ||
|
||
Setting the Descriptor Helper | ||
----------------------------- | ||
|
||
Descriptor Helper is not included in the default helper set, which you can | ||
get by calling | ||
:method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`, but | ||
you can include it:: | ||
|
||
// within your runner script | ||
$app = new Application(); | ||
$app->getHelperSet()->set(new DescriptorHelper()); | ||
|
||
// or overriding by extending the Application class | ||
protected function getDefaultHelperSet() | ||
{ | ||
return new HelperSet(array( | ||
// ... | ||
new DescriptorHelper(), | ||
)); | ||
} | ||
|
||
// and use it within your command | ||
$helper = $this->getHelperSet()->get('descriptor'); | ||
|
||
In order to take advantage of a custom Descriptor class | ||
you should register it with the helper above adding:: | ||
|
||
$helper->register('no-color', new NoColorDescriptor()); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this section is relevant, because I don't think Symfony ever looks for the descriptor inside the helper set. The descriptors are only ever used directly, for example:
So you don't register it, I think you just simply create one and use it. |
||
Custom Descriptors | ||
------------------ | ||
|
||
With the Descriptor abstraction the work of writing a custom | ||
descriptor is now easy. All default descriptors use an | ||
abstract class ``Descriptor`` which you can also extend to | ||
segregate the describe functionality for application, | ||
command, input definition, input argument and option accordingly. | ||
A better option is to implement the interface | ||
:class:``DescriptorInterface`` since you will be overriding most of it. | ||
|
||
In order to create your custom description you can | ||
first create a base abstract class:: | ||
|
||
use Symfony\Component\Console\Descriptor\DescriptorInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Acme\User; | ||
use Acme\UserGroup; | ||
|
||
abstract class UserDescriptor implements DescriptorInterface | ||
{ | ||
protected $output; | ||
|
||
public function describe(OutputInterface $output, $subject, array $options = array()) | ||
{ | ||
$this->output = $output; | ||
if ($subject instanceof User) { | ||
$this->describeUser($subject); | ||
} elseif ($subject instanceof UserGroup) { | ||
$this->describeUserGroup($subject); | ||
} | ||
} | ||
|
||
abstract protected function describeUser(User $subject); | ||
abstract protected function describeUserGroup(UserGroup $subject); | ||
} | ||
|
||
Let's enable this ``Descriptor`` to represent Users, either | ||
individually or within groups:: | ||
|
||
use Symfony\Component\Console\Helper\TableHelper; | ||
|
||
class TextUserDescriptor extends UserDescriptor | ||
{ | ||
protected function describeUser(User $subject) | ||
{ | ||
$lines = array(); | ||
$lines[] = 'Name: '.$subject->getName(); | ||
$lines[] = 'Age: '.$subject->getAge(); | ||
$lines[] = 'Group: '.$subject->getGroup()->getName(); | ||
|
||
$this->output->writeln($lines); | ||
} | ||
|
||
protected function describeUserGroup(UserGroup $subject) | ||
{ | ||
$table = new TableHelper(); | ||
$table->setLayout(TableHelper::LAYOUT_COMPACT); | ||
$table->setHeaders(array('Name', 'Age')); | ||
|
||
foreach ($subject->getUsers() as $user) { | ||
$table->addRow(array($user->getName(), $user->getAge())); | ||
} | ||
|
||
$this->output->writeln(array( | ||
'Group name: '.$subject->getName(), | ||
'', | ||
)); | ||
$table->render($this->output); | ||
} | ||
} | ||
|
||
Notice the describe method adapts accordingly whether the subject | ||
passed is a ``User`` object or a group of ``User`` objects. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're giving the user the wrong idea here. Descriptors are used for 2 things:
This gives the impression that we can hook into (1) and output in YAML format, for example. But that's just not true (not easily) - because the
HelpCommand
instantiates the DescriptorHelper (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Console/Command/HelpCommand.php#L83), which has the formats hardcoded in it: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Console/Helper/DescriptorHelper.php#L38Because of that, other than a small paragraph saying that the descriptor is used internally to print the help message for commands, I don't we should talk too much about it.
Instead, we should focus on the second use-case, and emphasize that this is handy when (1) you need to systematically output details about different types of objects and (2) you want the user to be able to pass some flag (e.g.
--format=json
) to render the output in different formats. We should pretty much describe the setup inContainerDebugCommand
(with its customDescriptorHelper
andTextDescriptor
,XmlDescriptor
, etc implementations).Someone let me know if I'm wrong anywhere - this is a bit of a confusing feature, only because I think it's been created primarily for internal use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fully agree (that's actually what I want to tell in this ticket :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The case 1 is simply a use case for the case 2 btw: The HelpCommand uses the helper to output the commands in several format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right - I just don't want to talk about it in a way that makes it seem like you can hook into that and add, for example, the ability to output the Help command in YAML. That just doesn't seem possible, short of overriding the help command itself :).