Fixed the issue 11116

This commit is contained in:
Saro0h 2014-12-05 01:10:24 +01:00
parent ff91d306ba
commit fa03e523d7
3 changed files with 119 additions and 4 deletions

View File

@ -36,7 +36,7 @@ class ChoiceQuestion extends Question
$this->choices = $choices;
$this->setValidator($this->getDefaultValidator());
$this->setAutocompleterValues(array_keys($choices));
$this->setAutocompleterValues($choices);
}
/**
@ -134,17 +134,69 @@ class ChoiceQuestion extends Question
$multiselectChoices = array();
foreach ($selectedChoices as $value) {
if (empty($choices[$value])) {
$this->checkMultipleResults($choices, $value);
$result = $this->getResult($choices, $value);
if (empty($result)) {
throw new \InvalidArgumentException(sprintf($errorMessage, $value));
}
array_push($multiselectChoices, $choices[$value]);
array_push($multiselectChoices, $result);
}
if ($multiselect) {
return $multiselectChoices;
}
return $choices[$selected];
return current($multiselectChoices);
};
}
/**
* Checks if there are multiple keys corresponding to the value supplied
* by the user.
*
* @param array $possibleChoices Possible value(s) that the user can supply
* @param string $value Value supplied by the user
*
* @return null
*/
private function checkMultipleResults(array $possibleChoices, $value)
{
$results = array();
foreach ($possibleChoices as $key => $choice) {
if ($choice === $value) {
$results[] = $key;
}
}
if (count($results) > 1) {
throw new \InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
}
}
/**
* Get the result according to what have been provided by the user and the
* possible choices.
*
* @param array $possibleChoices Possible value(s) that the user can supply
* @param string $value Value supplied by the user
*
* @retun string
*/
private function getResult(array $possibleChoices, $value)
{
$result = array_search($value, $possibleChoices);
if (!$this->isAssoc($possibleChoices)) {
if (!empty($result)) {
$result = $possibleChoices[$result];
} elseif (isset($possibleChoices[$value])) {
$result = $possibleChoices[$value];
}
} elseif (empty($result) && array_key_exists($value, $possibleChoices)) {
$result = $value;
}
return $result;
}
}

View File

@ -135,6 +135,10 @@ class Question
*/
public function setAutocompleterValues($values)
{
if (is_array($values) && $this->isAssoc($values)) {
$values = array_merge(array_keys($values), array_values($values));
}
if (null !== $values && !is_array($values)) {
if (!$values instanceof \Traversable || $values instanceof \Countable) {
throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
@ -235,4 +239,9 @@ class Question
{
return $this->normalizer;
}
protected function isAssoc($array)
{
return (bool) count(array_filter(array_keys($array), 'is_string'));
}
}

View File

@ -198,6 +198,60 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase
}
}
/**
* @dataProvider answerProvider
*/
public function testSelectChoiceFromChoiceList($providedAnswer, $expectedValue)
{
$possibleChoices = array(
'env_1' => 'My environment 1',
'env_2' => 'My environment',
'env_3' => 'My environment',
);
$dialog = new QuestionHelper();
$dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
$helperSet = new HelperSet(array(new FormatterHelper()));
$dialog->setHelperSet($helperSet);
$question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
$answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
$this->assertSame($expectedValue, $answer);
}
public function testAmbiguousChoiceFromChoicelist()
{
$possibleChoices = array(
'env_1' => 'My environment 1',
'env_2' => 'My environment',
'env_3' => 'My environment',
);
$dialog = new QuestionHelper();
$dialog->setInputStream($this->getInputStream("My environment\n"));
$helperSet = new HelperSet(array(new FormatterHelper()));
$dialog->setHelperSet($helperSet);
$question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
try {
$dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
} catch (\InvalidArgumentException $e) {
$this->assertEquals('The provided answer is ambiguous. Value should be one of env_2 or env_3.', $e->getMessage());
}
}
public function answerProvider()
{
return array(
array('env_1', 'env_1'),
array('env_2', 'env_2'),
array('env_3', 'env_3'),
array('My environment 1', 'env_1'),
);
}
public function testNoInteraction()
{
$dialog = new QuestionHelper();