8000 feature #34790 [Console] Remove restriction for choices to be strings… · symfony/symfony@d6468a9 · GitHub
[go: up one dir, main page]

Skip to content

Commit d6468a9

Browse files
committed
feature #34790 [Console] Remove restriction for choices to be strings (LordZardeck, YaFou, ogizanagi)
This PR was merged into the 5.2-dev branch. Discussion ---------- [Console] Remove restriction for choices to be strings | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #34789 | License | MIT When using choice, selected answers are forced into strings, preventing us from using complex values such as a class with a custom __toString. This is a problem, as I need the ability to present the user with a list of display strings to choose from, but need the ID associated with that display string in order to do anything useful. Commits ------- d276cc9 [Console] Cast associative choices questions keys to string a022308 [Console] Add tests for removing restriction for choices to be strings 3349d3c Remove restriction for choices to be strings
2 parents c649bfa + d276cc9 commit d6468a9

File tree

3 files changed

+74
-36
lines changed

3 files changed

+74
-36
lines changed

src/Symfony/Component/Console/Question/ChoiceQuestion.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ private function getDefaultValidator(): callable
169169
throw new InvalidArgumentException(sprintf($errorMessage, $value));
170170
}
171171

172-
$multiselectChoices[] = (string) $result;
172+
// For associative choices, consistently return the key as string:
173+
$multiselectChoices[] = $isAssoc ? (string) $result : $result;
173174
}
174175

175176
if ($multiselect) {

src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -607,41 +607,6 @@ public function specialCharacterInMultipleChoice()
607607
];
608608
}
609609

610-
/**
611-
* @dataProvider mixedKeysChoiceListAnswerProvider
612-
*/
613-
public function testChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
614-
{
615-
$possibleChoices = [
616-
'0' => 'No environment',
617-
'1' => 'My environment 1',
618-
'env_2' => 'My environment 2',
619-
3 => 'My environment 3',
620-
];
621-
622-
$dialog = new QuestionHelper();
623-
$helperSet = new HelperSet([new FormatterHelper()]);
624-
$dialog->setHelperSet($helperSet);
625-
626-
$question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
627-
$question->setMaxAttempts(1);
628-
$answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
629-
630-
$this->assertSame($expectedValue, $answer);
631-
}
632-
633-
public function mixedKeysChoiceListAnswerProvider()
634-
{
635-
return [
636-
['0', '0'],
637-
['No environment', '0'],
638-
['1', '1'],
639-
['env_2', 'env_2'],
640-
[3, '3'],
641-
['My environment 1', '1'],
642-
];
643-
}
644-
645610
/**
646611
* @dataProvider answerProvider
647612
*/

src/Symfony/Component/Console/Tests/Question/ChoiceQuestionTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ public function selectUseCases()
5959
['First response', 'Second response'],
6060
'When passed multiple answers on MultiSelect, the defaultValidator must return these answers as an array',
6161
],
62+
[
63+
false,
64+
[0],
65+
'First response',
66+
'When passed single answer using choice\'s key, the defaultValidator must return the choice value',
67+
],
68+
[
69+
true,
70+
['0, 2'],
71+
['First response', 'Third response'],
72+
'When passed multiple answers using choices\' key, the defaultValidator must return the choice values in an array',
73+
],
6274
];
6375
}
6476

@@ -77,4 +89,64 @@ public function testNonTrimmable()
7789

7890
$this->assertSame(['First response ', ' Second response'], $question->getValidator()('First response , Second response'));
7991
}
92+
93+
/**
94+
* @dataProvider selectAssociativeChoicesProvider
95+
*/
96+
public function testSelectAssociativeChoices($providedAnswer, $expectedValue)
97+
{
98+
$question = new ChoiceQuestion('A question', [
99+
'0' => 'First choice',
9E7A 100+
'foo' => 'Foo',
101+
'99' => 'N°99',
102+
'string object' => new StringChoice('String Object'),
103+
]);
104+
105+
$this->assertSame($expectedValue, $question->getValidator()($providedAnswer));
106+
}
107+
108+
public function selectAssociativeChoicesProvider()
109+
{
110+
return [
111+
'select "0" choice by key' => ['0', '0'],
112+
'select "0" choice by value' => ['First choice', '0'],
113+
'select by key' => ['foo', 'foo'],
114+
'select by value' => ['Foo', 'foo'],
115+
'select by key, with numeric key' => ['99', '99'],
116+
'select by value, with numeric key' => ['N°99', '99'],
117+
'select by key, with string object value' => ['string object', 'string object'],
118+
'select by value, with string object value' => ['String Object', 'string object'],
119+
];
120+
}
121+
122+
public function testSelectWithNonStringChoices()
123+
{
124+
$question = new ChoiceQuestion('A question', [
125+
$result1 = new StringChoice('foo'),
126+
$result2 = new StringChoice('bar'),
127+
$result3 = new StringChoice('baz'),
128+
]);
129+
130+
$this->assertSame($result1, $question->getValidator()('foo'), 'answer can be selected by its string value');
131+
$this->assertSame($result1, $question->getValidator()(0), 'answer can be selected by index');
132+
133+
$question->setMultiselect(true);
134+
135+
$this->assertSame([$result3, $result2], $question->getValidator()('baz, bar'));
136+
}
137+
}
138+
139+
class StringChoice
140+
{
141+
private $string;
142+
143+
public function __construct(string $string)
144+
{
145+
$this->string = $string;
146+
}
147+
148+
public function __toString()
149+
{
150+
return $this->string;
151+
}
80152
}

0 commit comments

Comments
 (0)
0