8000 bug #19946 [Console] Fix parsing optionnal options with empty value i… · symfony/symfony@2d08be1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2d08be1

Browse files
committed
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
2 parents b28cd81 + 8952155 commit 2d08be1

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/Symfony/Component/Console/Input/ArgvInput.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ private function parseLongOption($token)
145145
$name = substr($token, 2);
146146

147147
if (false !== $pos = strpos($name, '=')) {
148-
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
148+
if (0 === strlen($value = substr($name, $pos + 1))) {
149+
array_unshift($this->parsed, null);
150+
}
151+
$this->addLongOption(substr($name, 0, $pos), $value);
149152
} else {
150153
$this->addLongOption($name, null);
151154
}
@@ -232,7 +235,7 @@ private function addLongOption($name, $value)
232235
if (isset($next[0]) && '-' !== $next[0]) {
233236
$value = $next;
234237
} elseif (empty($next)) {
235-
$value = '';
238+
$value = null;
236239
} else {
237240
array_unshift($this->parsed, $next);
238241
}

src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ public function provideOptions()
7171
array('foo' => 'bar'),
7272
'->parse() parses long options with a required value (with a space separator)',
7373
),
74+
array(
75+
array('cli.php', '--foo='),
76+
array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
77+
array('foo' => null),
78+
'->parse() parses long options with optional value which is empty (with a = separator) as null',
79+
),
80+
array(
81+
array('cli.php', '--foo=', 'bar'),
82+
array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)),
83+
array('foo' => null),
84+
'->parse() parses long options with optional value which is empty (with a = separator) followed by an argument',
85+
),
7486
array(
7587
array('cli.php', '-f'),
7688
array(new InputOption('foo', 'f')),
@@ -324,4 +336,30 @@ public function testParseSingleDashAsArgument()
324336
$input->bind(new InputDefinition(array(new InputArgument('file'))));
325337
$this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument');
326338
}
339+
340+
public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument()
341+
{
342+
$input = new ArgvInput(array('cli.php', '--foo=', 'bar'));
343+
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED))));
344+
$this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null');
345+
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments');
346+
347+
$input = new ArgvInput(array('cli.php', '--foo=0', 'bar'));
348+
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED))));
349+
$this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null');
350+
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments');
351+
}
352+
353+
public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument()
354+
{
355+
$input = new ArgvInput(array('cli.php', '--foo=', 'bar'));
356+
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL))));
357+
$this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null');
358+
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments');
359+
360+
$input = new ArgvInput(array('cli.php', '--foo=0', 'bar'));
361+
$input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL))));
362+
$this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null');
363+
$this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments');
364+
}
327365
}

0 commit comments

Comments
 (0)
0