3
3
namespace Matthias \SymfonyConsoleForm \Console \Helper \Question ;
4
4
5
5
use Symfony \Component \Console \Question \ChoiceQuestion ;
6
+ use Symfony \Component \Form \Extension \Core \View \ChoiceView ;
6
7
7
8
class AlwaysReturnKeyOfChoiceQuestion extends ChoiceQuestion
8
9
{
10
+ /**
11
+ * @var ChoiceView[]
12
+ */
13
+ private $ choiceViews ;
9
14
private $ _multiselect = false ;
10
15
11
16
private $ _errorMessage = 'Value "%s" is invalid ' ;
12
17
18
+ public function __construct ($ question , array $ choiceViews , $ default = null )
19
+ {
20
+ \Assert \that ($ choiceViews )
21
+ ->all ()
22
+ ->isInstanceOf (
23
+ 'Symfony\Component\Form\Extension\Core\View\ChoiceView ' ,
24
+ 'Only a flat choice hierarchy is supported '
25
+ );
26
+
27
+ $ this ->choiceViews = $ choiceViews ;
28
+
29
+ parent ::__construct ($ question , $ this ->prepareChoices (), $ default );
30
+
31
+ $ this ->setAutocompleterValues ($ this ->prepareAutocompleteValues ());
32
+ }
33
+
13
34
public function setMultiselect ($ multiselect )
14
35
{
15
36
$ this ->_multiselect = $ multiselect ;
@@ -26,18 +47,14 @@ public function setErrorMessage($errorMessage)
26
47
27
48
public function getValidator ()
28
49
{
29
- $ choices = $ this ->getChoices ();
30
- $ errorMessage = $ this ->_errorMessage ;
31
- $ multiselect = $ this ->_multiselect ;
32
-
33
- return function ($ selected ) use ($ choices , $ errorMessage , $ multiselect ) {
50
+ return function ($ selected ) {
34
51
// Collapse all spaces.
35
52
$ selectedChoices = str_replace (' ' , '' , $ selected );
36
53
37
- if ($ multiselect ) {
54
+ if ($ this -> _multiselect ) {
38
55
// Check for a separated comma values
39
56
if (!preg_match ('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/ ' , $ selectedChoices , $ matches )) {
40
- throw new \InvalidArgumentException (sprintf ($ errorMessage , $ selected ));
57
+ throw new \InvalidArgumentException (sprintf ($ this -> _errorMessage , $ selected ));
41
58
}
42
59
$ selectedChoices = explode (', ' , $ selectedChoices );
43
60
} else {
@@ -46,25 +63,58 @@ public function getValidator()
46
63
47
64
$ selectedKeys = array ();
48
65
49
- foreach ($ selectedChoices as $ value ) {
50
- if (array_key_exists ($ value , $ choices )) {
51
- $ selectedKeys [] = $ value ;
52
- continue ;
53
- }
54
-
55
- $ key = array_search ($ value , $ choices );
56
- if ($ key === false ) {
57
- throw new \InvalidArgumentException (sprintf ($ errorMessage , $ value ));
58
- }
59
-
60
- $ selectedKeys [] = $ key ;
66
+ foreach ($ selectedChoices as $ selectedValue ) {
67
+ $ selectedKeys [] = $ this ->resolveChoiceViewValue ($ selectedValue );
61
68
}
62
69
63
- if ($ multiselect ) {
70
+ if ($ this -> _multiselect ) {
64
71
return $ selectedKeys ;
65
72
}
66
73
67
74
return current ($ selectedKeys );
68
75
};
69
76
}
77
+
78
+ /**
79
+ * @param string $selectedValue The selected value
80
+ * @return string The corresponding value of the ChoiceView
81
+ */
82
+ private function resolveChoiceViewValue ($ selectedValue )
83
+ {
84
+ foreach ($ this ->choiceViews as $ choiceView ) {
85
+ if (in_array ($ selectedValue , [$ choiceView ->data , $ choiceView ->value , $ choiceView ->label ])) {
86
+ return $ choiceView ->value ;
87
+ }
88
+ }
89
+
90
+ throw new \InvalidArgumentException (sprintf ($ this ->_errorMessage , $ selectedValue ));
91
+ }
92
+
93
+ private function prepareChoices ()
94
+ {
95
+ $ choices = [];
96
+ foreach ($ this ->choiceViews as $ choiceView ) {
97
+ $ label = $ choiceView ->label ;
98
+ if ($ choiceView ->data != $ choiceView ->value ) {
99
+ $ label .= ' (<comment> ' . $ choiceView ->data . '</comment>) ' ;
100
+ }
101
+
102
+ $ choices [$ choiceView ->value ] = $ label ;
103
+ }
104
+
105
+ return $ choices ;
106
+ }
107
+
108
+ private function prepareAutocompleteValues ()
109
+ {
110
+ $ autocompleteValues = array ();
111
+
112
+ foreach ($ this ->choiceViews as $ choiceView ) {
113
+ $ autocompleteValues [] = $ choiceView ->value ;
114
+ $ autocompleteValues [] = $ choiceView ->data ;
115
+ $ autocompleteValues [] = $ choiceView ->label ;
116
+ }
117
+
118
+ return $ autocompleteValues ;
119
+ }
70
120
}
0 commit comments