Browse Source

Add basic option parser integration.

I wanted to avoid needing to call parent for building option parsers.
Instead people will be able to completely replace the buildOptionParser
method and not call parent.
Mark Story 8 years ago
parent
commit
186d74849d
2 changed files with 86 additions and 9 deletions
  1. 49 4
      src/Console/Command.php
  2. 37 5
      tests/TestCase/Console/CommandTest.php

+ 49 - 4
src/Console/Command.php

@@ -17,6 +17,7 @@ namespace Cake\Console;
 use Cake\Datasource\ModelAwareTrait;
 use Cake\Log\LogTrait;
 use Cake\ORM\Locator\LocatorAwareTrait;
+use RuntimeException;
 
 /**
  * Base class for console commands.
@@ -44,11 +45,21 @@ class Command
     {
         $locator = $this->getTableLocator() ? : 'Cake\ORM\TableRegistry';
         $this->modelFactory('Table', [$locator, 'get']);
+    }
 
-        if (!$this->name) {
-            list(, $class) = namespaceSplit(get_class($this));
-            $this->name = str_replace('Command', '', $class);
-        }
+    /**
+     * Set the name this command uses in the collection.
+     *
+     * Generally invoked by the CommandCollection when the command is added.
+     *
+     * @param string $name The name the command uses in the collection.
+     * @return $this;
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+
+        return $this;
     }
 
     /**
@@ -62,6 +73,40 @@ class Command
     }
 
     /**
+     * Get the option parser.
+     *
+     * You can override buildOptionParser() to define your options & arguments.
+     *
+     * @return \Cake\Console\ConsoleOptionParser
+     * @throws \RuntimeException When the parser is invalid
+     */
+    public function getOptionParser()
+    {
+        $parser = new ConsoleOptionParser($this->name);
+        $parser = $this->buildOptionParser($parser);
+        if (!($parser instanceof ConsoleOptionParser)) {
+            throw new RuntimeException(sprintf(
+                "Invalid option parser returned from buildOptionParser(). Expected %s, got %s",
+                ConsoleOptionParser::class,
+                get_class($parser)
+            ));
+        }
+
+        return $parser;
+    }
+
+    /**
+     * Hook method for defining this command's option parser.
+     *
+     * @param \Cake\Console\ConsoleOptionParser $parser The parser to be defined
+     * @return \Cake\Console\ConsoleOptionParser The built parser.
+     */
+    protected function buildOptionParser(ConsoleOptionParser $parser)
+    {
+        return $parser;
+    }
+
+    /**
      * Hook method invoked by CakePHP when a command is about to be executed.
      *
      * Override this method and implement expensive/important setup steps that

+ 37 - 5
tests/TestCase/Console/CommandTest.php

@@ -15,10 +15,10 @@
 namespace Cake\Test\TestCase\Console;
 
 use Cake\Console\Command;
+use Cake\Console\ConsoleOptionParser;
 use Cake\ORM\Locator\TableLocator;
 use Cake\ORM\Table;
 use Cake\TestSuite\TestCase;
-use TestApp\Command\ExampleCommand;
 
 /**
  * Test case for Console\Command
@@ -50,13 +50,45 @@ class CommandTest extends TestCase
     }
 
     /**
-     * Test name inflection
+     * Test name
      *
      * @return void
      */
-    public function testNameInflection()
+    public function testSetName()
     {
-        $command = new ExampleCommand();
-        $this->assertSame('Example', $command->getName());
+        $command = new Command();
+        $this->assertSame($command, $command->setName('routes show'));
+        $this->assertSame('routes show', $command->getName());
+    }
+
+    /**
+     * Test option parser fetching
+     *
+     * @return void
+     */
+    public function testGetOptionParser()
+    {
+        $command = new Command();
+        $command->setName('cake routes show');
+        $parser = $command->getOptionParser();
+        $this->assertInstanceOf(ConsoleOptionParser::class, $parser);
+        $this->assertSame('cake routes show', $parser->getCommand());
+    }
+
+    /**
+     * Test option parser fetching
+     *
+     * @expectedException RuntimeException
+     * @return void
+     */
+    public function testGetOptionParserInvalid()
+    {
+        $command = $this->getMockBuilder(Command::class)
+            ->setMethods(['buildOptionParser'])
+            ->getMock();
+        $command->expects($this->once())
+            ->method('buildOptionParser')
+            ->will($this->returnValue(null));
+        $command->getOptionParser();
     }
 }