Yaffs site version 1.1
[yaffs-website] / vendor / symfony / console / Question / ChoiceQuestion.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Console\Question;
13
14 use Symfony\Component\Console\Exception\InvalidArgumentException;
15
16 /**
17  * Represents a choice question.
18  *
19  * @author Fabien Potencier <fabien@symfony.com>
20  */
21 class ChoiceQuestion extends Question
22 {
23     private $choices;
24     private $multiselect = false;
25     private $prompt = ' > ';
26     private $errorMessage = 'Value "%s" is invalid';
27
28     /**
29      * Constructor.
30      *
31      * @param string $question The question to ask to the user
32      * @param array  $choices  The list of available choices
33      * @param mixed  $default  The default answer to return
34      */
35     public function __construct($question, array $choices, $default = null)
36     {
37         if (!$choices) {
38             throw new \LogicException('Choice question must have at least 1 choice available.');
39         }
40
41         parent::__construct($question, $default);
42
43         $this->choices = $choices;
44         $this->setValidator($this->getDefaultValidator());
45         $this->setAutocompleterValues($choices);
46     }
47
48     /**
49      * Returns available choices.
50      *
51      * @return array
52      */
53     public function getChoices()
54     {
55         return $this->choices;
56     }
57
58     /**
59      * Sets multiselect option.
60      *
61      * When multiselect is set to true, multiple choices can be answered.
62      *
63      * @param bool $multiselect
64      *
65      * @return $this
66      */
67     public function setMultiselect($multiselect)
68     {
69         $this->multiselect = $multiselect;
70         $this->setValidator($this->getDefaultValidator());
71
72         return $this;
73     }
74
75     /**
76      * Returns whether the choices are multiselect.
77      *
78      * @return bool
79      */
80     public function isMultiselect()
81     {
82         return $this->multiselect;
83     }
84
85     /**
86      * Gets the prompt for choices.
87      *
88      * @return string
89      */
90     public function getPrompt()
91     {
92         return $this->prompt;
93     }
94
95     /**
96      * Sets the prompt for choices.
97      *
98      * @param string $prompt
99      *
100      * @return $this
101      */
102     public function setPrompt($prompt)
103     {
104         $this->prompt = $prompt;
105
106         return $this;
107     }
108
109     /**
110      * Sets the error message for invalid values.
111      *
112      * The error message has a string placeholder (%s) for the invalid value.
113      *
114      * @param string $errorMessage
115      *
116      * @return $this
117      */
118     public function setErrorMessage($errorMessage)
119     {
120         $this->errorMessage = $errorMessage;
121         $this->setValidator($this->getDefaultValidator());
122
123         return $this;
124     }
125
126     /**
127      * Returns the default answer validator.
128      *
129      * @return callable
130      */
131     private function getDefaultValidator()
132     {
133         $choices = $this->choices;
134         $errorMessage = $this->errorMessage;
135         $multiselect = $this->multiselect;
136         $isAssoc = $this->isAssoc($choices);
137
138         return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
139             // Collapse all spaces.
140             $selectedChoices = str_replace(' ', '', $selected);
141
142             if ($multiselect) {
143                 // Check for a separated comma values
144                 if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
145                     throw new InvalidArgumentException(sprintf($errorMessage, $selected));
146                 }
147                 $selectedChoices = explode(',', $selectedChoices);
148             } else {
149                 $selectedChoices = array($selected);
150             }
151
152             $multiselectChoices = array();
153             foreach ($selectedChoices as $value) {
154                 $results = array();
155                 foreach ($choices as $key => $choice) {
156                     if ($choice === $value) {
157                         $results[] = $key;
158                     }
159                 }
160
161                 if (count($results) > 1) {
162                     throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
163                 }
164
165                 $result = array_search($value, $choices);
166
167                 if (!$isAssoc) {
168                     if (false !== $result) {
169                         $result = $choices[$result];
170                     } elseif (isset($choices[$value])) {
171                         $result = $choices[$value];
172                     }
173                 } elseif (false === $result && isset($choices[$value])) {
174                     $result = $value;
175                 }
176
177                 if (false === $result) {
178                     throw new InvalidArgumentException(sprintf($errorMessage, $value));
179                 }
180
181                 $multiselectChoices[] = (string) $result;
182             }
183
184             if ($multiselect) {
185                 return $multiselectChoices;
186             }
187
188             return current($multiselectChoices);
189         };
190     }
191 }