bug #15533 [Console] Fix input validation when required arguments are missing (jakzal)

This PR was merged into the 2.3 branch.

Discussion
----------

[Console] Fix input validation when required arguments are missing

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #15505
| License       | MIT
| Doc PR        | -

The rule that was here in place previously only works when arguments are passed from command line, as in command line there is no way of skipping an argument. The rule does not work for arguments set on the Input after a command is run.

Commits
-------

4982b02 [Console] Add the command name to input arguments if it's missing
f12a4c1 [Console] Fix input validation when required arguments are missing
This commit is contained in:
Fabien Potencier 2015-09-27 15:31:56 +02:00
commit 7f829b8d55
4 changed files with 37 additions and 3 deletions

View File

@ -241,6 +241,13 @@ class Command
$this->interact($input, $output);
}
// The command name argument is often omitted when a command is executed directly with its run() method.
// It would fail the validation if we didn't make sure the command argument is present,
// since it's required by the application.
if ($input->hasArgument('command') && null === $input->getArgument('command')) {
$input->setArgument('command', $this->getName());
}
$input->validate();
if ($this->code) {

View File

@ -72,8 +72,15 @@ abstract class Input implements InputInterface
*/
public function validate()
{
if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
throw new \RuntimeException('Not enough arguments.');
$definition = $this->definition;
$givenArguments = $this->arguments;
$missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
});
if (count($missingArguments) > 0) {
throw new \RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
}
}

View File

@ -267,6 +267,15 @@ class CommandTest extends \PHPUnit_Framework_TestCase
$this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)');
}
public function testRunWithApplication()
{
$command = new \TestCommand();
$command->setApplication(new Application());
$exitCode = $command->run(new StringInput(''), new NullOutput());
$this->assertSame(0, $exitCode, '->run() returns an integer exit code');
}
public function testRunReturnsAlwaysInteger()
{
$command = new \TestCommand();

View File

@ -94,7 +94,7 @@ class InputTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Not enough arguments.
* @expectedExceptionMessage Not enough arguments (missing: "name").
*/
public function testValidateWithMissingArguments()
{
@ -103,6 +103,17 @@ class InputTest extends \PHPUnit_Framework_TestCase
$input->validate();
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Not enough arguments (missing: "name").
*/
public function testValidateWithMissingRequiredArguments()
{
$input = new ArrayInput(array('bar' => 'baz'));
$input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED), new InputArgument('bar', InputArgument::OPTIONAL))));
$input->validate();
}
public function testValidate()
{
$input = new ArrayInput(array('name' => 'foo'));