Added the Search API Synonym module to deal specifically with licence and license...
[yaffs-website] / vendor / symfony / console / Input / ArgvInput.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\Input;
13
14 use Symfony\Component\Console\Exception\RuntimeException;
15
16 /**
17  * ArgvInput represents an input coming from the CLI arguments.
18  *
19  * Usage:
20  *
21  *     $input = new ArgvInput();
22  *
23  * By default, the `$_SERVER['argv']` array is used for the input values.
24  *
25  * This can be overridden by explicitly passing the input values in the constructor:
26  *
27  *     $input = new ArgvInput($_SERVER['argv']);
28  *
29  * If you pass it yourself, don't forget that the first element of the array
30  * is the name of the running application.
31  *
32  * When passing an argument to the constructor, be sure that it respects
33  * the same rules as the argv one. It's almost always better to use the
34  * `StringInput` when you want to provide your own input.
35  *
36  * @author Fabien Potencier <fabien@symfony.com>
37  *
38  * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
39  * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
40  */
41 class ArgvInput extends Input
42 {
43     private $tokens;
44     private $parsed;
45
46     /**
47      * @param array|null           $argv       An array of parameters from the CLI (in the argv format)
48      * @param InputDefinition|null $definition A InputDefinition instance
49      */
50     public function __construct(array $argv = null, InputDefinition $definition = null)
51     {
52         if (null === $argv) {
53             $argv = $_SERVER['argv'];
54         }
55
56         // strip the application name
57         array_shift($argv);
58
59         $this->tokens = $argv;
60
61         parent::__construct($definition);
62     }
63
64     protected function setTokens(array $tokens)
65     {
66         $this->tokens = $tokens;
67     }
68
69     /**
70      * {@inheritdoc}
71      */
72     protected function parse()
73     {
74         $parseOptions = true;
75         $this->parsed = $this->tokens;
76         while (null !== $token = array_shift($this->parsed)) {
77             if ($parseOptions && '' == $token) {
78                 $this->parseArgument($token);
79             } elseif ($parseOptions && '--' == $token) {
80                 $parseOptions = false;
81             } elseif ($parseOptions && 0 === strpos($token, '--')) {
82                 $this->parseLongOption($token);
83             } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
84                 $this->parseShortOption($token);
85             } else {
86                 $this->parseArgument($token);
87             }
88         }
89     }
90
91     /**
92      * Parses a short option.
93      *
94      * @param string $token The current token
95      */
96     private function parseShortOption($token)
97     {
98         $name = substr($token, 1);
99
100         if (\strlen($name) > 1) {
101             if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
102                 // an option with a value (with no space)
103                 $this->addShortOption($name[0], substr($name, 1));
104             } else {
105                 $this->parseShortOptionSet($name);
106             }
107         } else {
108             $this->addShortOption($name, null);
109         }
110     }
111
112     /**
113      * Parses a short option set.
114      *
115      * @param string $name The current token
116      *
117      * @throws RuntimeException When option given doesn't exist
118      */
119     private function parseShortOptionSet($name)
120     {
121         $len = \strlen($name);
122         for ($i = 0; $i < $len; ++$i) {
123             if (!$this->definition->hasShortcut($name[$i])) {
124                 $encoding = mb_detect_encoding($name, null, true);
125                 throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
126             }
127
128             $option = $this->definition->getOptionForShortcut($name[$i]);
129             if ($option->acceptValue()) {
130                 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
131
132                 break;
133             } else {
134                 $this->addLongOption($option->getName(), null);
135             }
136         }
137     }
138
139     /**
140      * Parses a long option.
141      *
142      * @param string $token The current token
143      */
144     private function parseLongOption($token)
145     {
146         $name = substr($token, 2);
147
148         if (false !== $pos = strpos($name, '=')) {
149             if (0 === \strlen($value = substr($name, $pos + 1))) {
150                 // if no value after "=" then substr() returns "" since php7 only, false before
151                 // see http://php.net/manual/fr/migration70.incompatible.php#119151
152                 if (\PHP_VERSION_ID < 70000 && false === $value) {
153                     $value = '';
154                 }
155                 array_unshift($this->parsed, $value);
156             }
157             $this->addLongOption(substr($name, 0, $pos), $value);
158         } else {
159             $this->addLongOption($name, null);
160         }
161     }
162
163     /**
164      * Parses an argument.
165      *
166      * @param string $token The current token
167      *
168      * @throws RuntimeException When too many arguments are given
169      */
170     private function parseArgument($token)
171     {
172         $c = \count($this->arguments);
173
174         // if input is expecting another argument, add it
175         if ($this->definition->hasArgument($c)) {
176             $arg = $this->definition->getArgument($c);
177             $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
178
179         // if last argument isArray(), append token to last argument
180         } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
181             $arg = $this->definition->getArgument($c - 1);
182             $this->arguments[$arg->getName()][] = $token;
183
184         // unexpected argument
185         } else {
186             $all = $this->definition->getArguments();
187             if (\count($all)) {
188                 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
189             }
190
191             throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
192         }
193     }
194
195     /**
196      * Adds a short option value.
197      *
198      * @param string $shortcut The short option key
199      * @param mixed  $value    The value for the option
200      *
201      * @throws RuntimeException When option given doesn't exist
202      */
203     private function addShortOption($shortcut, $value)
204     {
205         if (!$this->definition->hasShortcut($shortcut)) {
206             throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
207         }
208
209         $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
210     }
211
212     /**
213      * Adds a long option value.
214      *
215      * @param string $name  The long option key
216      * @param mixed  $value The value for the option
217      *
218      * @throws RuntimeException When option given doesn't exist
219      */
220     private function addLongOption($name, $value)
221     {
222         if (!$this->definition->hasOption($name)) {
223             throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
224         }
225
226         $option = $this->definition->getOption($name);
227
228         if (null !== $value && !$option->acceptValue()) {
229             throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
230         }
231
232         if (\in_array($value, array('', null), true) && $option->acceptValue() && \count($this->parsed)) {
233             // if option accepts an optional or mandatory argument
234             // let's see if there is one provided
235             $next = array_shift($this->parsed);
236             if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, array('', null), true)) {
237                 $value = $next;
238             } else {
239                 array_unshift($this->parsed, $next);
240             }
241         }
242
243         if (null === $value) {
244             if ($option->isValueRequired()) {
245                 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
246             }
247
248             if (!$option->isArray() && !$option->isValueOptional()) {
249                 $value = true;
250             }
251         }
252
253         if ($option->isArray()) {
254             $this->options[$name][] = $value;
255         } else {
256             $this->options[$name] = $value;
257         }
258     }
259
260     /**
261      * {@inheritdoc}
262      */
263     public function getFirstArgument()
264     {
265         foreach ($this->tokens as $token) {
266             if ($token && '-' === $token[0]) {
267                 continue;
268             }
269
270             return $token;
271         }
272     }
273
274     /**
275      * {@inheritdoc}
276      */
277     public function hasParameterOption($values, $onlyParams = false)
278     {
279         $values = (array) $values;
280
281         foreach ($this->tokens as $token) {
282             if ($onlyParams && '--' === $token) {
283                 return false;
284             }
285             foreach ($values as $value) {
286                 // Options with values:
287                 //   For long options, test for '--option=' at beginning
288                 //   For short options, test for '-o' at beginning
289                 $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
290                 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
291                     return true;
292                 }
293             }
294         }
295
296         return false;
297     }
298
299     /**
300      * {@inheritdoc}
301      */
302     public function getParameterOption($values, $default = false, $onlyParams = false)
303     {
304         $values = (array) $values;
305         $tokens = $this->tokens;
306
307         while (0 < \count($tokens)) {
308             $token = array_shift($tokens);
309             if ($onlyParams && '--' === $token) {
310                 return $default;
311             }
312
313             foreach ($values as $value) {
314                 if ($token === $value) {
315                     return array_shift($tokens);
316                 }
317                 // Options with values:
318                 //   For long options, test for '--option=' at beginning
319                 //   For short options, test for '-o' at beginning
320                 $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
321                 if ('' !== $leading && 0 === strpos($token, $leading)) {
322                     return substr($token, \strlen($leading));
323                 }
324             }
325         }
326
327         return $default;
328     }
329
330     /**
331      * Returns a stringified representation of the args passed to the command.
332      *
333      * @return string
334      */
335     public function __toString()
336     {
337         $tokens = array_map(function ($token) {
338             if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
339                 return $match[1].$this->escapeToken($match[2]);
340             }
341
342             if ($token && '-' !== $token[0]) {
343                 return $this->escapeToken($token);
344             }
345
346             return $token;
347         }, $this->tokens);
348
349         return implode(' ', $tokens);
350     }
351 }