[Console] enable describing commands in ways that make the list
command lazy
This commit is contained in:
parent
28533aa43c
commit
8a1a1b8171
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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')
|
||||
|
@ -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');
|
||||
}
|
||||
};
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.')
|
||||
;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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.
|
||||
|
@ -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'
|
||||
|
@ -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.')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
;
|
||||
};
|
||||
|
@ -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.')
|
||||
|
@ -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')
|
||||
;
|
||||
};
|
||||
|
@ -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')
|
||||
;
|
||||
};
|
||||
|
@ -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)));
|
||||
|
@ -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
|
||||
-----
|
||||
|
@ -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;
|
||||
}
|
||||
|
211
src/Symfony/Component/Console/Command/LazyCommand.php
Normal file
211
src/Symfony/Component/Console/Command/LazyCommand.php
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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')
|
||||
|
Reference in New Issue
Block a user