diff options
Diffstat (limited to 'vendor/symfony/console/Input/InputOption.php')
-rw-r--r-- | vendor/symfony/console/Input/InputOption.php | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php new file mode 100644 index 0000000..617c348 --- /dev/null +++ b/vendor/symfony/console/Input/InputOption.php | |||
@@ -0,0 +1,262 @@ | |||
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\Input; | ||
13 | |||
14 | use Symfony\Component\Console\Command\Command; | ||
15 | use Symfony\Component\Console\Completion\CompletionInput; | ||
16 | use Symfony\Component\Console\Completion\CompletionSuggestions; | ||
17 | use Symfony\Component\Console\Completion\Suggestion; | ||
18 | use Symfony\Component\Console\Exception\InvalidArgumentException; | ||
19 | use Symfony\Component\Console\Exception\LogicException; | ||
20 | |||
21 | /** | ||
22 | * Represents a command line option. | ||
23 | * | ||
24 | * @author Fabien Potencier <fabien@symfony.com> | ||
25 | */ | ||
26 | class InputOption | ||
27 | { | ||
28 | /** | ||
29 | * Do not accept input for the option (e.g. --yell). This is the default behavior of options. | ||
30 | */ | ||
31 | public const VALUE_NONE = 1; | ||
32 | |||
33 | /** | ||
34 | * A value must be passed when the option is used (e.g. --iterations=5 or -i5). | ||
35 | */ | ||
36 | public const VALUE_REQUIRED = 2; | ||
37 | |||
38 | /** | ||
39 | * The option may or may not have a value (e.g. --yell or --yell=loud). | ||
40 | */ | ||
41 | public const VALUE_OPTIONAL = 4; | ||
42 | |||
43 | /** | ||
44 | * The option accepts multiple values (e.g. --dir=/foo --dir=/bar). | ||
45 | */ | ||
46 | public const VALUE_IS_ARRAY = 8; | ||
47 | |||
48 | /** | ||
49 | * The option allows passing a negated variant (e.g. --ansi or --no-ansi). | ||
50 | */ | ||
51 | public const VALUE_NEGATABLE = 16; | ||
52 | |||
53 | private string $name; | ||
54 | private ?string $shortcut; | ||
55 | private int $mode; | ||
56 | private string|int|bool|array|float|null $default; | ||
57 | |||
58 | /** | ||
59 | * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts | ||
60 | * @param int-mask-of<InputOption::*>|null $mode The option mode: One of the VALUE_* constants | ||
61 | * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) | ||
62 | * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion | ||
63 | * | ||
64 | * @throws InvalidArgumentException If option mode is invalid or incompatible | ||
65 | */ | ||
66 | public function __construct( | ||
67 | string $name, | ||
68 | string|array|null $shortcut = null, | ||
69 | ?int $mode = null, | ||
70 | private string $description = '', | ||
71 | string|bool|int|float|array|null $default = null, | ||
72 | private array|\Closure $suggestedValues = [], | ||
73 | ) { | ||
74 | if (str_starts_with($name, '--')) { | ||
75 | $name = substr($name, 2); | ||
76 | } | ||
77 | |||
78 | if (!$name) { | ||
79 | throw new InvalidArgumentException('An option name cannot be empty.'); | ||
80 | } | ||
81 | |||
82 | if ('' === $shortcut || [] === $shortcut || false === $shortcut) { | ||
83 | $shortcut = null; | ||
84 | } | ||
85 | |||
86 | if (null !== $shortcut) { | ||
87 | if (\is_array($shortcut)) { | ||
88 | $shortcut = implode('|', $shortcut); | ||
89 | } | ||
90 | $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); | ||
91 | $shortcuts = array_filter($shortcuts, 'strlen'); | ||
92 | $shortcut = implode('|', $shortcuts); | ||
93 | |||
94 | if ('' === $shortcut) { | ||
95 | throw new InvalidArgumentException('An option shortcut cannot be empty.'); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (null === $mode) { | ||
100 | $mode = self::VALUE_NONE; | ||
101 | } elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) { | ||
102 | throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); | ||
103 | } | ||
104 | |||
105 | $this->name = $name; | ||
106 | $this->shortcut = $shortcut; | ||
107 | $this->mode = $mode; | ||
108 | |||
109 | if ($suggestedValues && !$this->acceptValue()) { | ||
110 | throw new LogicException('Cannot set suggested values if the option does not accept a value.'); | ||
111 | } | ||
112 | if ($this->isArray() && !$this->acceptValue()) { | ||
113 | throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); | ||
114 | } | ||
115 | if ($this->isNegatable() && $this->acceptValue()) { | ||
116 | throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.'); | ||
117 | } | ||
118 | |||
119 | $this->setDefault($default); | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * Returns the option shortcut. | ||
124 | */ | ||
125 | public function getShortcut(): ?string | ||
126 | { | ||
127 | return $this->shortcut; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Returns the option name. | ||
132 | */ | ||
133 | public function getName(): string | ||
134 | { | ||
135 | return $this->name; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Returns true if the option accepts a value. | ||
140 | * | ||
141 | * @return bool true if value mode is not self::VALUE_NONE, false otherwise | ||
142 | */ | ||
143 | public function acceptValue(): bool | ||
144 | { | ||
145 | return $this->isValueRequired() || $this->isValueOptional(); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * Returns true if the option requires a value. | ||
150 | * | ||
151 | * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise | ||
152 | */ | ||
153 | public function isValueRequired(): bool | ||
154 | { | ||
155 | return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * Returns true if the option takes an optional value. | ||
160 | * | ||
161 | * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise | ||
162 | */ | ||
163 | public function isValueOptional(): bool | ||
164 | { | ||
165 | return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * Returns true if the option can take multiple values. | ||
170 | * | ||
171 | * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise | ||
172 | */ | ||
173 | public function isArray(): bool | ||
174 | { | ||
175 | return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * Returns true if the option allows passing a negated variant. | ||
180 | * | ||
181 | * @return bool true if mode is self::VALUE_NEGATABLE, false otherwise | ||
182 | */ | ||
183 | public function isNegatable(): bool | ||
184 | { | ||
185 | return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Sets the default value. | ||
190 | */ | ||
191 | public function setDefault(string|bool|int|float|array|null $default): void | ||
192 | { | ||
193 | if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { | ||
194 | throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); | ||
195 | } | ||
196 | |||
197 | if ($this->isArray()) { | ||
198 | if (null === $default) { | ||
199 | $default = []; | ||
200 | } elseif (!\is_array($default)) { | ||
201 | throw new LogicException('A default value for an array option must be an array.'); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | $this->default = $this->acceptValue() || $this->isNegatable() ? $default : false; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Returns the default value. | ||
210 | */ | ||
211 | public function getDefault(): string|bool|int|float|array|null | ||
212 | { | ||
213 | return $this->default; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Returns the description text. | ||
218 | */ | ||
219 | public function getDescription(): string | ||
220 | { | ||
221 | return $this->description; | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * Returns true if the option has values for input completion. | ||
226 | */ | ||
227 | public function hasCompletion(): bool | ||
228 | { | ||
229 | return [] !== $this->suggestedValues; | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * Supplies suggestions when command resolves possible completion options for input. | ||
234 | * | ||
235 | * @see Command::complete() | ||
236 | */ | ||
237 | public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void | ||
238 | { | ||
239 | $values = $this->suggestedValues; | ||
240 | if ($values instanceof \Closure && !\is_array($values = $values($input))) { | ||
241 | throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, get_debug_type($values))); | ||
242 | } | ||
243 | if ($values) { | ||
244 | $suggestions->suggestValues($values); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Checks whether the given option equals this one. | ||
250 | */ | ||
251 | public function equals(self $option): bool | ||
252 | { | ||
253 | return $option->getName() === $this->getName() | ||
254 | && $option->getShortcut() === $this->getShortcut() | ||
255 | && $option->getDefault() === $this->getDefault() | ||
256 | && $option->isNegatable() === $this->isNegatable() | ||
257 | && $option->isArray() === $this->isArray() | ||
258 | && $option->isValueRequired() === $this->isValueRequired() | ||
259 | && $option->isValueOptional() === $this->isValueOptional() | ||
260 | ; | ||
261 | } | ||
262 | } | ||