8000 [Console][DescriptorHelper] plugs the docu for 2.3, a second PR follows after this is merged by cordoval · Pull Request #3430 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

[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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions components/console/helpers/descriptorhelper.rst
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``.
Copy link
Member

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:

  1. They're used by the help command to output in different formats
  2. They're used in the ContainerDebugCommand (and could be used similarly in your custom commands) as a systematic way to render output for objects

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#L38

Because 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 in ContainerDebugCommand (with its custom DescriptorHelper and TextDescriptor, 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.

Copy link
Member

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 :)

Copy link
Member

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

Copy link
Member

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 :).


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());

Copy link
Member

Choose a reason for hiding this comment

The 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.
1 change: 1 addition & 0 deletions components/console/helpers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The Console Helpers
.. toctree::
:hidden:

descriptorhelper
dialoghelper
formatterhelper
progresshelper
Expand Down
1 change: 1 addition & 0 deletions components/console/helpers/map.rst.inc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* :doc:`/components/console/helpers/descriptionhelper`
* :doc:`/components/console/helpers/dialoghelper`
* :doc:`/components/console/helpers/formatterhelper`
* :doc:`/components/console/helpers/progresshelper`
Expand Down
1 change: 1 addition & 0 deletions components/console/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ Console Helpers
The console component also contains a set of "helpers" - different small
tools capable of helping you with different tasks:

* :doc:`/components/console/helpers/descriptorhelper`: formats help information
* :doc:`/components/console/helpers/dialoghelper`: interactively ask the user for information
* :doc:`/components/console/helpers/formatterhelper`: customize the output colorization
* :doc:`/components/console/helpers/progresshelper`: shows a progress bar
Expand Down
0