Browse Source

Merge pull request #9958 from cakephp/shell-option-multiple-values

Add support for multiple values option in the Shell system
Mark Story 9 years ago
parent
commit
5a3d301235

+ 28 - 2
src/Console/ConsoleInputOption.php

@@ -62,6 +62,13 @@ class ConsoleInputOption
     protected $_default;
 
     /**
+     * Can the option accept multiple value definition.
+     *
+     * @var bool
+     */
+    protected $_multiple;
+
+    /**
      * An array of choices for the option.
      *
      * @var array
@@ -77,10 +84,18 @@ class ConsoleInputOption
      * @param bool $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
      * @param string $default The default value for this option.
      * @param array $choices Valid choices for this option.
+     * @param bool $multiple Whether this option can accept multiple value definition.
      * @throws \Cake\Console\Exception\ConsoleException
      */
-    public function __construct($name, $short = '', $help = '', $boolean = false, $default = '', $choices = [])
-    {
+    public function __construct(
+        $name,
+        $short = '',
+        $help = '',
+        $boolean = false,
+        $default = '',
+        $choices = [],
+        $multiple = false
+    ) {
         if (is_array($name) && isset($name['name'])) {
             foreach ($name as $key => $value) {
                 $this->{'_' . $key} = $value;
@@ -92,6 +107,7 @@ class ConsoleInputOption
             $this->_boolean = $boolean;
             $this->_default = $default;
             $this->_choices = $choices;
+            $this->_multiple = $multiple;
         }
         if (strlen($this->_short) > 1) {
             throw new ConsoleException(
@@ -186,6 +202,16 @@ class ConsoleInputOption
     }
 
     /**
+     * Check if this option accepts multiple values.
+     *
+     * @return bool
+     */
+    public function acceptsMultiple()
+    {
+        return (bool)$this->_multiple;
+    }
+
+    /**
      * Check that a value is a valid choice for this option.
      *
      * @param string $value The choice to validate.

+ 5 - 1
src/Console/ConsoleOptionParser.php

@@ -736,7 +736,11 @@ class ConsoleOptionParser
             $value = $option->defaultValue();
         }
         if ($option->validChoice($value)) {
-            $params[$name] = $value;
+            if ($option->acceptsMultiple($value)) {
+                $params[$name][] = $value;
+            } else {
+                $params[$name] = $value;
+            }
 
             return $params;
         }

+ 70 - 0
tests/TestCase/Console/ConsoleOptionParserTest.php

@@ -181,6 +181,29 @@ class ConsoleOptionParserTest extends TestCase
     }
 
     /**
+     * test adding an option and using the short value for parsing.
+     *
+     * @return void
+     */
+    public function testAddOptionWithMultipleShort()
+    {
+        $parser = new ConsoleOptionParser('test', false);
+        $parser->addOption('source', [
+            'multiple' => true,
+            'short' => 's'
+        ]);
+        $result = $parser->parse(['-s', 'mysql', '-s', 'postgres']);
+        $this->assertEquals(
+            [
+                'source' => ['mysql', 'postgres'],
+                'help' => false
+            ],
+            $result[0],
+            'Short parameter did not parse out'
+        );
+    }
+
+    /**
      * Test that adding an option using a two letter short value causes an exception.
      * As they will not parse correctly.
      *
@@ -252,6 +275,53 @@ class ConsoleOptionParserTest extends TestCase
     }
 
     /**
+     * test adding an option that accepts multiple values.
+     *
+     * @return void
+     */
+    public function testAddOptionWithMultiple()
+    {
+        $parser = new ConsoleOptionParser('test', false);
+        $parser->addOption('source', ['short' => 's', 'multiple' => true]);
+
+        $result = $parser->parse(['--source', 'mysql', '-s', 'postgres']);
+        $expected = [
+            'source' => [
+                'mysql',
+                'postgres'
+            ],
+            'help' => false
+        ];
+        $this->assertEquals($expected, $result[0], 'options with multiple values did not parse');
+    }
+
+    /**
+     * test adding multiple options, including one that accepts multiple values.
+     *
+     * @return void
+     */
+    public function testAddMultipleOptionsWithMultiple()
+    {
+        $parser = new ConsoleOptionParser('test', false);
+        $parser
+            ->addOption('source', ['multiple' => true])
+            ->addOption('name')
+            ->addOption('export', ['boolean' => true]);
+
+        $result = $parser->parse(['--export', '--source', 'mysql', '--name', 'annual-report', '--source', 'postgres']);
+        $expected = [
+            'export' => true,
+            'source' => [
+                'mysql',
+                'postgres'
+            ],
+            'name' => 'annual-report',
+            'help' => false
+        ];
+        $this->assertEquals($expected, $result[0], 'options with multiple values did not parse');
+    }
+
+    /**
      * Test adding multiple options.
      *
      * @return void