Permalink
Browse files

Merge pull request #1855 from eddieajau/staging

Fix several bugs in parseArguments and add test suite Edit
  • Loading branch information...
2 parents e429676 + ba462b0 commit 1be55969d87fb8f88585eb8d045eba3d578dd6bc @eddieajau eddieajau committed Mar 27, 2013
Showing with 182 additions and 49 deletions.
  1. +60 −49 libraries/joomla/input/cli.php
  2. +122 −0 tests/suites/unit/joomla/input/JInputCLITest.php
@@ -110,82 +110,93 @@ public function unserialize($input)
/**
* Initialise the options and arguments
*
+ * Not supported: -abc c-value
+ *
* @return void
*
* @since 11.1
*/
protected function parseArguments()
{
- // Get the list of argument values from the environment.
- $args = $_SERVER['argv'];
+ $argv = $_SERVER['argv'];
+
+ $this->executable = array_shift($argv);
- // Set the path used for program execution and remove it form the program arguments.
- $this->executable = array_shift($args);
+ $out = array();
- // We use a for loop because in some cases we need to look ahead.
- for ($i = 0; $i < count($args); $i++)
+ for ($i = 0, $j = count($argv); $i < $j; $i++)
{
- // Get the current argument to analyze.
- $arg = $args[$i];
+ $arg = $argv[$i];
- // First let's tackle the long argument case. eg. --foo
- if (strlen($arg) > 2 && substr($arg, 0, 2) == '--')
+ // --foo --bar=baz
+ if (substr($arg, 0, 2) === '--')
{
+ $eqPos = strpos($arg, '=');
- // Attempt to split the thing over equals so we can get the key/value pair if an = was used.
- $arg = substr($arg, 2);
- $parts = explode('=', $arg);
- $this->data[$parts[0]] = true;
-
- // Does not have an =, so let's look ahead to the next argument for the value.
- if (count($parts) == 1 && isset($args[$i + 1]) && preg_match('/^--?.+/', $args[$i + 1]) == 0)
+ // --foo
+ if ($eqPos === false)
{
- $this->data[$parts[0]] = $args[$i + 1];
-
- // Since we used the next argument, increment the counter so we don't use it again.
- $i++;
+ $key = substr($arg, 2);
+
+ // --foo value
+ if ($i + 1 < $j && $argv[$i + 1][0] !== '-')
+ {
+ $value = $argv[$i + 1];
+ $i++;
+ }
+ else
+ {
+ $value = isset($out[$key]) ? $out[$key] : true;
+ }
+
+ $out[$key] = $value;
}
- // We have an equals sign so take the second "part" of the argument as the value.
- elseif (count($parts) == 2)
+
+ // --bar=baz
+ else
{
- $this->data[$parts[0]] = $parts[1];
+ $key = substr($arg, 2, $eqPos - 2);
+ $value = substr($arg, $eqPos + 1);
+ $out[$key] = $value;
}
}
-
- // Next let's see if we are dealing with a "bunch" of short arguments. eg. -abc
- elseif (strlen($arg) > 2 && $arg[0] == '-')
+ elseif (substr($arg, 0, 1) === '-')
+ // -k=value -abc
{
-
- // For each of these arguments set the value to TRUE since the flag has been set.
- for ($j = 1; $j < strlen($arg); $j++)
+ // -k=value
+ if (substr($arg, 2, 1) === '=')
{
- $this->data[$arg[$j]] = true;
+ $key = substr($arg, 1, 1);
+ $value = substr($arg, 3);
+ $out[$key] = $value;
}
- }
-
- // OK, so it isn't a long argument or bunch of short ones, so let's look and see if it is a single
- // short argument. eg. -h
- elseif (strlen($arg) == 2 && $arg[0] == '-')
- {
-
- // Go ahead and set the value to TRUE and if we find a value later we'll overwrite it.
- $this->data[$arg[1]] = true;
-
- // Let's look ahead to see if the next argument is a "value". If it is, use it for this value.
- if (isset($args[$i + 1]) && preg_match('/^--?.+/', $args[$i + 1]) == 0)
+ else
+ // -abc
{
- $this->data[$arg[1]] = $args[$i + 1];
-
- // Since we used the next argument, increment the counter so we don't use it again.
- $i++;
+ $chars = str_split(substr($arg, 1));
+
+ foreach ($chars as $char)
+ {
+ $key = $char;
+ $value = isset($out[$key]) ? $out[$key] : true;
+ $out[$key] = $value;
+ }
+
+ // -a a-value
+ if ((count($chars) === 1) && ($i + 1 < $j) && ($argv[$i + 1][0] !== '-'))
+ {
+ $out[$key] = $argv[$i + 1];
+ $i++;
+ }
}
}
-
- // Last but not least, we don't have a key/value based argument so just add it to the arguments list.
else
{
+ // Plain-arg
$this->args[] = $arg;
}
}
+
+ $this->data = $out;
}
}
@@ -34,6 +34,128 @@ protected function setUp()
}
/**
+ * Test the JInput::parseArguments method.
+ *
+ * @dataProvider provider_parseArguments
+ */
+ public function test_parseArguments($inputArgv, $expectedData, $expectedArgs)
+ {
+ $_SERVER['argv'] = $inputArgv;
+ $this->inspector = new JInputCLIInspector(null, array('filter' => new JFilterInputMock));
+
+ $this->assertThat(
+ $this->inspector->data,
+ $this->identicalTo($expectedData)
+ );
+
+ $this->assertThat(
+ $this->inspector->args,
+ $this->identicalTo($expectedArgs)
+ );
+ }
+
+ /**
+ * Test inputs:
+ *
+ * php test.php --foo --bar=baz
+ * php test.php -abc
+ * php test.php arg1 arg2 arg3
+ * php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \
+ * 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s
+ * php test.php --key value -abc not-c-value
+ * php test.php --key1 value1 -a --key2 -b b-value --c
+ *
+ * Note that this pattern is not supported: -abc c-value
+ */
+ public function provider_parseArguments()
+ {
+ return array(
+
+ // php test.php --foo --bar=baz
+ array(
+ array('test.php', '--foo', '--bar=baz'),
+ array(
+ 'foo' => true,
+ 'bar' => 'baz'
+ ),
+ array()
+ ),
+
+ // php test.php -abc
+ array(
+ array('test.php', '-abc'),
+ array(
+ 'a' => true,
+ 'b' => true,
+ 'c' => true
+ ),
+ array()
+ ),
+
+ // php test.php arg1 arg2 arg3
+ array(
+ array('test.php', 'arg1', 'arg2', 'arg3'),
+ array(),
+ array(
+ 'arg1',
+ 'arg2',
+ 'arg3'
+ )
+ ),
+
+ // php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs \
+ // 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s
+ array(
+ array('test.php', 'plain-arg', '--foo', '--bar=baz', '--funny=spam=eggs', '--also-funny=spam=eggs',
+ 'plain arg 2', '-abc', '-k=value', 'plain arg 3', '--s=original', '--s=overwrite', '--s'),
+ array(
+ 'foo' => true,
+ 'bar' => 'baz',
+ 'funny' => 'spam=eggs',
+ 'also-funny' => 'spam=eggs',
+ 'a' => true,
+ 'b' => true,
+ 'c' => true,
+ 'k' => 'value',
+ 's' => 'overwrite'
+ ),
+ array(
+ 'plain-arg',
+ 'plain arg 2',
+ 'plain arg 3'
+ )
+ ),
+
+ // php test.php --key value -abc not-c-value
+ array(
+ array('test.php', '--key', 'value', '-abc', 'not-c-value'),
+ array(
+ 'key' => 'value',
+ 'a' => true,
+ 'b' => true,
+ 'c' => true
+ ),
+ array(
+ 'not-c-value'
+ )
+ ),
+
+ // php test.php --key1 value1 -a --key2 -b b-value --c
+ array(
+ array('test.php', '--key1', 'value1', '-a', '--key2', '-b', 'b-value', '--c'),
+ array(
+ 'key1' => 'value1',
+ 'a' => true,
+ 'key2' => true,
+ 'b' => 'b-value',
+ 'c' => true
+ ),
+ array()
+ )
+ );
+ }
+
+ /**
* Test the JInput::get method.
*
* @return void

0 comments on commit 1be5596

Please sign in to comment.