Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 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 array $choices;
24
    private bool $multiselect = false;
25
    private string $prompt = ' > ';
26
    private string $errorMessage = 'Value "%s" is invalid';
27
 
28
    /**
29
     * @param string $question The question to ask to the user
30
     * @param array  $choices  The list of available choices
31
     * @param mixed  $default  The default answer to return
32
     */
33
    public function __construct(string $question, array $choices, mixed $default = null)
34
    {
35
        if (!$choices) {
36
            throw new \LogicException('Choice question must have at least 1 choice available.');
37
        }
38
 
39
        parent::__construct($question, $default);
40
 
41
        $this->choices = $choices;
42
        $this->setValidator($this->getDefaultValidator());
43
        $this->setAutocompleterValues($choices);
44
    }
45
 
46
    /**
47
     * Returns available choices.
48
     */
49
    public function getChoices(): array
50
    {
51
        return $this->choices;
52
    }
53
 
54
    /**
55
     * Sets multiselect option.
56
     *
57
     * When multiselect is set to true, multiple choices can be answered.
58
     *
59
     * @return $this
60
     */
61
    public function setMultiselect(bool $multiselect): static
62
    {
63
        $this->multiselect = $multiselect;
64
        $this->setValidator($this->getDefaultValidator());
65
 
66
        return $this;
67
    }
68
 
69
    /**
70
     * Returns whether the choices are multiselect.
71
     */
72
    public function isMultiselect(): bool
73
    {
74
        return $this->multiselect;
75
    }
76
 
77
    /**
78
     * Gets the prompt for choices.
79
     */
80
    public function getPrompt(): string
81
    {
82
        return $this->prompt;
83
    }
84
 
85
    /**
86
     * Sets the prompt for choices.
87
     *
88
     * @return $this
89
     */
90
    public function setPrompt(string $prompt): static
91
    {
92
        $this->prompt = $prompt;
93
 
94
        return $this;
95
    }
96
 
97
    /**
98
     * Sets the error message for invalid values.
99
     *
100
     * The error message has a string placeholder (%s) for the invalid value.
101
     *
102
     * @return $this
103
     */
104
    public function setErrorMessage(string $errorMessage): static
105
    {
106
        $this->errorMessage = $errorMessage;
107
        $this->setValidator($this->getDefaultValidator());
108
 
109
        return $this;
110
    }
111
 
112
    private function getDefaultValidator(): callable
113
    {
114
        $choices = $this->choices;
115
        $errorMessage = $this->errorMessage;
116
        $multiselect = $this->multiselect;
117
        $isAssoc = $this->isAssoc($choices);
118
 
119
        return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
120
            if ($multiselect) {
121
                // Check for a separated comma values
122
                if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) {
123
                    throw new InvalidArgumentException(sprintf($errorMessage, $selected));
124
                }
125
 
126
                $selectedChoices = explode(',', (string) $selected);
127
            } else {
128
                $selectedChoices = [$selected];
129
            }
130
 
131
            if ($this->isTrimmable()) {
132
                foreach ($selectedChoices as $k => $v) {
133
                    $selectedChoices[$k] = trim((string) $v);
134
                }
135
            }
136
 
137
            $multiselectChoices = [];
138
            foreach ($selectedChoices as $value) {
139
                $results = [];
140
                foreach ($choices as $key => $choice) {
141
                    if ($choice === $value) {
142
                        $results[] = $key;
143
                    }
144
                }
145
 
146
                if (\count($results) > 1) {
147
                    throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results)));
148
                }
149
 
150
                $result = array_search($value, $choices);
151
 
152
                if (!$isAssoc) {
153
                    if (false !== $result) {
154
                        $result = $choices[$result];
155
                    } elseif (isset($choices[$value])) {
156
                        $result = $choices[$value];
157
                    }
158
                } elseif (false === $result && isset($choices[$value])) {
159
                    $result = $value;
160
                }
161
 
162
                if (false === $result) {
163
                    throw new InvalidArgumentException(sprintf($errorMessage, $value));
164
                }
165
 
166
                // For associative choices, consistently return the key as string:
167
                $multiselectChoices[] = $isAssoc ? (string) $result : $result;
168
            }
169
 
170
            if ($multiselect) {
171
                return $multiselectChoices;
172
            }
173
 
174
            return current($multiselectChoices);
175
        };
176
    }
177
}