Description
Symfony version(s) affected: symfony/console
, (at least) 4.1
Description
When not giving a value to an option with VALUE_OPTIONAL, one would expect the option to gain the default value; instead, the option value is null
.
How to reproduce
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\NullOutput;
class CommandOptionDefaultValueTest extends TestCase
{
public function testCommandDefaultValueForOptionalOptionValues()
{
self::assertSame(
0,
(new Command())->setName('test')
->addOption(
'option',
'o',
InputOption::VALUE_OPTIONAL,
'Optional option!',
'This should be the default value...'
)
->setCode(function(InputInterface $input): int {
if ($input->getOption('option') === null) {
throw new \InvalidArgumentException(
'...but instead, the default became `null`!'
);
}
return 0;
})
->run(new StringInput('--option'), new NullOutput())
);
}
}
Possible Solution
Use the available default value when an optional value is not provided.
Additional context
The current behaviour is potentially problematic, especially for options with a "true-ish" default value: When providing options such as dry-run
or only-validated
with a default value of true
, one would expect that running: command --dry-run
will make a dry run, and command --only-validated
will only process the validated data.
This assumption is exceptionally easily made when the option explicitly declares its default value to be true
.
What happens in reality, however, is the following:
- the option value is missing, thus becoming
null
- the if-statement (eg.
if ($input->getOption('dry-run'))
) considers null to be false command --dry-run
does not make a dry run- hell breaks loose
Note: When not adding the option at all, the default value is used as expected.