diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index cf9c8c20a7..21edb0f197 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -168,6 +168,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c * made the defaults (helper set, commands, input definition) in Application more easily customizable * added support for the shell even if readline is not available * added support for process isolation in Symfony shell via `--process-isolation` switch + * added support for `--`, which disables options parsing after that point (tokens will be parsed as arguments) ### ClassLoader diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index dda022206c..f0cfb1419e 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -75,11 +75,14 @@ class ArgvInput extends Input */ protected function parse() { + $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { - if (0 === strpos($token, '--')) { + if ($parseOptions && '--' == $token) { + $parseOptions = false; + } elseif ($parseOptions && 0 === strpos($token, '--')) { $this->parseLongOption($token); - } elseif ('-' === $token[0]) { + } elseif ($parseOptions && '-' === $token[0]) { $this->parseShortOption($token); } else { $this->parseArgument($token); diff --git a/tests/Symfony/Tests/Component/Console/Input/ArgvInputTest.php b/tests/Symfony/Tests/Component/Console/Input/ArgvInputTest.php index 32c0393228..d852b1287a 100644 --- a/tests/Symfony/Tests/Component/Console/Input/ArgvInputTest.php +++ b/tests/Symfony/Tests/Component/Console/Input/ArgvInputTest.php @@ -151,6 +151,24 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz')); $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions()); + + try { + $input = new ArgvInput(array('cli.php', '-1')); + $input->bind(new InputDefinition(array(new InputArgument('number')))); + $this->fail('->parse() throws a \RuntimeException if an unknown option is passed'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e, '->parse() parses arguments with leading dashes as options without having encountered a double-dash sequence'); + $this->assertEquals('The "-1" option does not exist.', $e->getMessage(), '->parse() parses arguments with leading dashes as options without having encountered a double-dash sequence'); + } + + $input = new ArgvInput(array('cli.php', '--', '-1')); + $input->bind(new InputDefinition(array(new InputArgument('number')))); + $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); + + $input = new ArgvInput(array('cli.php', '-f', 'bar', '--', '-1')); + $input->bind(new InputDefinition(array(new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)))); + $this->assertEquals(array('foo' => 'bar'), $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence'); + $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); } public function testGetFirstArgument()