diff --git a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
index f04db50c8ced7..8ecd220a2f0b9 100644
--- a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
+++ b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php
@@ -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 @@ protected function configure()
->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'
%command.name% starts a log server to display in real time the log
messages generated by your application:
diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
index 8962a41dd366e..88fae85aaf102 100644
--- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php
+++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
@@ -33,6 +33,7 @@
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 @@ protected function configure()
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 %command.name% command outputs a list of twig functions,
filters, globals and tests.
diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php
index 505f05959bb68..39d79f0b1bba6 100644
--- a/src/Symfony/Bridge/Twig/Command/LintCommand.php
+++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php
@@ -35,6 +35,7 @@
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 @@ public function __construct(Environment $twig)
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')
diff --git a/src/Symfony/Bundle/DebugBundle/Resources/config/services.php b/src/Symfony/Bundle/DebugBundle/Resources/config/services.php
index abde96d0625ec..d0f57c092872e 100644
--- a/src/Symfony/Bundle/DebugBundle/Resources/config/services.php
+++ b/src/Symfony/Bundle/DebugBundle/Resources/config/services.php
@@ -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 @@
'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');
+ }
};
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php
index 4c9f968736c59..d1de7c651b9b1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php
@@ -30,6 +30,7 @@
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 %command.name% command displays information about the current Symfony project.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 70ad92343eb25..ae8ca199879fc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -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 @@ protected function configure()
->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 %command.name% command installs bundle assets into a given
directory (e.g. the public directory).
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
index b9a829471f098..5b9271920e7ae 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
@@ -36,6 +36,7 @@
class CacheClearCommand extends Command
{
protected static $defaultName = 'cache:clear';
+ protected static $defaultDescription = 'Clears the cache';
private $cacheClearer;
private $filesystem;
@@ -58,7 +59,7 @@ protected function configure()
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 %command.name% command clears the application cache for a given environment
and debug mode:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
index 50aacd9bbd73d..2ffde574f16b0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php
@@ -28,6 +28,7 @@
final class CachePoolClearCommand extends Command
{
protected static $defaultName = 'cache:pool:clear';
+ protected static $defaultDescription = 'Clears cache pools';
private $poolClearer;
@@ -47,7 +48,7 @@ protected function configure()
->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 %command.name% command clears the given cache pools or cache pool clearers.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php
index 2a7a2fe513040..6ac82925e6a3d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php
@@ -26,6 +26,7 @@
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 @@ protected function configure()
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 %command.name% deletes an item from a given cache pool.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php
index 7b725411d5015..4a4b1eb2fa49e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php
@@ -24,6 +24,7 @@
final class CachePoolListCommand extends Command
{
protected static $defaultName = 'cache:pool:list';
+ protected static $defaultDescription = 'List available cache pools';
private $poolNames;
@@ -40,7 +41,7 @@ public function __construct(array $poolNames)
protected function configure()
{
$this
- ->setDescription('List available cache pools')
+ ->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The %command.name% command lists all available cache pools.
EOF
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php
index 65f3ff6b5802e..bc5b7f861fb72 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php
@@ -25,6 +25,7 @@
final class CachePoolPruneCommand extends Command
{
protected static $defaultName = 'cache:pool:prune';
+ protected static $defaultDescription = 'Prunes cache pools';
private $pools;
@@ -44,7 +45,7 @@ public function __construct(iterable $pools)
protected function configure()
{
$this
- ->setDescription('Prunes cache pools')
+ ->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The %command.name% command deletes all expired items from all pruneable pools.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
index 8feb2dd9c51b2..a79a1106d6e6d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
@@ -29,6 +29,7 @@
class CacheWarmupCommand extends Command
{
protected static $defaultName = 'cache:warmup';
+ protected static $defaultDescription = 'Warms up an empty cache';
private $cacheWarmer;
@@ -48,7 +49,7 @@ protected function configure()
->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 %command.name% command warms up the cache.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
index c68f17e120bbd..8a526cb99143d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php
@@ -33,6 +33,7 @@
class ConfigDebugCommand extends AbstractConfigCommand
{
protected static $defaultName = 'debug:config';
+ protected static $defaultDescription = 'Dumps the current configuration for an extension';
/**
* {@inheritdoc}
@@ -44,7 +45,7 @@ protected function configure()
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 %command.name% command dumps the current configuration for an
extension/bundle.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
index 62dcc856e0f56..c1b0cf1626c19 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
@@ -36,6 +36,7 @@
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 @@ protected function configure()
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 %command.name% command dumps the default configuration for an
extension/bundle.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
index 7c330dbdf4f85..8b41fc1dce7a0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
@@ -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 @@ protected function configure()
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 %command.name% command displays all configured public services:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php
index f059df1ee62fe..02ef668cfbee6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php
@@ -30,6 +30,7 @@
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.')
;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php
index 32bd630f32516..8aceb5c0a66df 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php
@@ -30,6 +30,7 @@
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 @@ protected function configure()
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 %command.name% command displays the classes and interfaces that
you can use as type-hints for autowiring:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
index a053d96dd8fdb..b828dee78139e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php
@@ -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 @@ protected function configure()
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 %command.name% command displays all configured listeners:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
index 16acf7a7db9c4..24c306c9d901d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
@@ -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 @@ protected function configure()
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 %command.name% displays the configured routes:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
index 1e2fefbbacb26..85ce52608d0d4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
@@ -31,6 +31,7 @@
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 @@ protected function configure()
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 %command.name% shows which routes match a given request and which don't and for what reason:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
index 1571c7f1b7c79..0ca168b5fd177 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php
@@ -27,6 +27,7 @@
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 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
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 %command.name% command decrypts all secrets and copies them in the local vault.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php
index e1c8904c698b5..d9a635f210391 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php
@@ -26,6 +26,7 @@
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 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
protected function configure()
{
$this
- ->setDescription('Encrypts all local secrets to the vault')
+ ->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The %command.name% command encrypts all locally overridden secrets to the vault.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php
index 18dba29ac9797..abd052918e2eb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php
@@ -29,6 +29,7 @@
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 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
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'
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php
index 9848ab993331e..f828776b16da3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php
@@ -30,6 +30,7 @@
final class SecretsListCommand extends Command
{
protected static $defaultName = 'secrets:list';
+ protected static $defaultDescription = 'Lists all secrets';
private $vault;
private $localVault;
@@ -45,7 +46,7 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
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 %command.name% command list all stored secrets.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php
index 2f06cb4592545..1ea079b3dc338 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php
@@ -29,6 +29,7 @@
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 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
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'
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php
index 95b8f6a0f622b..3753691a7379b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php
@@ -30,6 +30,7 @@
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 @@ public function __construct(AbstractVault $vault, AbstractVault $localVault = nu
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.')
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
index ec17387d9b078..8cb80babe61cb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
@@ -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 @@ protected function configure()
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 %command.name% command helps finding unused or missing translation
messages and comparing them with the fallback ones by inspecting the
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
index 9274d7e70baf6..2e4dd776b779b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
@@ -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 @@ protected function configure()
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 %command.name% command extracts translation strings from templates
of a given bundle or the default translations directory. It can display them or merge
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
index cec930da1c0da..d3cc460318e4b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php
@@ -30,6 +30,7 @@
class WorkflowDumpCommand extends Command
{
protected static $defaultName = 'workflow:dump';
+ protected static $defaultDescription = 'Dump a workflow';
/**
* {@inheritdoc}
@@ -43,7 +44,7 @@ protected function configure()
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 %command.name% command dumps the graphical representation of a
workflow in different formats
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php
index 81531599f1f6c..5aea86ba7a06b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php
@@ -62,76 +62,76 @@
->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 @@
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 @@
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 @@
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 @@
[], // 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 @@
[], // 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 @@
[], // 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')
;
};
diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
index de23fdd618a11..8352bc41a8b4c 100644
--- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
+++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
@@ -34,6 +34,7 @@
class UserPasswordEncoderCommand extends Command
{
protected static $defaultName = 'security:encode-password';
+ protected static $defaultDescription = 'Encodes a password';
private $encoderFactory;
private $userClasses;
@@ -52,7 +53,7 @@ public function __construct(EncoderFactoryInterface $encoderFactory, array $user
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.')
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.php
index a5ea6868a8bb6..61bc1f553e582 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.php
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.php
@@ -20,6 +20,6 @@
service('security.encoder_factory'),
abstract_arg('encoders user classes'),
])
- ->tag('console.command', ['command' => 'security:encode-password'])
+ ->tag('console.command')
;
};
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.php b/src/Symfony/Bundle/TwigBundle/Resources/config/console.php
index 9abd75da19ffc..0dc7ebdb7a5ad 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/console.php
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.php
@@ -24,10 +24,10 @@
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')
;
};
diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php
index 1b995abb20a59..440b93dc5c6fe 100644
--- a/src/Symfony/Component/Console/Application.php
+++ b/src/Symfony/Component/Console/Application.php
@@ -13,6 +13,7 @@
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 @@ public function add(Command $command)
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)));
diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md
index 17a709a6e27e7..37689ab692db1 100644
--- a/src/Symfony/Component/Console/CHANGELOG.md
+++ b/src/Symfony/Component/Console/CHANGELOG.md
@@ -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
-----
diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php
index b530f4d89fd2e..a1809acd2322a 100644
--- a/src/Symfony/Component/Console/Command/Command.php
+++ b/src/Symfony/Component/Console/Command/Command.php
@@ -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 @@ public static function getDefaultName()
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 @@ public function __construct(string $name = null)
$this->setName($name);
}
+ if ('' === $this->description) {
+ $this->setDescription(static::getDefaultDescription() ?? '');
+ }
+
$this->configure();
}
@@ -298,6 +318,8 @@ public function setCode(callable $code)
* 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 @@ public function getProcessedHelp()
*/
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;
}
diff --git a/src/Symfony/Component/Console/Command/LazyCommand.php b/src/Symfony/Component/Console/Command/LazyCommand.php
new file mode 100644
index 0000000000000..763133e81e12c
--- /dev/null
+++ b/src/Symfony/Component/Console/Command/LazyCommand.php
@@ -0,0 +1,211 @@
+
+ *
+ * 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
+ */
+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;
+ }
+}
diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php
index 77ae6f9d47869..42ec2eabad472 100644
--- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php
+++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php
@@ -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 @@ public function process(ContainerBuilder $container)
$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 @@ public function process(ContainerBuilder $container)
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 @@ public function process(ContainerBuilder $container)
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 @@ public function process(ContainerBuilder $container)
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
diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php
index 5e59f8fab3746..c0ecacd451e1d 100644
--- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php
+++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php
@@ -13,6 +13,7 @@
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\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 @@ public function visibilityProvider()
];
}
+ 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();
+ }
+}
diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php
index 4150feaf8ce85..9eac585dc8548 100644
--- a/src/Symfony/Component/Form/Command/DebugCommand.php
+++ b/src/Symfony/Component/Form/Command/DebugCommand.php
@@ -32,6 +32,7 @@
class DebugCommand extends Command
{
protected static $defaultName = 'debug:form';
+ protected static $defaultDescription = 'Displays form type information';
private $formRegistry;
private $namespaces;
@@ -64,7 +65,7 @@ protected function configure()
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 %command.name% command displays information about form types.
diff --git a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
index 03320b6f66e15..b289a29c0ef40 100644
--- a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
+++ b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
@@ -36,6 +36,7 @@
class ConsumeMessagesCommand extends Command
{
protected static $defaultName = 'messenger:consume';
+ protected static $defaultDescription = 'Consumes messages';
private $routableBus;
private $receiverLocator;
@@ -71,7 +72,7 @@ protected function configure(): void
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 %command.name% command consumes messages and dispatches them to the message bus.
diff --git a/src/Symfony/Component/Messenger/Command/DebugCommand.php b/src/Symfony/Component/Messenger/Command/DebugCommand.php
index 31b19d0bff948..047ceaf6ee18d 100644
--- a/src/Symfony/Component/Messenger/Command/DebugCommand.php
+++ b/src/Symfony/Component/Messenger/Command/DebugCommand.php
@@ -26,6 +26,7 @@
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 @@ protected function configure()
{
$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 %command.name% command displays all messages that can be
dispatched using the message buses:
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
index 951b7d499ed1b..df21b9bcd4f5a 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
@@ -27,6 +27,7 @@
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 @@ protected function configure(): void
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 %command.name% removes given messages that are pending in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
index 87426edd9dbaa..f56eeb3345b4d 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
@@ -35,6 +35,7 @@
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 @@ protected function configure(): void
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 %command.name% retries message in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
index bf8a72f906367..4a97159cf7539 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
@@ -28,6 +28,7 @@
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 @@ protected function configure(): void
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 %command.name% shows message that are pending in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php b/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
index 84395892fdf9b..71dd7ab5fd1a8 100644
--- a/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
+++ b/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
@@ -25,6 +25,7 @@
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 @@ protected function configure()
{
$this
->addArgument('transport', InputArgument::OPTIONAL, 'Name of the transport to setup', null)
- ->setDescription('Prepares the required infrastructure for the transport')
+ ->setDescription(self::$defaultDescription)
->setHelp(<<%command.name% command setups the transports:
diff --git a/src/Symfony/Component/Messenger/Command/StopWorkersCommand.php b/src/Symfony/Component/Messenger/Command/StopWorkersCommand.php
index 7df9b9d2014f0..c861513402b6a 100644
--- a/src/Symfony/Component/Messenger/Command/StopWorkersCommand.php
+++ b/src/Symfony/Component/Messenger/Command/StopWorkersCommand.php
@@ -25,6 +25,7 @@
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 @@ protected function configure(): void
{
$this
->setDefinition([])
- ->setDescription('Stops workers after their current message')
+ ->setDescription(self::$defaultDescription)
->setHelp(<<<'EOF'
The %command.name% command sends a signal to stop any messenger:consume processes that are running.
diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php
index dc2e9a9d936dd..f246b7ea33491 100644
--- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php
+++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php
@@ -31,6 +31,7 @@
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 @@ public function __construct(string $name = null, callable $directoryIteratorProv
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(<<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 %command.name% 'App\Entity\Dummy' command dumps the validators for the dummy class.
diff --git a/src/Symfony/Component/VarDumper/Command/ServerDumpCommand.php b/src/Symfony/Component/VarDumper/Command/ServerDumpCommand.php
index c8a61da98c5b6..8b50bc3c7f16e 100644
--- a/src/Symfony/Component/VarDumper/Command/ServerDumpCommand.php
+++ b/src/Symfony/Component/VarDumper/Command/ServerDumpCommand.php
@@ -35,6 +35,7 @@
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 @@ protected function configure()
$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'
%command.name% starts a dump server that collects and displays
dumps in a single place for debugging you application:
diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php
index 94a84b754d213..5375bf460d3c1 100644
--- a/src/Symfony/Component/Yaml/Command/LintCommand.php
+++ b/src/Symfony/Component/Yaml/Command/LintCommand.php
@@ -33,6 +33,7 @@
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 @@ public function __construct(string $name = null, callable $directoryIteratorProv
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')
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