From 22b65f3ff5daecbec3c16916a549a0da60f8d7c7 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Thu, 27 Nov 2025 22:43:00 +0100 Subject: [PATCH 01/12] feat: updated MakeCommand to create InvokableCommand by default --- config/help/MakeCommand.txt | 4 ++ src/Maker/MakeCommand.php | 72 ++++++++++++++++------ templates/command/InvokableCommand.tpl.php | 32 ++++++++++ 3 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 templates/command/InvokableCommand.tpl.php diff --git a/config/help/MakeCommand.txt b/config/help/MakeCommand.txt index a88b9d430..8b4ac41ee 100644 --- a/config/help/MakeCommand.txt +++ b/config/help/MakeCommand.txt @@ -3,3 +3,7 @@ The %command.name% command generates a new command: php %command.full_name% app:do-something If the argument is missing, the command will ask for the command name interactively. + +Symfony can also generate the command with the old structure (configure and execute method) instead of an invokable command. + +php %command.full_name% --old-structure \ No newline at end of file diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 52d331c53..662d9af30 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -18,13 +18,16 @@ use Symfony\Bundle\MakerBundle\Str; use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; use Symfony\Bundle\MakerBundle\Util\UseStatementGenerator; +use Symfony\Component\Console\Attribute\Argument; use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Attribute\Option; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\LazyCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Style\SymfonyStyle; /** @@ -58,10 +61,23 @@ public function configureCommand(Command $command, InputConfiguration $inputConf { $command ->addArgument('name', InputArgument::OPTIONAL, \sprintf('Choose a command name (e.g. app:%s)', Str::asCommand(Str::getRandomTerm()))) + ->addOption('old-structure', null, InputOption::VALUE_NONE, 'Generate the command with the old structure (configure and execute method) instead of an invokable command?') ->setHelp($this->getHelpFileContents('MakeCommand.txt')) ; } + public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void + { + if (!$input->getOption('old-structure')) + { + $description = $command->getDefinition()->getOption('old-structure')->getDescription(); + $question = new ConfirmationQuestion($description, false); + $isUsingOldStructure = $io->askQuestion($question); + + $input->setOption('old-structure', $isUsingOldStructure); + } + } + public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void { $commandName = trim($input->getArgument('name')); @@ -74,25 +90,45 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen \sprintf('The "%s" command name is not valid because it would be implemented by "%s" class, which is not valid as a PHP class name (it must start with a letter or underscore, followed by any number of letters, numbers, or underscores).', $commandName, Str::asClassName($commandName, 'Command')) ); - $useStatements = new UseStatementGenerator([ - Command::class, - InputArgument::class, - InputInterface::class, - InputOption::class, - OutputInterface::class, - SymfonyStyle::class, - AsCommand::class, - ]); + if ($input->getOption('old-structure')) { + $useStatements = new UseStatementGenerator([ + Command::class, + InputArgument::class, + InputInterface::class, + InputOption::class, + OutputInterface::class, + SymfonyStyle::class, + AsCommand::class, + ]); - $generator->generateClass( - $commandClassNameDetails->getFullName(), - 'command/Command.tpl.php', - [ - 'use_statements' => $useStatements, - 'command_name' => $commandName, - 'set_description' => !class_exists(LazyCommand::class), - ] - ); + $generator->generateClass( + $commandClassNameDetails->getFullName(), + 'command/Command.tpl.php', + [ + 'use_statements' => $useStatements, + 'command_name' => $commandName, + 'set_description' => !class_exists(LazyCommand::class), + ] + ); + + } else { + $useStatements = new UseStatementGenerator([ + Command::class, + SymfonyStyle::class, + AsCommand::class, + Argument::class, + Option::class, + ]); + + $generator->generateClass( + $commandClassNameDetails->getFullName(), + 'command/InvokableCommand.tpl.php', + [ + 'use_statements' => $useStatements, + 'command_name' => $commandName, + ] + ); + } $generator->writeChanges(); diff --git a/templates/command/InvokableCommand.tpl.php b/templates/command/InvokableCommand.tpl.php new file mode 100644 index 000000000..7a0e06ac5 --- /dev/null +++ b/templates/command/InvokableCommand.tpl.php @@ -0,0 +1,32 @@ + + +namespace ; + + + +#[AsCommand( + name: '', + description: 'Add a short description for your command', +)] +class +{ + public function __invoke( + SymfonyStyle $symfonyStyle, + #[Argument('Required argument description')] string $requiredArg, + #[Argument('Optional nullable argument description')] ?string $optionalNullableArg, + #[Argument('Optional non-nullable argument description')] int $optionalNonNullableArg = 1, + #[Option('Option description')] string $option = "defaultOptionValue", + #[Option('Nullable option description')] ?string $nullableOption = null, + ): int + { + $symfonyStyle->note(sprintf('The value of $requiredArg is: %s', $requiredArg)); + $symfonyStyle->note(sprintf('The value of $optionalNullableArg is: %s', $optionalNullableArg)); + $symfonyStyle->note(sprintf('The value of $optionalNonNullableArg is: %s', $optionalNonNullableArg)); + $symfonyStyle->note(sprintf('The value of $option is: %s', $option)); + $symfonyStyle->note(sprintf('The value of $nullableOption is: %s', $nullableOption)); + + $symfonyStyle->success('You have a new command! Now make it your own! Pass --help to see your options.'); + + return Command::SUCCESS; + } +} From 81437a7da30440de785428ddcaa1df2158eaadff Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Thu, 27 Nov 2025 22:55:01 +0100 Subject: [PATCH 02/12] style: updated code style to satisfy PHP-CS-Fixer --- src/Maker/MakeCommand.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 662d9af30..22bd24a1a 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -68,8 +68,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void { - if (!$input->getOption('old-structure')) - { + if (!$input->getOption('old-structure')) { $description = $command->getDefinition()->getOption('old-structure')->getDescription(); $question = new ConfirmationQuestion($description, false); $isUsingOldStructure = $io->askQuestion($question); @@ -110,7 +109,6 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen 'set_description' => !class_exists(LazyCommand::class), ] ); - } else { $useStatements = new UseStatementGenerator([ Command::class, From 20c0a4bffc4b4d9aeeb6d94f0f40360c75fcd07c Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Thu, 27 Nov 2025 23:13:01 +0100 Subject: [PATCH 03/12] test: updated MakeCommandTest --- tests/Maker/MakeCommandTest.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/Maker/MakeCommandTest.php b/tests/Maker/MakeCommandTest.php index 1ff279c19..5cdeeb267 100644 --- a/tests/Maker/MakeCommandTest.php +++ b/tests/Maker/MakeCommandTest.php @@ -25,11 +25,26 @@ protected function getMakerClass(): string public function getTestDetails(): \Generator { - yield 'it_makes_a_command_no_attributes' => [$this->createMakerTest() + yield 'it_makes_an_invokable_command_no_attributes' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { $runner->runMaker([ // command name 'app:foo', + // create invokable command by default + '' + ]); + + $this->runCommandTest($runner, 'it_makes_a_command.php'); + }), + ]; + + yield 'it_makes_an_old_structured_command_no_attributes' => [$this->createMakerTest() + ->run(function (MakerTestRunner $runner) { + $runner->runMaker([ + // command name + 'app:foo', + // create invokable command by default + 'yes' ]); $this->runCommandTest($runner, 'it_makes_a_command.php'); @@ -41,6 +56,8 @@ public function getTestDetails(): \Generator $runner->runMaker([ // command name 'app:foo', + // create invokable command by default + '' ]); $this->runCommandTest($runner, 'it_makes_a_command.php'); @@ -63,6 +80,8 @@ public function getTestDetails(): \Generator $runner->runMaker([ // command name 'app:foo', + // create invokable command by default + '' ]); $this->runCommandTest($runner, 'it_makes_a_command_in_custom_namespace.php'); From 690fd4de00a8ac30b97ff6ac76dab92fd22baedd Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Thu, 27 Nov 2025 23:17:30 +0100 Subject: [PATCH 04/12] style: updated code style to satisfy PHP-CS-Fixer --- tests/Maker/MakeCommandTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Maker/MakeCommandTest.php b/tests/Maker/MakeCommandTest.php index 5cdeeb267..3776e08a7 100644 --- a/tests/Maker/MakeCommandTest.php +++ b/tests/Maker/MakeCommandTest.php @@ -31,7 +31,7 @@ public function getTestDetails(): \Generator // command name 'app:foo', // create invokable command by default - '' + '', ]); $this->runCommandTest($runner, 'it_makes_a_command.php'); @@ -44,7 +44,7 @@ public function getTestDetails(): \Generator // command name 'app:foo', // create invokable command by default - 'yes' + 'yes', ]); $this->runCommandTest($runner, 'it_makes_a_command.php'); @@ -57,7 +57,7 @@ public function getTestDetails(): \Generator // command name 'app:foo', // create invokable command by default - '' + '', ]); $this->runCommandTest($runner, 'it_makes_a_command.php'); @@ -81,7 +81,7 @@ public function getTestDetails(): \Generator // command name 'app:foo', // create invokable command by default - '' + '', ]); $this->runCommandTest($runner, 'it_makes_a_command_in_custom_namespace.php'); From ff0b82ace6eea31b78d81b6a58372962e8eaf54e Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 11:02:20 +0100 Subject: [PATCH 05/12] docs: updated commend in MakeCommandTest --- tests/Maker/MakeCommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Maker/MakeCommandTest.php b/tests/Maker/MakeCommandTest.php index 3776e08a7..65e5cde35 100644 --- a/tests/Maker/MakeCommandTest.php +++ b/tests/Maker/MakeCommandTest.php @@ -43,7 +43,7 @@ public function getTestDetails(): \Generator $runner->runMaker([ // command name 'app:foo', - // create invokable command by default + // create a command with the old structure by default 'yes', ]); From a1316062199ae3bce08e7c571483e2f768ff8166 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 11:20:18 +0100 Subject: [PATCH 06/12] refactor: updated method parameters for InvokableCommand --- templates/command/InvokableCommand.tpl.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/templates/command/InvokableCommand.tpl.php b/templates/command/InvokableCommand.tpl.php index 7a0e06ac5..63e95ffd1 100644 --- a/templates/command/InvokableCommand.tpl.php +++ b/templates/command/InvokableCommand.tpl.php @@ -11,21 +11,21 @@ class { public function __invoke( - SymfonyStyle $symfonyStyle, - #[Argument('Required argument description')] string $requiredArg, + SymfonyStyle $io, + #[Argument('Required argument description')] string $requiredArg, #[Argument('Optional nullable argument description')] ?string $optionalNullableArg, - #[Argument('Optional non-nullable argument description')] int $optionalNonNullableArg = 1, - #[Option('Option description')] string $option = "defaultOptionValue", - #[Option('Nullable option description')] ?string $nullableOption = null, + #[Argument('Optional non-nullable argument description')] int $optionalNonNullableArg = 1, + #[Option('Option description')] string $option = "defaultOptionValue", + #[Option('Nullable option description')] ?string $nullableOption = null, ): int { - $symfonyStyle->note(sprintf('The value of $requiredArg is: %s', $requiredArg)); - $symfonyStyle->note(sprintf('The value of $optionalNullableArg is: %s', $optionalNullableArg)); - $symfonyStyle->note(sprintf('The value of $optionalNonNullableArg is: %s', $optionalNonNullableArg)); - $symfonyStyle->note(sprintf('The value of $option is: %s', $option)); - $symfonyStyle->note(sprintf('The value of $nullableOption is: %s', $nullableOption)); + $io->note(sprintf('The value of $requiredArg is: %s', $requiredArg)); + $io->note(sprintf('The value of $optionalNullableArg is: %s', $optionalNullableArg)); + $io->note(sprintf('The value of $optionalNonNullableArg is: %s', $optionalNonNullableArg)); + $io->note(sprintf('The value of $option is: %s', $option)); + $io->note(sprintf('The value of $nullableOption is: %s', $nullableOption)); - $symfonyStyle->success('You have a new command! Now make it your own! Pass --help to see your options.'); + $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); return Command::SUCCESS; } From d27d248e5339d224b30f67d832dd8bce61585a42 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 14:04:23 +0100 Subject: [PATCH 07/12] feat: changed old-structure option to negatable 'invokeable' option --- config/help/MakeCommand.txt | 2 +- src/Maker/MakeCommand.php | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/config/help/MakeCommand.txt b/config/help/MakeCommand.txt index 8b4ac41ee..f555cd4f0 100644 --- a/config/help/MakeCommand.txt +++ b/config/help/MakeCommand.txt @@ -6,4 +6,4 @@ If the argument is missing, the command will ask for the command name interactiv Symfony can also generate the command with the old structure (configure and execute method) instead of an invokable command. -php %command.full_name% --old-structure \ No newline at end of file +php %command.full_name% --invokable \ No newline at end of file diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 22bd24a1a..d093828b3 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -29,6 +29,8 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\Kernel; + /** * @author Javier Eguiluz @@ -61,19 +63,19 @@ public function configureCommand(Command $command, InputConfiguration $inputConf { $command ->addArgument('name', InputArgument::OPTIONAL, \sprintf('Choose a command name (e.g. app:%s)', Str::asCommand(Str::getRandomTerm()))) - ->addOption('old-structure', null, InputOption::VALUE_NONE, 'Generate the command with the old structure (configure and execute method) instead of an invokable command?') + ->addOption('invokable', null, InputOption::VALUE_NEGATABLE, 'Generate an invokable command instead of a command with the old structure (configure and execute method)?') ->setHelp($this->getHelpFileContents('MakeCommand.txt')) ; } public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void { - if (!$input->getOption('old-structure')) { - $description = $command->getDefinition()->getOption('old-structure')->getDescription(); - $question = new ConfirmationQuestion($description, false); + if (!$input->getOption('invokable')) { + $description = $command->getDefinition()->getOption('invokable')->getDescription(); + $question = new ConfirmationQuestion($description, Kernel::VERSION_ID >= 70300); $isUsingOldStructure = $io->askQuestion($question); - $input->setOption('old-structure', $isUsingOldStructure); + $input->setOption('invokable', $isUsingOldStructure); } } @@ -89,41 +91,41 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen \sprintf('The "%s" command name is not valid because it would be implemented by "%s" class, which is not valid as a PHP class name (it must start with a letter or underscore, followed by any number of letters, numbers, or underscores).', $commandName, Str::asClassName($commandName, 'Command')) ); - if ($input->getOption('old-structure')) { + if ($input->getOption('invokable')) { $useStatements = new UseStatementGenerator([ Command::class, - InputArgument::class, - InputInterface::class, - InputOption::class, - OutputInterface::class, SymfonyStyle::class, AsCommand::class, + Argument::class, + Option::class, ]); $generator->generateClass( $commandClassNameDetails->getFullName(), - 'command/Command.tpl.php', + 'command/InvokableCommand.tpl.php', [ 'use_statements' => $useStatements, 'command_name' => $commandName, - 'set_description' => !class_exists(LazyCommand::class), ] ); } else { $useStatements = new UseStatementGenerator([ Command::class, + InputArgument::class, + InputInterface::class, + InputOption::class, + OutputInterface::class, SymfonyStyle::class, AsCommand::class, - Argument::class, - Option::class, ]); $generator->generateClass( $commandClassNameDetails->getFullName(), - 'command/InvokableCommand.tpl.php', + 'command/Command.tpl.php', [ 'use_statements' => $useStatements, 'command_name' => $commandName, + 'set_description' => !class_exists(LazyCommand::class), ] ); } From 50c9802752490118be4f82b7946ea0682dde7ad7 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 14:32:46 +0100 Subject: [PATCH 08/12] feat: updated MakeCommand->interact method --- src/Maker/MakeCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index d093828b3..5c12142f1 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -70,7 +70,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void { - if (!$input->getOption('invokable')) { + if ($input->getOption('invokable') === null) { $description = $command->getDefinition()->getOption('invokable')->getDescription(); $question = new ConfirmationQuestion($description, Kernel::VERSION_ID >= 70300); $isUsingOldStructure = $io->askQuestion($question); From 29084d34970b576db5f49e7238aeb955651ec98f Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 15:16:41 +0100 Subject: [PATCH 09/12] refactor: simplified InvokableCommand template --- templates/command/InvokableCommand.tpl.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/templates/command/InvokableCommand.tpl.php b/templates/command/InvokableCommand.tpl.php index 63e95ffd1..40cabb02b 100644 --- a/templates/command/InvokableCommand.tpl.php +++ b/templates/command/InvokableCommand.tpl.php @@ -12,18 +12,12 @@ class { public function __invoke( SymfonyStyle $io, - #[Argument('Required argument description')] string $requiredArg, - #[Argument('Optional nullable argument description')] ?string $optionalNullableArg, - #[Argument('Optional non-nullable argument description')] int $optionalNonNullableArg = 1, - #[Option('Option description')] string $option = "defaultOptionValue", - #[Option('Nullable option description')] ?string $nullableOption = null, + #[Argument('Argument description')] string $arg, + #[Option('Option description')] bool $enable = false", ): int { - $io->note(sprintf('The value of $requiredArg is: %s', $requiredArg)); - $io->note(sprintf('The value of $optionalNullableArg is: %s', $optionalNullableArg)); - $io->note(sprintf('The value of $optionalNonNullableArg is: %s', $optionalNonNullableArg)); - $io->note(sprintf('The value of $option is: %s', $option)); - $io->note(sprintf('The value of $nullableOption is: %s', $nullableOption)); + $io->note(sprintf('The value of $arg is: %s', $arg)); + $io->note(sprintf('The value of $enable is: %s', $enable ? 'true' : 'false')); $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); From ead2e490437606fcfbcb493dacaa2efd3b6fdda5 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 15:18:36 +0100 Subject: [PATCH 10/12] style: updated code style of invokable command template --- templates/command/InvokableCommand.tpl.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/command/InvokableCommand.tpl.php b/templates/command/InvokableCommand.tpl.php index 40cabb02b..3a775bfe2 100644 --- a/templates/command/InvokableCommand.tpl.php +++ b/templates/command/InvokableCommand.tpl.php @@ -14,8 +14,7 @@ public function __invoke( SymfonyStyle $io, #[Argument('Argument description')] string $arg, #[Option('Option description')] bool $enable = false", - ): int - { + ): int { $io->note(sprintf('The value of $arg is: %s', $arg)); $io->note(sprintf('The value of $enable is: %s', $enable ? 'true' : 'false')); From 0588d4d66d86aef52aac08900e28ea8d0edb3bd1 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 15:19:50 +0100 Subject: [PATCH 11/12] refactor: renamed variable --- src/Maker/MakeCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 5c12142f1..8421ac597 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -73,9 +73,9 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma if ($input->getOption('invokable') === null) { $description = $command->getDefinition()->getOption('invokable')->getDescription(); $question = new ConfirmationQuestion($description, Kernel::VERSION_ID >= 70300); - $isUsingOldStructure = $io->askQuestion($question); + $invokable = $io->askQuestion($question); - $input->setOption('invokable', $isUsingOldStructure); + $input->setOption('invokable', $invokable); } } From ce19ba3c01e84b2dfb60a988bab09e849f231025 Mon Sep 17 00:00:00 2001 From: Basil Baumgartner Date: Fri, 28 Nov 2025 15:21:15 +0100 Subject: [PATCH 12/12] feat: updated invokable option description for make:command --- src/Maker/MakeCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Maker/MakeCommand.php b/src/Maker/MakeCommand.php index 8421ac597..34cafb177 100644 --- a/src/Maker/MakeCommand.php +++ b/src/Maker/MakeCommand.php @@ -63,7 +63,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf { $command ->addArgument('name', InputArgument::OPTIONAL, \sprintf('Choose a command name (e.g. app:%s)', Str::asCommand(Str::getRandomTerm()))) - ->addOption('invokable', null, InputOption::VALUE_NEGATABLE, 'Generate an invokable command instead of a command with the old structure (configure and execute method)?') + ->addOption('invokable', null, InputOption::VALUE_NEGATABLE, 'Generate an invokable command (using PHP attributes) starting from Symfony 7.3?') ->setHelp($this->getHelpFileContents('MakeCommand.txt')) ; }