-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Console] Fix parsing optionnal options with empty value in argv #19946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Console] Fix parsing optionnal options with empty value in argv #19946
Conversation
@@ -232,7 +235,7 @@ private function addLongOption($name, $value) | |||
if (isset($next[0]) && '-' !== $next[0]) { | |||
$value = $next; | |||
} elseif (empty($next)) { | |||
$value = ''; | |||
$value = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is needed, making the behavior always consistent with the expected one.
@@ -145,7 +145,10 @@ private function parseLongOption($token) | |||
$name = substr($token, 2); | |||
|
|||
if (false !== $pos = strpos($name, '=')) { | |||
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); | |||
if (!$value = substr($name, $pos + 1)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still sure something like --foo=0
won't cause any issue with this check ? :/ (Maybe add this test case below ?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch, thank you @ogizanagi
b569ebb
to
1177289
Compare
array('cli.php', '--foo='), | ||
array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), | ||
array('foo' => null), | ||
'->parse() parses long options with optionnal value which is empty (with a = separator) as null', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*optional
And below also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @ro0NL
1177289
to
6b05e7f
Compare
6b05e7f
to
8952155
Compare
Thank you @chalasr. |
…n 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
@@ -145,7 +145,10 @@ private function parseLongOption($token) | |||
$name = substr($token, 2); | |||
|
|||
if (false !== $pos = strpos($name, '=')) { | |||
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); | |||
if (0 === strlen($value = substr($name, $pos + 1))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about using '' === $value = substr($name, $pos + 1)
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine. See #20008
Btw, could you take a look on this check? I think we can do the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, looks like a candidate that could be changed.
…n translation:update (chalasr) This PR was merged into the 2.7 branch. Discussion ---------- [FrameworkBundle] Convert null prefix to an empty string in translation:update | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #20044 | License | MIT | Doc PR | n/a This command needs the ability to use an empty string as prefix, which is not possible using `bin/console translation:update --prefix=""` because `$argv` doesn't parse empty strings thus the value is converted to `null` by `ArgvInput` (only since #19946, before the option was not considered to be set, giving the default `'__'` thus this should be fine from a BC pov). Here I propose to explicitly convert the `prefix` value to an empty string if set to `null`, as it is a very specific need and we can't guess that from `ArgvInput`. An other way to fix it could be to add a `--no-prefix` option to the command but I don't think it is worth it, and it couldn't be treated as a bug fix thus not fixed before `3.2`. Commits ------- f02b687 [FrameworkBundle] Convert null prefix to an empty string in translation:update command
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"
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 thebar
argument value is considered as thefoo
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.