bug #19946 [Console] Fix parsing optionnal options with empty value in argv (chalasr)
This PR was merged into the 2.7 branch.
Discussion
----------
[Console] Fix parsing optionnal options with empty value in argv
| Q | A
| ------------- | ---
| Branch? | 2.7
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #19884
| License | MIT
If a command takes an option accepting an optional value, passing an empty value to this option will make it parsed as `null`, e.g:
`bin/console dummy --foo ""` gives `['foo' => null]`.
`bin/console dummy --foo=""` gives `['foo' => null]`.
Problems appear when adding an argument with a required value (let's call it `bar`):
`bin/console dummy --foo "" "bar-val"` gives `['foo' => null, 'bar' => 'bar-val']` which is OK.
But:
`bin/console dummy --foo="" "bar-val"`
> [RuntimeException]
Not enough arguments (missing: "bar").
The empty value is never considered, as `$argv` just return `"--foo="` for the option, the current implementation doesn't handle the empty value when using an equal as separator, so the `bar` argument value is considered as the `foo` one, giving a missing required argument at runtime.
This fixes it by explicitly considering the empty value if there is nothing immediately after the equal sign, so args/options correctly take their respective values.
Commits
-------
8952155
[Console] Fix empty optionnal options with = separator in argv
This commit is contained in:
commit
2d08be14f5
@ -145,7 +145,10 @@ class ArgvInput extends Input
|
|||||||
$name = substr($token, 2);
|
$name = substr($token, 2);
|
||||||
|
|
||||||
if (false !== $pos = strpos($name, '=')) {
|
if (false !== $pos = strpos($name, '=')) {
|
||||||
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
|
if (0 === strlen($value = substr($name, $pos + 1))) {
|
||||||
|
array_unshift($this->parsed, null);
|
||||||
|
}
|
||||||
|
$this->addLongOption(substr($name, 0, $pos), $value);
|
||||||
} else {
|
} else {
|
||||||
$this->addLongOption($name, null);
|
$this->addLongOption($name, null);
|
||||||
}
|
}
|
||||||
@ -232,7 +235,7 @@ class ArgvInput extends Input
|
|||||||
if (isset($next[0]) && '-' !== $next[0]) {
|
if (isset($next[0]) && '-' !== $next[0]) {
|
||||||
$value = $next;
|
$value = $next;
|
||||||
} elseif (empty($next)) {
|
} elseif (empty($next)) {
|
||||||
$value = '';
|
$value = null;
|
||||||
} else {
|
} else {
|
||||||
array_unshift($this->parsed, $next);
|
array_unshift($this->parsed, $next);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,18 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase
|
|||||||
array('foo' => 'bar'),
|
array('foo' => 'bar'),
|
||||||
'->parse() parses long options with a required value (with a space separator)',
|
'->parse() parses long options with a required value (with a space separator)',
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
array('cli.php', '--foo='),
|
||||||
|
array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
|
||||||
|
array('foo' => null),
|
||||||
|
'->parse() parses long options with optional value which is empty (with a = separator) as null',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array('cli.php', '--foo=', 'bar'),
|
||||||
|
array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)),
|
||||||
|
array('foo' => null),
|
||||||
|
'->parse() parses long options with optional value which is empty (with a = separator) followed by an argument',
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
array('cli.php', '-f'),
|
array('cli.php', '-f'),
|
||||||
array(new InputOption('foo', 'f')),
|
array(new InputOption('foo', 'f')),
|
||||||
@ -324,4 +336,30 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase
|
|||||||
$input->bind(new InputDefinition(array(new InputArgument('file'))));
|
$input->bind(new InputDefinition(array(new InputArgument('file'))));
|
||||||
$this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument');
|
$this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument()
|
||||||
|
{
|
||||||
|
$input = new ArgvInput(array('cli.php', '--foo=', 'bar'));
|
||||||
|
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED))));
|
||||||
|
$this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null');
|
||||||
|
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments');
|
||||||
|
|
||||||
|
$input = new ArgvInput(array('cli.php', '--foo=0', 'bar'));
|
||||||
|
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED))));
|
||||||
|
$this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null');
|
||||||
|
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument()
|
||||||
|
{
|
||||||
|
$input = new ArgvInput(array('cli.php', '--foo=', 'bar'));
|
||||||
|
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL))));
|
||||||
|
$this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null');
|
||||||
|
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments');
|
||||||
|
|
||||||
|
$input = new ArgvInput(array('cli.php', '--foo=0', 'bar'));
|
||||||
|
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL))));
|
||||||
|
$this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null');
|
||||||
|
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user