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',
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy