Browse Source

Display help text for a subcommand when no parser is defined.

When a subcommand has no sub-parser, we should inherit the options and
arguments of the parent parser, but overwrite the description text and
omit the subcommands, as parser-less subcommands can't have subcommands.

Refs #12325
Mark Story 7 years ago
parent
commit
cc76f51dab

+ 8 - 1
src/Console/ConsoleOptionParser.php

@@ -805,8 +805,15 @@ class ConsoleOptionParser
         if (isset($this->_subcommands[$subcommand])) {
             $command = $this->_subcommands[$subcommand];
             $subparser = $command->parser();
+
+            // Generate a parser as the subcommand didn't define one.
             if (!($subparser instanceof self)) {
-                $subparser = clone $this;
+                // $subparser = clone $this;
+                $subparser = new self($subcommand);
+                $subparser
+                    ->setDescription($command->getRawHelp())
+                    ->addOptions($this->options())
+                    ->addArguments($this->arguments());
             }
             if (strlen($subparser->getDescription()) === 0) {
                 $subparser->setDescription($command->getRawHelp());

+ 75 - 24
tests/TestCase/Console/ConsoleOptionParserTest.php

@@ -652,30 +652,6 @@ class ConsoleOptionParserTest extends TestCase
     }
 
     /**
-     * Test addSubcommand inherits options as no
-     * parser is created.
-     *
-     * @return void
-     */
-    public function testAddSubcommandInheritOptions()
-    {
-        $parser = new ConsoleOptionParser('test', false);
-        $parser->addSubcommand('build', [
-            'help' => 'Build things'
-        ])->addOption('connection', [
-            'short' => 'c',
-            'default' => 'default'
-        ])->addArgument('name', ['required' => false]);
-
-        $result = $parser->parse(['build']);
-        $this->assertEquals('default', $result[0]['connection']);
-
-        $result = $parser->subcommands();
-        $this->assertArrayHasKey('build', $result);
-        $this->assertFalse($result['build']->parser(), 'No parser should be created');
-    }
-
-    /**
      * test addSubcommand with an object.
      *
      * @return void
@@ -790,6 +766,46 @@ TEXT;
     }
 
     /**
+     * Test addSubcommand inherits options as no
+     * parser is created.
+     *
+     * @return void
+     */
+    public function testHelpSubcommandInheritOptions()
+    {
+        $parser = new ConsoleOptionParser('mycommand', false);
+        $parser->addSubcommand('build', [
+            'help' => 'Build things.'
+        ])->addSubcommand('destroy', [
+            'help' => 'Destroy things.'
+        ])->addOption('connection', [
+            'help' => 'Db connection.',
+            'short' => 'c',
+        ])->addArgument('name', ['required' => false]);
+
+        $result = $parser->help('build');
+        $expected = <<<TEXT
+Build things.
+
+<info>Usage:</info>
+cake mycommand build [-c] [-h] [-q] [-v] [<name>]
+
+<info>Options:</info>
+
+--connection, -c  Db connection.
+--help, -h        Display this help.
+--quiet, -q       Enable quiet output.
+--verbose, -v     Enable verbose output.
+
+<info>Arguments:</info>
+
+name   <comment>(optional)</comment>
+
+TEXT;
+        $this->assertTextEquals($expected, $result, 'Help is not correct.');
+    }
+
+    /**
      * test that help() with a command param shows the help for a subcommand
      *
      * @return void
@@ -833,6 +849,41 @@ TEXT;
     }
 
     /**
+     * test that help() with a command param shows the help for a subcommand
+     *
+     * @return void
+     */
+    public function testHelpSubcommandInheritParser()
+    {
+        $subParser = new ConsoleOptionParser('method', false);
+        $subParser->addOption('connection', ['help' => 'Db connection.']);
+        $subParser->addOption('zero', ['short' => '0', 'help' => 'Zero.']);
+
+        $parser = new ConsoleOptionParser('mycommand', false);
+        $parser->addSubcommand('method', [
+                'help' => 'This is another command',
+                'parser' => $subParser
+            ])
+            ->addOption('test', ['help' => 'A test option.']);
+
+        $result = $parser->help('method');
+        $expected = <<<TEXT
+This is another command
+
+<info>Usage:</info>
+cake mycommand method [--connection] [-h] [-0]
+
+<info>Options:</info>
+
+--connection      Db connection.
+--help, -h        Display this help.
+--zero, -0        Zero.
+
+TEXT;
+        $this->assertTextEquals($expected, $result, 'Help is not correct.');
+    }
+
+    /**
      * test that help() with a custom rootName
      *
      * @return void