diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 0c68c637f8c5..da98feb7632b 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -26,6 +26,8 @@ */ class DebugCommand extends Command { + protected static $defaultName = 'debug:twig'; + private $twig; /** @@ -66,7 +68,6 @@ protected function getTwigEnvironment() protected function configure() { $this - ->setName('debug:twig') ->setDefinition(array( new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index f96da4d615a2..b747ddaac025 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -31,6 +31,8 @@ */ class LintCommand extends Command { + protected static $defaultName = 'lint:twig'; + private $twig; /** @@ -71,7 +73,6 @@ protected function getTwigEnvironment() protected function configure() { $this - ->setName('lint:twig') ->setDescription('Lints a template and outputs encountered errors') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->addArgument('filename', InputArgument::IS_ARRAY) diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index e86b4ecddce8..14f734cdc80e 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -33,13 +33,14 @@ "symfony/security": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/web-link": "~3.3|~4.0" }, "conflict": { - "symfony/form": "<3.2.10|~3.3,<3.3.3" + "symfony/form": "<3.2.10|~3.3,<3.3.3", + "symfony/console": "<3.4" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 3b9130a8e40a..4a594d3ae70c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -28,15 +28,14 @@ */ class AboutCommand extends ContainerAwareCommand { + protected static $defaultName = 'about'; + /** * {@inheritdoc} */ protected function configure() { - $this - ->setName('about') - ->setDescription('Displays information about the current project') - ; + $this->setDescription('Displays information about the current project'); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index ffc770c7a5a6..e1adbe9e9325 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -35,6 +35,8 @@ class AssetsInstallCommand extends ContainerAwareCommand const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; const METHOD_RELATIVE_SYMLINK = 'relative symlink'; + protected static $defaultName = 'assets:install'; + private $filesystem; /** @@ -61,7 +63,6 @@ public function __construct($filesystem = null) protected function configure() { $this - ->setName('assets:install') ->setDefinition(array( new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'public'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 3429d99ed1f8..29fa61a5f44a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -32,6 +32,8 @@ */ class CacheClearCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:clear'; + private $cacheClearer; private $filesystem; private $warning; @@ -62,7 +64,6 @@ public function __construct($cacheClearer = null, Filesystem $filesystem = null) protected function configure() { $this - ->setName('cache:clear') ->setDefinition(array( 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)'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index fec933f67b9c..dedd61e66811 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -25,6 +25,8 @@ */ final class CachePoolClearCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:pool:clear'; + private $poolClearer; /** @@ -51,7 +53,6 @@ public function __construct($poolClearer = null) protected function configure() { $this - ->setName('cache:pool:clear') ->setDefinition(array( new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php index 741979bd4f50..1c9cef9b93ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php @@ -24,6 +24,8 @@ */ final class CachePoolPruneCommand extends Command { + protected static $defaultName = 'cache:pool:prune'; + private $pools; /** @@ -42,7 +44,6 @@ public function __construct($pools) protected function configure() { $this - ->setName('cache:pool:prune') ->setDescription('Prune cache pools') ->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 57972782dc77..1ff474e96939 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -26,6 +26,8 @@ */ class CacheWarmupCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:warmup'; + private $cacheWarmer; /** @@ -52,7 +54,6 @@ public function __construct($cacheWarmer = null) protected function configure() { $this - ->setName('cache:warmup') ->setDefinition(array( new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index f460fd5f09a3..5a55332b334f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -28,13 +28,14 @@ */ class ConfigDebugCommand extends AbstractConfigCommand { + protected static $defaultName = 'debug:config'; + /** * {@inheritdoc} */ protected function configure() { $this - ->setName('debug:config') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index fb51f8c3fcf0..62bdfec8c9c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -30,13 +30,14 @@ */ class ConfigDumpReferenceCommand extends AbstractConfigCommand { + protected static $defaultName = 'config:dump-reference'; + /** * {@inheritdoc} */ protected function configure() { $this - ->setName('config:dump-reference') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 51c04969877e..ed859880cb00 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -32,6 +32,8 @@ */ class ContainerDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:container'; + /** * @var ContainerBuilder|null */ @@ -43,7 +45,6 @@ class ContainerDebugCommand extends ContainerAwareCommand protected function configure() { $this - ->setName('debug:container') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), new InputOption('show-private', null, InputOption::VALUE_NONE, 'Used to show public *and* private services'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index 18aa08575c4e..a36878d44533 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -28,6 +28,7 @@ */ class EventDispatcherDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:event-dispatcher'; private $dispatcher; /** @@ -54,7 +55,6 @@ public function __construct($dispatcher = null) protected function configure() { $this - ->setName('debug:event-dispatcher') ->setDefinition(array( new InputArgument('event', InputArgument::OPTIONAL, 'An event name'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 2a005090322d..03b227a731ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -32,6 +32,7 @@ */ class RouterDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:router'; private $router; /** @@ -79,7 +80,6 @@ public function isEnabled() protected function configure() { $this - ->setName('debug:router') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index f88d2a2dfe0c..ee5c4990a487 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -29,6 +29,8 @@ */ class RouterMatchCommand extends ContainerAwareCommand { + protected static $defaultName = 'router:match'; + private $router; /** @@ -76,7 +78,6 @@ public function isEnabled() protected function configure() { $this - ->setName('router:match') ->setDefinition(array( new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Sets the HTTP method'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index f8e69a3c4a64..cbf6bda5f3ff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -40,6 +40,8 @@ class TranslationDebugCommand extends ContainerAwareCommand const MESSAGE_UNUSED = 1; const MESSAGE_EQUALS_FALLBACK = 2; + protected static $defaultName = 'debug:translation'; + private $translator; private $loader; private $extractor; @@ -72,7 +74,6 @@ public function __construct($translator = null, TranslationLoader $loader = null protected function configure() { $this - ->setName('debug:translation') ->setDefinition(array( new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index a580315efdaa..abbe1e3b5460 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -33,6 +33,8 @@ */ class TranslationUpdateCommand extends ContainerAwareCommand { + protected static $defaultName = 'translation:update'; + private $writer; private $loader; private $extractor; @@ -68,7 +70,6 @@ public function __construct($writer = null, TranslationLoader $loader = null, Ex protected function configure() { $this - ->setName('translation:update') ->setDefinition(array( new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 27e0f645d8fd..9923f657794f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -25,6 +25,8 @@ */ class WorkflowDumpCommand extends ContainerAwareCommand { + protected static $defaultName = 'workflow:dump'; + /** * {@inheritdoc} * @@ -41,7 +43,6 @@ public function isEnabled() protected function configure() { $this - ->setName('workflow:dump') ->setDefinition(array( new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index 36876dee2425..2093c3d26230 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -24,6 +24,8 @@ */ class XliffLintCommand extends BaseLintCommand { + protected static $defaultName = 'lint:xliff'; + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { if (func_num_args()) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index f6c1a7f85b19..e54a0058cabc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -23,6 +23,8 @@ */ class YamlLintCommand extends BaseLintCommand { + protected static $defaultName = 'lint:yaml'; + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { if (func_num_args()) { diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index 597df8ceb9de..c8ccac32cab5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -27,6 +27,8 @@ */ class InitAclCommand extends ContainerAwareCommand { + protected static $defaultName = 'init:acl'; + private $connection; private $schema; @@ -70,7 +72,6 @@ public function isEnabled() protected function configure() { $this - ->setName('init:acl') ->setDescription('Mounts ACL tables in the database') ->setHelp(<<<'EOF' The %command.name% command mounts ACL tables in the database. diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index 840e74edfba8..bdb293a4ec6f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -32,6 +32,8 @@ */ class SetAclCommand extends ContainerAwareCommand { + protected static $defaultName = 'acl:set'; + private $provider; /** @@ -80,7 +82,6 @@ public function isEnabled() protected function configure() { $this - ->setName('acl:set') ->setDescription('Sets ACL for objects') ->setHelp(<<%command.name% command sets ACL. diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index 1f6a5d3c6213..c93cb4987f48 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\User\User; @@ -33,6 +32,8 @@ */ class UserPasswordEncoderCommand extends ContainerAwareCommand { + protected static $defaultName = 'security:encode-password'; + private $encoderFactory; private $userClasses; @@ -54,7 +55,6 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra protected function configure() { $this - ->setName('security:encode-password') ->setDescription('Encodes a password.') ->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.') diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 1ceaca100201..5ecbf47078af 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -20,7 +20,6 @@ * file that was distributed with this source code. */ use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\SecurityBundle\Command\InitAclCommand; use Symfony\Bundle\SecurityBundle\Command\SetAclCommand; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; @@ -170,7 +169,6 @@ private function getApplication() $kernel->boot(); $application = new Application($kernel); - $application->add(new InitAclCommand($kernel->getContainer()->get('security.acl.dbal.connection'), $kernel->getContainer()->get('security.acl.dbal.schema'))); $initAclCommand = $application->find('init:acl'); $initAclCommandTester = new CommandTester($initAclCommand); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index b1421742766d..38bf0220536d 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -26,7 +26,7 @@ "require-dev": { "symfony/asset": "~2.8|~3.0|~4.0", "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/console": "~3.2|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", @@ -47,7 +47,8 @@ }, "conflict": { "symfony/var-dumper": "<3.3", - "symfony/event-dispatcher": "<3.3.1" + "symfony/event-dispatcher": "<3.3.1", + "symfony/console": "<3.4" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 0c147a605ccb..24d7ff7af40e 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -7,6 +7,10 @@ CHANGELOG * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 `ContainerCommandLoader` for commands lazy-loading * added a case-insensitive command name matching fallback + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 6620ff5718c5..bd7059602d2f 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -29,6 +29,11 @@ */ class Command { + /** + * @var string|null The default command name + */ + protected static $defaultName; + private $application; private $name; private $processTitle; @@ -45,6 +50,17 @@ class Command private $usages = array(); private $helperSet; + /** + * @return string|null The default command name or null when no default name is set + */ + public static function getDefaultName() + { + $class = get_called_class(); + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + /** * Constructor. * @@ -56,7 +72,7 @@ public function __construct($name = null) { $this->definition = new InputDefinition(); - if (null !== $name) { + if (null !== $name || null !== $name = static::getDefaultName()) { $this->setName($name); } diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 67034098c218..add7c5d0df49 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -46,16 +46,21 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition($id); $class = $container->getParameterBag()->resolveValue($definition->getClass()); - 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)); - } - $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (!isset($tags[0]['command'])) { + if (isset($tags[0]['command'])) { + $commandName = $tags[0]['command']; + } else { + 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)); + } + $commandName = $class::getDefaultName(); + } + + if (null === $commandName) { if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { $commandId = $commandId.'_'.$id; } @@ -69,7 +74,6 @@ public function process(ContainerBuilder $container) } $serviceIds[$commandId] = false; - $commandName = $tags[0]['command']; unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index ddcee80145e5..807eb389730f 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -77,6 +77,38 @@ public function testProcessRegistersLazyCommands() $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); } + public function testProcessFallsBackToDefaultName() + { + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->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(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); + $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => false), $container->getParameter('console.command.ids')); + + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->addTag('console.command', array('command' => 'new-name')) + ; + + $pass->process($container); + + $this->assertSame(array('new-name' => 'with-default-name'), $container->getDefinition('console.command_loader')->getArgument(1)); + } + public function visibilityProvider() { return array( @@ -96,7 +128,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsAbstract() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); - $definition->addTag('console.command', array('command' => 'my:command')); + $definition->addTag('console.command'); $definition->setAbstract(true); $container->setDefinition('my-command', $definition); @@ -114,7 +146,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('SplObjectStorage'); - $definition->addTag('console.command', array('command' => 'my:command')); + $definition->addTag('console.command'); $container->setDefinition('my-command', $definition); $container->compile(); @@ -146,3 +178,8 @@ public function testProcessPrivateServicesWithSameCommand() class MyCommand extends Command { } + +class NamedCommand extends Command +{ + protected static $defaultName = 'default'; +} diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php index 80d8bb25dca2..fead5edcb18b 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -26,6 +26,8 @@ */ class XliffLintCommand extends Command { + protected static $defaultName = 'lint:xliff'; + private $format; private $displayCorrectFiles; private $directoryIteratorProvider; @@ -45,7 +47,6 @@ public function __construct($name = null, $directoryIteratorProvider = null, $is protected function configure() { $this - ->setName('lint:xliff') ->setDescription('Lints a XLIFF file and outputs encountered errors') ->addArgument('filename', null, 'A file or a directory or STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 36025bdebb8b..202291551b57 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -28,6 +28,8 @@ */ class LintCommand extends Command { + protected static $defaultName = 'lint:yaml'; + private $parser; private $format; private $displayCorrectFiles; @@ -48,7 +50,6 @@ public function __construct($name = null, $directoryIteratorProvider = null, $is protected function configure() { $this - ->setName('lint:yaml') ->setDescription('Lints a file and outputs encountered errors') ->addArgument('filename', null, 'A file or a directory or STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 41f04fb9f954..a31a2cef426e 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -19,7 +19,10 @@ "php": "^5.5.9|>=7.0.8" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0" + "symfony/console": "~3.4|~4.0" + }, + "conflict": { + "symfony/console": "<3.4" }, "suggest": { "symfony/console": "For validating YAML files using the lint command"