-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[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
| $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.
|
|
||
| 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( | ||
| array('cli.php', '--foo='), | ||
| array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), | ||
| array('foo' => 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
|
|
||
| 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
$argvjust return"--foo="for the option, the current implementation doesn't handle the empty value when using an equal as separator, so thebarargument value is considered as thefooone, 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.