[Console] enable describing commands in ways that make the list command lazy

This commit is contained in:
Nicolas Grekas 2021-01-15 13:40:32 +01:00
parent 28533aa43c
commit 8a1a1b8171
51 changed files with 463 additions and 90 deletions

View File

@ -34,6 +34,7 @@ class ServerLogCommand extends Command
private $handler;
protected static $defaultName = 'server:log';
protected static $defaultDescription = 'Starts a log server that displays logs in real time';
public function isEnabled()
{
@ -60,7 +61,7 @@ class ServerLogCommand extends Command
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The line format', ConsoleFormatter::SIMPLE_FORMAT)
->addOption('date-format', null, InputOption::VALUE_REQUIRED, 'The date format', ConsoleFormatter::SIMPLE_DATE)
->addOption('filter', null, InputOption::VALUE_REQUIRED, 'An expression to filter log. Example: "level > 200 or channel in [\'app\', \'doctrine\']"')
->setDescription('Starts a log server that displays logs in real time')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
<info>%command.name%</info> starts a log server to display in real time the log
messages generated by your application:

View File

@ -33,6 +33,7 @@ use Twig\Loader\FilesystemLoader;
class DebugCommand extends Command
{
protected static $defaultName = 'debug:twig';
protected static $defaultDescription = 'Shows a list of twig functions, filters, globals and tests';
private $twig;
private $projectDir;
@ -60,7 +61,7 @@ class DebugCommand extends Command
new InputOption('filter', null, InputOption::VALUE_REQUIRED, 'Show details for all entries matching this filter'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
])
->setDescription('Shows a list of twig functions, filters, globals and tests')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command outputs a list of twig functions,
filters, globals and tests.

View File

@ -35,6 +35,7 @@ use Twig\Source;
class LintCommand extends Command
{
protected static $defaultName = 'lint:twig';
protected static $defaultDescription = 'Lints a template and outputs encountered errors';
private $twig;
@ -48,7 +49,7 @@ class LintCommand extends Command
protected function configure()
{
$this
->setDescription('Lints a template and outputs encountered errors')
->setDescription(self::$defaultDescription)
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
->addOption('show-deprecations', null, InputOption::VALUE_NONE, 'Show deprecations as errors')
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')

View File

@ -11,7 +11,9 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Monolog\Formatter\FormatterInterface;
use Symfony\Bridge\Monolog\Command\ServerLogCommand;
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use Symfony\Bridge\Twig\Extension\DumpExtension;
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
use Symfony\Component\HttpKernel\EventListener\DumpListener;
@ -127,9 +129,12 @@ return static function (ContainerConfigurator $container) {
'html' => inline_service(HtmlDescriptor::class)->args([service('var_dumper.html_dumper')]),
],
])
->tag('console.command', ['command' => 'server:dump'])
->tag('console.command')
->set('monolog.command.server_log', ServerLogCommand::class)
->tag('console.command', ['command' => 'server:log'])
;
if (class_exists(ConsoleFormatter::class) && interface_exists(FormatterInterface::class)) {
$container->services()->get('monolog.command.server_log')->tag('console.command');
}
};

View File

@ -30,6 +30,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
class AboutCommand extends Command
{
protected static $defaultName = 'about';
protected static $defaultDescription = 'Displays information about the current project';
/**
* {@inheritdoc}
@ -37,7 +38,7 @@ class AboutCommand extends Command
protected function configure()
{
$this
->setDescription('Displays information about the current project')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOT'
The <info>%command.name%</info> command displays information about the current Symfony project.

View File

@ -40,6 +40,7 @@ class AssetsInstallCommand extends Command
public const METHOD_RELATIVE_SYMLINK = 'relative symlink';
protected static $defaultName = 'assets:install';
protected static $defaultDescription = 'Installs bundles web assets under a public directory';
private $filesystem;
private $projectDir;
@ -64,7 +65,7 @@ class AssetsInstallCommand extends Command
->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it')
->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks')
->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist')
->setDescription('Installs bundles web assets under a public directory')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOT'
The <info>%command.name%</info> command installs bundle assets into a given
directory (e.g. the <comment>public</comment> directory).

View File

@ -36,6 +36,7 @@ use Symfony\Component\HttpKernel\RebootableInterface;
class CacheClearCommand extends Command
{
protected static $defaultName = 'cache:clear';
protected static $defaultDescription = 'Clears the cache';
private $cacheClearer;
private $filesystem;
@ -58,7 +59,7 @@ class CacheClearCommand extends Command
new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'),
new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'),
])
->setDescription('Clears the cache')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command clears the application cache for a given environment
and debug mode:

View File

@ -28,6 +28,7 @@ use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
final class CachePoolClearCommand extends Command
{
protected static $defaultName = 'cache:pool:clear';
protected static $defaultDescription = 'Clears cache pools';
private $poolClearer;
@ -47,7 +48,7 @@ final class CachePoolClearCommand extends Command
->setDefinition([
new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'),
])
->setDescription('Clears cache pools')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command clears the given cache pools or cache pool clearers.

View File

@ -26,6 +26,7 @@ use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
final class CachePoolDeleteCommand extends Command
{
protected static $defaultName = 'cache:pool:delete';
protected static $defaultDescription = 'Deletes an item from a cache pool';
private $poolClearer;
@ -46,7 +47,7 @@ final class CachePoolDeleteCommand extends Command
new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'),
new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'),
])
->setDescription('Deletes an item from a cache pool')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> deletes an item from a given cache pool.

View File

@ -24,6 +24,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class CachePoolListCommand extends Command
{
protected static $defaultName = 'cache:pool:list';
protected static $defaultDescription = 'List available cache pools';
private $poolNames;
@ -40,7 +41,7 @@ final class CachePoolListCommand extends Command
protected function configure()
{
$this
->setDescription('List available cache pools')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all available cache pools.
EOF

View File

@ -25,6 +25,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class CachePoolPruneCommand extends Command
{
protected static $defaultName = 'cache:pool:prune';
protected static $defaultDescription = 'Prunes cache pools';
private $pools;
@ -44,7 +45,7 @@ final class CachePoolPruneCommand extends Command
protected function configure()
{
$this
->setDescription('Prunes cache pools')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command deletes all expired items from all pruneable pools.

View File

@ -29,6 +29,7 @@ use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate;
class CacheWarmupCommand extends Command
{
protected static $defaultName = 'cache:warmup';
protected static $defaultDescription = 'Warms up an empty cache';
private $cacheWarmer;
@ -48,7 +49,7 @@ class CacheWarmupCommand extends Command
->setDefinition([
new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'),
])
->setDescription('Warms up an empty cache')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command warms up the cache.

View File

@ -33,6 +33,7 @@ use Symfony\Component\Yaml\Yaml;
class ConfigDebugCommand extends AbstractConfigCommand
{
protected static $defaultName = 'debug:config';
protected static $defaultDescription = 'Dumps the current configuration for an extension';
/**
* {@inheritdoc}
@ -44,7 +45,7 @@ class ConfigDebugCommand extends AbstractConfigCommand
new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'),
new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
])
->setDescription('Dumps the current configuration for an extension')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command dumps the current configuration for an
extension/bundle.

View File

@ -36,6 +36,7 @@ use Symfony\Component\Yaml\Yaml;
class ConfigDumpReferenceCommand extends AbstractConfigCommand
{
protected static $defaultName = 'config:dump-reference';
protected static $defaultDescription = 'Dumps the default configuration for an extension';
/**
* {@inheritdoc}
@ -48,7 +49,7 @@ class ConfigDumpReferenceCommand extends AbstractConfigCommand
new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'),
])
->setDescription('Dumps the default configuration for an extension')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command dumps the default configuration for an
extension/bundle.

View File

@ -35,6 +35,7 @@ class ContainerDebugCommand extends Command
use BuildDebugContainerTrait;
protected static $defaultName = 'debug:container';
protected static $defaultDescription = 'Displays current services for an application';
/**
* {@inheritdoc}
@ -57,7 +58,7 @@ class ContainerDebugCommand extends Command
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Displays deprecations generated when compiling and warming up the container'),
])
->setDescription('Displays current services for an application')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all configured <comment>public</comment> services:

View File

@ -30,6 +30,7 @@ use Symfony\Component\HttpKernel\Kernel;
final class ContainerLintCommand extends Command
{
protected static $defaultName = 'lint:container';
protected static $defaultDescription = 'Ensures that arguments injected into services match type declarations';
/**
* @var ContainerBuilder
@ -42,7 +43,7 @@ final class ContainerLintCommand extends Command
protected function configure()
{
$this
->setDescription('Ensures that arguments injected into services match type declarations')
->setDescription(self::$defaultDescription)
->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.')
;
}

View File

@ -30,6 +30,7 @@ use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
class DebugAutowiringCommand extends ContainerDebugCommand
{
protected static $defaultName = 'debug:autowiring';
protected static $defaultDescription = 'Lists classes/interfaces you can use for autowiring';
private $supportsHref;
private $fileLinkFormatter;
@ -50,7 +51,7 @@ class DebugAutowiringCommand extends ContainerDebugCommand
new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'),
new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'),
])
->setDescription('Lists classes/interfaces you can use for autowiring')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays the classes and interfaces that
you can use as type-hints for autowiring:

View File

@ -33,6 +33,7 @@ class EventDispatcherDebugCommand extends Command
private const DEFAULT_DISPATCHER = 'event_dispatcher';
protected static $defaultName = 'debug:event-dispatcher';
protected static $defaultDescription = 'Displays configured listeners for an application';
private $dispatchers;
public function __construct(ContainerInterface $dispatchers)
@ -54,7 +55,7 @@ class EventDispatcherDebugCommand extends Command
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
])
->setDescription('Displays configured listeners for an application')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all configured listeners:

View File

@ -36,6 +36,7 @@ class RouterDebugCommand extends Command
use BuildDebugContainerTrait;
protected static $defaultName = 'debug:router';
protected static $defaultDescription = 'Displays current routes for an application';
private $router;
private $fileLinkFormatter;
@ -59,7 +60,7 @@ class RouterDebugCommand extends Command
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'),
])
->setDescription('Displays current routes for an application')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> displays the configured routes:

View File

@ -31,6 +31,7 @@ use Symfony\Component\Routing\RouterInterface;
class RouterMatchCommand extends Command
{
protected static $defaultName = 'router:match';
protected static $defaultDescription = 'Helps debug routes by simulating a path info match';
private $router;
private $expressionLanguageProviders;
@ -55,7 +56,7 @@ class RouterMatchCommand extends Command
new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Sets the URI scheme (usually http or https)'),
new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Sets the URI host'),
])
->setDescription('Helps debug routes by simulating a path info match')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> shows which routes match a given request and which don't and for what reason:

View File

@ -27,6 +27,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsDecryptToLocalCommand extends Command
{
protected static $defaultName = 'secrets:decrypt-to-local';
protected static $defaultDescription = 'Decrypts all secrets and stores them in the local vault';
private $vault;
private $localVault;
@ -42,7 +43,7 @@ final class SecretsDecryptToLocalCommand extends Command
protected function configure()
{
$this
->setDescription('Decrypts all secrets and stores them in the local vault')
->setDescription(self::$defaultDescription)
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces overriding of secrets that already exist in the local vault')
->setHelp(<<<'EOF'
The <info>%command.name%</info> command decrypts all secrets and copies them in the local vault.

View File

@ -26,6 +26,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsEncryptFromLocalCommand extends Command
{
protected static $defaultName = 'secrets:encrypt-from-local';
protected static $defaultDescription = 'Encrypts all local secrets to the vault';
private $vault;
private $localVault;
@ -41,7 +42,7 @@ final class SecretsEncryptFromLocalCommand extends Command
protected function configure()
{
$this
->setDescription('Encrypts all local secrets to the vault')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command encrypts all locally overridden secrets to the vault.

View File

@ -29,6 +29,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsGenerateKeysCommand extends Command
{
protected static $defaultName = 'secrets:generate-keys';
protected static $defaultDescription = 'Generates new encryption keys';
private $vault;
private $localVault;
@ -44,7 +45,7 @@ final class SecretsGenerateKeysCommand extends Command
protected function configure()
{
$this
->setDescription('Generates new encryption keys')
->setDescription(self::$defaultDescription)
->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.')
->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypts existing secrets with the newly generated keys.')
->setHelp(<<<'EOF'

View File

@ -30,6 +30,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsListCommand extends Command
{
protected static $defaultName = 'secrets:list';
protected static $defaultDescription = 'Lists all secrets';
private $vault;
private $localVault;
@ -45,7 +46,7 @@ final class SecretsListCommand extends Command
protected function configure()
{
$this
->setDescription('Lists all secrets')
->setDescription(self::$defaultDescription)
->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names')
->setHelp(<<<'EOF'
The <info>%command.name%</info> command list all stored secrets.

View File

@ -29,6 +29,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsRemoveCommand extends Command
{
protected static $defaultName = 'secrets:remove';
protected static $defaultDescription = 'Removes a secret from the vault';
private $vault;
private $localVault;
@ -44,7 +45,7 @@ final class SecretsRemoveCommand extends Command
protected function configure()
{
$this
->setDescription('Removes a secret from the vault')
->setDescription(self::$defaultDescription)
->addArgument('name', InputArgument::REQUIRED, 'The name of the secret')
->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.')
->setHelp(<<<'EOF'

View File

@ -30,6 +30,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
final class SecretsSetCommand extends Command
{
protected static $defaultName = 'secrets:set';
protected static $defaultDescription = 'Sets a secret in the vault';
private $vault;
private $localVault;
@ -45,7 +46,7 @@ final class SecretsSetCommand extends Command
protected function configure()
{
$this
->setDescription('Sets a secret in the vault')
->setDescription(self::$defaultDescription)
->addArgument('name', InputArgument::REQUIRED, 'The name of the secret')
->addArgument('file', InputArgument::OPTIONAL, 'A file where to read the secret from or "-" for reading from STDIN')
->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.')

View File

@ -47,6 +47,7 @@ class TranslationDebugCommand extends Command
public const MESSAGE_EQUALS_FALLBACK = 2;
protected static $defaultName = 'debug:translation';
protected static $defaultDescription = 'Displays translation messages information';
private $translator;
private $reader;
@ -83,7 +84,7 @@ class TranslationDebugCommand extends Command
new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Displays only unused messages'),
new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'),
])
->setDescription('Displays translation messages information')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command helps finding unused or missing translation
messages and comparing them with the fallback ones by inspecting the

View File

@ -42,6 +42,7 @@ class TranslationUpdateCommand extends Command
private const SORT_ORDERS = [self::ASC, self::DESC];
protected static $defaultName = 'translation:update';
protected static $defaultDescription = 'Updates the translation file';
private $writer;
private $reader;
@ -85,7 +86,7 @@ class TranslationUpdateCommand extends Command
new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically', 'asc'),
new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'),
])
->setDescription('Updates the translation file')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command extracts translation strings from templates
of a given bundle or the default translations directory. It can display them or merge

View File

@ -30,6 +30,7 @@ use Symfony\Component\Workflow\Marking;
class WorkflowDumpCommand extends Command
{
protected static $defaultName = 'workflow:dump';
protected static $defaultDescription = 'Dump a workflow';
/**
* {@inheritdoc}
@ -43,7 +44,7 @@ class WorkflowDumpCommand extends Command
new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Labels a graph'),
new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format [dot|puml]', 'dot'),
])
->setDescription('Dump a workflow')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command dumps the graphical representation of a
workflow in different formats

View File

@ -62,76 +62,76 @@ return static function (ContainerConfigurator $container) {
->tag('kernel.event_subscriber')
->set('console.command.about', AboutCommand::class)
->tag('console.command', ['command' => 'about'])
->tag('console.command')
->set('console.command.assets_install', AssetsInstallCommand::class)
->args([
service('filesystem'),
param('kernel.project_dir'),
])
->tag('console.command', ['command' => 'assets:install'])
->tag('console.command')
->set('console.command.cache_clear', CacheClearCommand::class)
->args([
service('cache_clearer'),
service('filesystem'),
])
->tag('console.command', ['command' => 'cache:clear'])
->tag('console.command')
->set('console.command.cache_pool_clear', CachePoolClearCommand::class)
->args([
service('cache.global_clearer'),
])
->tag('console.command', ['command' => 'cache:pool:clear'])
->tag('console.command')
->set('console.command.cache_pool_prune', CachePoolPruneCommand::class)
->args([
[],
])
->tag('console.command', ['command' => 'cache:pool:prune'])
->tag('console.command')
->set('console.command.cache_pool_delete', CachePoolDeleteCommand::class)
->args([
service('cache.global_clearer'),
])
->tag('console.command', ['command' => 'cache:pool:delete'])
->tag('console.command')
->set('console.command.cache_pool_list', CachePoolListCommand::class)
->args([
null,
])
->tag('console.command', ['command' => 'cache:pool:list'])
->tag('console.command')
->set('console.command.cache_warmup', CacheWarmupCommand::class)
->args([
service('cache_warmer'),
])
->tag('console.command', ['command' => 'cache:warmup'])
->tag('console.command')
->set('console.command.config_debug', ConfigDebugCommand::class)
->tag('console.command', ['command' => 'debug:config'])
->tag('console.command')
->set('console.command.config_dump_reference', ConfigDumpReferenceCommand::class)
->tag('console.command', ['command' => 'config:dump-reference'])
->tag('console.command')
->set('console.command.container_debug', ContainerDebugCommand::class)
->tag('console.command', ['command' => 'debug:container'])
->tag('console.command')
->set('console.command.container_lint', ContainerLintCommand::class)
->tag('console.command', ['command' => 'lint:container'])
->tag('console.command')
->set('console.command.debug_autowiring', DebugAutowiringCommand::class)
->args([
null,
service('debug.file_link_formatter')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'debug:autowiring'])
->tag('console.command')
->set('console.command.event_dispatcher_debug', EventDispatcherDebugCommand::class)
->args([
tagged_locator('event_dispatcher.dispatcher'),
])
->tag('console.command', ['command' => 'debug:event-dispatcher'])
->tag('console.command')
->set('console.command.messenger_consume_messages', ConsumeMessagesCommand::class)
->args([
@ -141,7 +141,7 @@ return static function (ContainerConfigurator $container) {
service('logger')->nullOnInvalid(),
[], // Receiver names
])
->tag('console.command', ['command' => 'messenger:consume'])
->tag('console.command')
->tag('monolog.logger', ['channel' => 'messenger'])
->set('console.command.messenger_setup_transports', SetupTransportsCommand::class)
@ -149,19 +149,19 @@ return static function (ContainerConfigurator $container) {
service('messenger.receiver_locator'),
[], // Receiver names
])
->tag('console.command', ['command' => 'messenger:setup-transports'])
->tag('console.command')
->set('console.command.messenger_debug', DebugCommand::class)
->args([
[], // Message to handlers mapping
])
->tag('console.command', ['command' => 'debug:messenger'])
->tag('console.command')
->set('console.command.messenger_stop_workers', StopWorkersCommand::class)
->args([
service('cache.messenger.restart_workers_signal'),
])
->tag('console.command', ['command' => 'messenger:stop-workers'])
->tag('console.command')
->set('console.command.messenger_failed_messages_retry', FailedMessagesRetryCommand::class)
->args([
@ -171,35 +171,35 @@ return static function (ContainerConfigurator $container) {
service('event_dispatcher'),
service('logger'),
])
->tag('console.command', ['command' => 'messenger:failed:retry'])
->tag('console.command')
->set('console.command.messenger_failed_messages_show', FailedMessagesShowCommand::class)
->args([
abstract_arg('Receiver name'),
abstract_arg('Receiver'),
])
->tag('console.command', ['command' => 'messenger:failed:show'])
->tag('console.command')
->set('console.command.messenger_failed_messages_remove', FailedMessagesRemoveCommand::class)
->args([
abstract_arg('Receiver name'),
abstract_arg('Receiver'),
])
->tag('console.command', ['command' => 'messenger:failed:remove'])
->tag('console.command')
->set('console.command.router_debug', RouterDebugCommand::class)
->args([
service('router'),
service('debug.file_link_formatter')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'debug:router'])
->tag('console.command')
->set('console.command.router_match', RouterMatchCommand::class)
->args([
service('router'),
tagged_iterator('routing.expression_language_provider'),
])
->tag('console.command', ['command' => 'router:match'])
->tag('console.command')
->set('console.command.translation_debug', TranslationDebugCommand::class)
->args([
@ -211,7 +211,7 @@ return static function (ContainerConfigurator $container) {
[], // Translator paths
[], // Twig paths
])
->tag('console.command', ['command' => 'debug:translation'])
->tag('console.command')
->set('console.command.translation_update', TranslationUpdateCommand::class)
->args([
@ -224,22 +224,22 @@ return static function (ContainerConfigurator $container) {
[], // Translator paths
[], // Twig paths
])
->tag('console.command', ['command' => 'translation:update'])
->tag('console.command')
->set('console.command.validator_debug', ValidatorDebugCommand::class)
->args([
service('validator'),
])
->tag('console.command', ['command' => 'debug:validator'])
->tag('console.command')
->set('console.command.workflow_dump', WorkflowDumpCommand::class)
->tag('console.command', ['command' => 'workflow:dump'])
->tag('console.command')
->set('console.command.xliff_lint', XliffLintCommand::class)
->tag('console.command', ['command' => 'lint:xliff'])
->tag('console.command')
->set('console.command.yaml_lint', YamlLintCommand::class)
->tag('console.command', ['command' => 'lint:yaml'])
->tag('console.command')
->set('console.command.form_debug', \Symfony\Component\Form\Command\DebugCommand::class)
->args([
@ -250,48 +250,48 @@ return static function (ContainerConfigurator $container) {
[], // All type guessers are stored here by FormPass
service('debug.file_link_formatter')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'debug:form'])
->tag('console.command')
->set('console.command.secrets_set', SecretsSetCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'secrets:set'])
->tag('console.command')
->set('console.command.secrets_remove', SecretsRemoveCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'secrets:remove'])
->tag('console.command')
->set('console.command.secrets_generate_key', SecretsGenerateKeysCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault')->ignoreOnInvalid(),
])
->tag('console.command', ['command' => 'secrets:generate-keys'])
->tag('console.command')
->set('console.command.secrets_list', SecretsListCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault'),
])
->tag('console.command', ['command' => 'secrets:list'])
->tag('console.command')
->set('console.command.secrets_decrypt_to_local', SecretsDecryptToLocalCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault')->ignoreOnInvalid(),
])
->tag('console.command', ['command' => 'secrets:decrypt-to-local'])
->tag('console.command')
->set('console.command.secrets_encrypt_from_local', SecretsEncryptFromLocalCommand::class)
->args([
service('secrets.vault'),
service('secrets.local_vault'),
])
->tag('console.command', ['command' => 'secrets:encrypt-from-local'])
->tag('console.command')
;
};

View File

@ -34,6 +34,7 @@ use Symfony\Component\Security\Core\Encoder\SelfSaltingEncoderInterface;
class UserPasswordEncoderCommand extends Command
{
protected static $defaultName = 'security:encode-password';
protected static $defaultDescription = 'Encodes a password';
private $encoderFactory;
private $userClasses;
@ -52,7 +53,7 @@ class UserPasswordEncoderCommand extends Command
protected function configure()
{
$this
->setDescription('Encodes a password')
->setDescription(self::$defaultDescription)
->addArgument('password', InputArgument::OPTIONAL, 'The plain password to encode.')
->addArgument('user-class', InputArgument::OPTIONAL, 'The User entity class path associated with the encoder used to encode the password.')
->addOption('empty-salt', null, InputOption::VALUE_NONE, 'Do not generate a salt or let the encoder generate one.')

View File

@ -20,6 +20,6 @@ return static function (ContainerConfigurator $container) {
service('security.encoder_factory'),
abstract_arg('encoders user classes'),
])
->tag('console.command', ['command' => 'security:encode-password'])
->tag('console.command')
;
};

View File

@ -24,10 +24,10 @@ return static function (ContainerConfigurator $container) {
param('twig.default_path'),
service('debug.file_link_formatter')->nullOnInvalid(),
])
->tag('console.command', ['command' => 'debug:twig'])
->tag('console.command')
->set('twig.command.lint', LintCommand::class)
->args([service('twig')])
->tag('console.command', ['command' => 'lint:twig'])
->tag('console.command')
;
};

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Console;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Command\SignalableCommandInterface;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
@ -489,8 +490,10 @@ class Application implements ResetInterface
return null;
}
// Will throw if the command is not correctly initialized.
$command->getDefinition();
if (!$command instanceof LazyCommand) {
// Will throw if the command is not correctly initialized.
$command->getDefinition();
}
if (!$command->getName()) {
throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command)));

View File

@ -4,8 +4,10 @@ CHANGELOG
5.3
---
* Added `GithubActionReporter` to render annotations in a Github Action
* Added `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options.
* Add `GithubActionReporter` to render annotations in a Github Action
* Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options
* Add the `Command::$defaultDescription` static property and the `description` attribute
on the `console.command` tag to allow the `list` command to instantiate commands lazily
5.2.0
-----

View File

@ -39,6 +39,11 @@ class Command
*/
protected static $defaultName;
/**
* @var string|null The default command description
*/
protected static $defaultDescription;
private $application;
private $name;
private $processTitle;
@ -65,6 +70,17 @@ class Command
return $class === $r->class ? static::$defaultName : null;
}
/**
* @return string|null The default command description or null when no default description is set
*/
public static function getDefaultDescription(): ?string
{
$class = static::class;
$r = new \ReflectionProperty($class, 'defaultDescription');
return $class === $r->class ? static::$defaultDescription : null;
}
/**
* @param string|null $name The name of the command; passing null means it must be set in configure()
*
@ -78,6 +94,10 @@ class Command
$this->setName($name);
}
if ('' === $this->description) {
$this->setDescription(static::getDefaultDescription() ?? '');
}
$this->configure();
}
@ -298,6 +318,8 @@ class Command
* This method is not part of public API and should not be used directly.
*
* @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
*
* @internal
*/
public function mergeApplicationDefinition(bool $mergeArgs = true)
{
@ -554,11 +576,14 @@ class Command
*/
public function setAliases(iterable $aliases)
{
$list = [];
foreach ($aliases as $alias) {
$this->validateName($alias);
$list[] = $alias;
}
$this->aliases = $aliases;
$this->aliases = \is_array($aliases) ? $aliases : $list;
return $this;
}

View File

@ -0,0 +1,211 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
final class LazyCommand extends Command
{
private $command;
private $isEnabled;
public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true)
{
$this->setName($name)
->setAliases($aliases)
->setHidden($isHidden)
->setDescription($description);
$this->command = $commandFactory;
$this->isEnabled = $isEnabled;
}
public function ignoreValidationErrors(): void
{
$this->getCommand()->ignoreValidationErrors();
}
public function setApplication(Application $application = null): void
{
if ($this->command instanceof parent) {
$this->command->setApplication($application);
}
parent::setApplication($application);
}
public function setHelperSet(HelperSet $helperSet): void
{
if ($this->command instanceof parent) {
$this->command->setHelperSet($helperSet);
}
parent::setHelperSet($helperSet);
}
public function isEnabled(): bool
{
return $this->isEnabled ?? $this->getCommand()->isEnabled();
}
public function run(InputInterface $input, OutputInterface $output): int
{
return $this->getCommand()->run($input, $output);
}
/**
* @return $this
*/
public function setCode(callable $code): self
{
$this->getCommand()->setCode($code);
return $this;
}
/**
* @internal
*/
public function mergeApplicationDefinition(bool $mergeArgs = true): void
{
$this->getCommand()->mergeApplicationDefinition($mergeArgs);
}
/**
* @return $this
*/
public function setDefinition($definition): self
{
$this->getCommand()->setDefinition($definition);
return $this;
}
public function getDefinition(): InputDefinition
{
return $this->getCommand()->getDefinition();
}
public function getNativeDefinition(): InputDefinition
{
return $this->getCommand()->getNativeDefinition();
}
/**
* @return $this
*/
public function addArgument(string $name, int $mode = null, string $description = '', $default = null): self
{
$this->getCommand()->addArgument($name, $mode, $description, $default);
return $this;
}
/**
* @return $this
*/
public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null): self
{
$this->getCommand()->addOption($name, $shortcut, $mode, $description, $default);
return $this;
}
/**
* @return $this
*/
public function setProcessTitle(string $title): self
{
$this->getCommand()->setProcessTitle($title);
return $this;
}
/**
* @return $this
*/
public function setHelp(string $help): self
{
$this->getCommand()->setHelp($help);
return $this;
}
public function getHelp(): string
{
return $this->getCommand()->getHelp();
}
public function getProcessedHelp(): string
{
return $this->getCommand()->getProcessedHelp();
}
public function getSynopsis(bool $short = false): string
{
return $this->getCommand()->getSynopsis($short);
}
/**
* @return $this
*/
public function addUsage(string $usage): self
{
$this->getCommand()->addUsage($usage);
return $this;
}
public function getUsages(): array
{
return $this->getCommand()->getUsages();
}
/**
* @return mixed
*/
public function getHelper(string $name)
{
return $this->getCommand()->getHelper($name);
}
public function getCommand(): parent
{
if (!$this->command instanceof \Closure) {
return $this->command;
}
$command = $this->command = ($this->command)();
$command->setApplication($this->getApplication());
if (null !== $this->getHelperSet()) {
$command->setHelperSet($this->getHelperSet());
}
$command->setName($this->getName())
->setAliases($this->getAliases())
->setHidden($this->isHidden())
->setDescription($this->getDescription());
// Will throw if the command is not correctly initialized.
$command->getDefinition();
return $command;
}
}

View File

@ -12,11 +12,14 @@
namespace Symfony\Component\Console\DependencyInjection;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
/**
@ -52,7 +55,7 @@ class AddConsoleCommandPass implements CompilerPassInterface
$class = $container->getParameterBag()->resolveValue($definition->getClass());
if (isset($tags[0]['command'])) {
$commandName = $tags[0]['command'];
$aliases = $tags[0]['command'];
} else {
if (!$r = $container->getReflectionClass($class)) {
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
@ -60,7 +63,14 @@ class AddConsoleCommandPass implements CompilerPassInterface
if (!$r->isSubclassOf(Command::class)) {
throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
}
$commandName = $class::getDefaultName();
$aliases = $class::getDefaultName();
}
$aliases = explode('|', $aliases ?? '');
$commandName = array_shift($aliases);
if ($isHidden = '' === $commandName) {
$commandName = array_shift($aliases);
}
if (null === $commandName) {
@ -74,16 +84,19 @@ class AddConsoleCommandPass implements CompilerPassInterface
continue;
}
$description = $tags[0]['description'] ?? null;
unset($tags[0]);
$lazyCommandMap[$commandName] = $id;
$lazyCommandRefs[$id] = new TypedReference($id, $class);
$aliases = [];
foreach ($tags as $tag) {
if (isset($tag['command'])) {
$aliases[] = $tag['command'];
$lazyCommandMap[$tag['command']] = $id;
}
$description = $description ?? $tag['description'] ?? null;
}
$definition->addMethodCall('setName', [$commandName]);
@ -91,6 +104,29 @@ class AddConsoleCommandPass implements CompilerPassInterface
if ($aliases) {
$definition->addMethodCall('setAliases', [$aliases]);
}
if ($isHidden) {
$definition->addMethodCall('setHidden', [true]);
}
if (!$description) {
if (!$r = $container->getReflectionClass($class)) {
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
}
if (!$r->isSubclassOf(Command::class)) {
throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
}
$description = $class::getDefaultDescription();
}
if ($description) {
$definition->addMethodCall('setDescription', [$description]);
$container->register('.'.$id.'.lazy', LazyCommand::class)
->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
$lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy');
}
}
$container

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Console\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
@ -20,6 +21,7 @@ use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
class AddConsoleCommandPassTest extends TestCase
@ -118,6 +120,39 @@ class AddConsoleCommandPassTest extends TestCase
];
}
public function testProcessFallsBackToDefaultDescription()
{
$container = new ContainerBuilder();
$container
->register('with-defaults', DescribedCommand::class)
->addTag('console.command')
;
$pass = new AddConsoleCommandPass();
$pass->process($container);
$commandLoader = $container->getDefinition('console.command_loader');
$commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0));
$this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass());
$this->assertSame(['cmdname' => 'with-defaults'], $commandLoader->getArgument(1));
$this->assertEquals([['with-defaults' => new ServiceClosureArgument(new Reference('.with-defaults.lazy'))]], $commandLocator->getArguments());
$this->assertSame([], $container->getParameter('console.command.ids'));
$initCounter = DescribedCommand::$initCounter;
$command = $container->get('console.command_loader')->get('cmdname');
$this->assertInstanceOf(LazyCommand::class, $command);
$this->assertSame(['cmdalias'], $command->getAliases());
$this->assertSame('Just testing', $command->getDescription());
$this->assertTrue($command->isHidden());
$this->assertTrue($command->isEnabled());
$this->assertSame($initCounter, DescribedCommand::$initCounter);
$this->assertSame('', $command->getHelp());
$this->assertSame(1 + $initCounter, DescribedCommand::$initCounter);
}
public function testProcessThrowAnExceptionIfTheServiceIsAbstract()
{
$this->expectException(\InvalidArgumentException::class);
@ -250,3 +285,18 @@ class NamedCommand extends Command
{
protected static $defaultName = 'default';
}
class DescribedCommand extends Command
{
public static $initCounter = 0;
protected static $defaultName = '|cmdname|cmdalias';
protected static $defaultDescription = 'Just testing';
public function __construct()
{
++self::$initCounter;
parent::__construct();
}
}

View File

@ -32,6 +32,7 @@ use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
class DebugCommand extends Command
{
protected static $defaultName = 'debug:form';
protected static $defaultDescription = 'Displays form type information';
private $formRegistry;
private $namespaces;
@ -64,7 +65,7 @@ class DebugCommand extends Command
new InputOption('show-deprecated', null, InputOption::VALUE_NONE, 'Display deprecated options in form types'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'),
])
->setDescription('Displays form type information')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays information about form types.

View File

@ -36,6 +36,7 @@ use Symfony\Component\Messenger\Worker;
class ConsumeMessagesCommand extends Command
{
protected static $defaultName = 'messenger:consume';
protected static $defaultDescription = 'Consumes messages';
private $routableBus;
private $receiverLocator;
@ -71,7 +72,7 @@ class ConsumeMessagesCommand extends Command
new InputOption('sleep', null, InputOption::VALUE_REQUIRED, 'Seconds to sleep before asking for new messages after no messages were found', 1),
new InputOption('bus', 'b', InputOption::VALUE_REQUIRED, 'Name of the bus to which received messages should be dispatched (if not passed, bus is determined automatically)'),
])
->setDescription('Consumes messages')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command consumes messages and dispatches them to the message bus.

View File

@ -26,6 +26,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
class DebugCommand extends Command
{
protected static $defaultName = 'debug:messenger';
protected static $defaultDescription = 'Lists messages you can dispatch using the message buses';
private $mapping;
@ -43,7 +44,7 @@ class DebugCommand extends Command
{
$this
->addArgument('bus', InputArgument::OPTIONAL, sprintf('The bus id (one of "%s")', implode('", "', array_keys($this->mapping))))
->setDescription('Lists messages you can dispatch using the message buses')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays all messages that can be
dispatched using the message buses:

View File

@ -27,6 +27,7 @@ use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface;
class FailedMessagesRemoveCommand extends AbstractFailedMessagesCommand
{
protected static $defaultName = 'messenger:failed:remove';
protected static $defaultDescription = 'Remove given messages from the failure transport';
/**
* {@inheritdoc}
@ -39,7 +40,7 @@ class FailedMessagesRemoveCommand extends AbstractFailedMessagesCommand
new InputOption('force', null, InputOption::VALUE_NONE, 'Force the operation without confirmation'),
new InputOption('show-messages', null, InputOption::VALUE_NONE, 'Display messages before removing it (if multiple ids are given)'),
])
->setDescription('Remove given messages from the failure transport')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> removes given messages that are pending in the failure transport.

View File

@ -35,6 +35,7 @@ use Symfony\Component\Messenger\Worker;
class FailedMessagesRetryCommand extends AbstractFailedMessagesCommand
{
protected static $defaultName = 'messenger:failed:retry';
protected static $defaultDescription = 'Retries one or more messages from the failure transport';
private $eventDispatcher;
private $messageBus;
@ -59,7 +60,7 @@ class FailedMessagesRetryCommand extends AbstractFailedMessagesCommand
new InputArgument('id', InputArgument::IS_ARRAY, 'Specific message id(s) to retry'),
new InputOption('force', null, InputOption::VALUE_NONE, 'Force action without confirmation'),
])
->setDescription('Retries one or more messages from the failure transport')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> retries message in the failure transport.

View File

@ -28,6 +28,7 @@ use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface;
class FailedMessagesShowCommand extends AbstractFailedMessagesCommand
{
protected static $defaultName = 'messenger:failed:show';
protected static $defaultDescription = 'Shows one or more messages from the failure transport';
/**
* {@inheritdoc}
@ -39,7 +40,7 @@ class FailedMessagesShowCommand extends AbstractFailedMessagesCommand
new InputArgument('id', InputArgument::OPTIONAL, 'Specific message id to show'),
new InputOption('max', null, InputOption::VALUE_REQUIRED, 'Maximum number of messages to list', 50),
])
->setDescription('Shows one or more messages from the failure transport')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> shows message that are pending in the failure transport.

View File

@ -25,6 +25,7 @@ use Symfony\Component\Messenger\Transport\SetupableTransportInterface;
class SetupTransportsCommand extends Command
{
protected static $defaultName = 'messenger:setup-transports';
protected static $defaultDescription = 'Prepares the required infrastructure for the transport';
private $transportLocator;
private $transportNames;
@ -41,7 +42,7 @@ class SetupTransportsCommand extends Command
{
$this
->addArgument('transport', InputArgument::OPTIONAL, 'Name of the transport to setup', null)
->setDescription('Prepares the required infrastructure for the transport')
->setDescription(self::$defaultDescription)
->setHelp(<<<EOF
The <info>%command.name%</info> command setups the transports:

View File

@ -25,6 +25,7 @@ use Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener;
class StopWorkersCommand extends Command
{
protected static $defaultName = 'messenger:stop-workers';
protected static $defaultDescription = 'Stops workers after their current message';
private $restartSignalCachePool;
@ -42,7 +43,7 @@ class StopWorkersCommand extends Command
{
$this
->setDefinition([])
->setDescription('Stops workers after their current message')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name%</info> command sends a signal to stop any <info>messenger:consume</info> processes that are running.

View File

@ -31,6 +31,7 @@ use Symfony\Component\Translation\Util\XliffUtils;
class XliffLintCommand extends Command
{
protected static $defaultName = 'lint:xliff';
protected static $defaultDescription = 'Lints a XLIFF file and outputs encountered errors';
private $format;
private $displayCorrectFiles;
@ -53,7 +54,7 @@ class XliffLintCommand extends Command
protected function configure()
{
$this
->setDescription('Lints a XLIFF file and outputs encountered errors')
->setDescription(self::$defaultDescription)
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
->setHelp(<<<EOF

View File

@ -33,6 +33,7 @@ use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
class DebugCommand extends Command
{
protected static $defaultName = 'debug:validator';
protected static $defaultDescription = 'Displays validation constraints for classes';
private $validator;
@ -48,7 +49,7 @@ class DebugCommand extends Command
$this
->addArgument('class', InputArgument::REQUIRED, 'A fully qualified class name or a path')
->addOption('show-all', null, InputOption::VALUE_NONE, 'Show all classes even if they have no validation constraints')
->setDescription('Displays validation constraints for classes')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The <info>%command.name% 'App\Entity\Dummy'</info> command dumps the validators for the dummy class.

View File

@ -35,6 +35,7 @@ use Symfony\Component\VarDumper\Server\DumpServer;
class ServerDumpCommand extends Command
{
protected static $defaultName = 'server:dump';
protected static $defaultDescription = 'Starts a dump server that collects and displays dumps in a single place';
private $server;
@ -58,7 +59,7 @@ class ServerDumpCommand extends Command
$this
->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', $availableFormats), 'cli')
->setDescription('Starts a dump server that collects and displays dumps in a single place')
->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
<info>%command.name%</info> starts a dump server that collects and displays
dumps in a single place for debugging you application:

View File

@ -33,6 +33,7 @@ use Symfony\Component\Yaml\Yaml;
class LintCommand extends Command
{
protected static $defaultName = 'lint:yaml';
protected static $defaultDescription = 'Lints a file and outputs encountered errors';
private $parser;
private $format;
@ -54,7 +55,7 @@ class LintCommand extends Command
protected function configure()
{
$this
->setDescription('Lints a file and outputs encountered errors')
->setDescription(self::$defaultDescription)
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format')
->addOption('parse-tags', null, InputOption::VALUE_NONE, 'Parse custom tags')