PluginProbe
WindPress – Tailwind CSS integration for WordPress / 3.2.82
WindPress – Tailwind CSS integration for WordPress v3.2.82
3.2.90 3.2.89 3.2.88 3.2.87 3.2.86 3.2.85 3.2.84 3.2.83 3.2.82 3.2.81 trunk 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.2 3.0.3 3.0.4 3.0.5 All 144 releases
windpress / vendor / symfony / yaml / Inline.php

Inline.php in WindPress – Tailwind CSS integration for WordPress 3.2.82, at vendor/symfony/yaml/Inline.php

705 lines 33.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 namespace WindPressDeps\Symfony\Component\Yaml;
12
13 use WindPressDeps\Symfony\Component\Yaml\Exception\DumpException;
14 use WindPressDeps\Symfony\Component\Yaml\Exception\ParseException;
15 use WindPressDeps\Symfony\Component\Yaml\Tag\TaggedValue;
16 /**
17 * Inline implements a YAML parser/dumper for the YAML inline syntax.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 *
21 * @internal
22 */
23 class Inline
24 {
25 public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')';
26 public static $parsedLineNumber = -1;
27 public static $parsedFilename;
28 private static $exceptionOnInvalidType = \false;
29 private static $objectSupport = \false;
30 private static $objectForMap = \false;
31 private static $constantSupport = \false;
32 public static function initialize(int $flags, ?int $parsedLineNumber = null, ?string $parsedFilename = null)
33 {
34 self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags);
35 self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
36 self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
37 self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
38 self::$parsedFilename = $parsedFilename;
39 if (null !== $parsedLineNumber) {
40 self::$parsedLineNumber = $parsedLineNumber;
41 }
42 }
43 /**
44 * Converts a YAML string to a PHP value.
45 *
46 * @param string|null $value A YAML string
47 * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior
48 * @param array $references Mapping of variable names to values
49 *
50 * @return mixed
51 *
52 * @throws ParseException
53 */
54 public static function parse(?string $value = null, int $flags = 0, array &$references = [])
55 {
56 if (null === $value) {
57 return '';
58 }
59 self::initialize($flags);
60 $value = trim($value);
61 if ('' === $value) {
62 return '';
63 }
64 if (2 & (int) \ini_get('mbstring.func_overload')) {
65 $mbEncoding = mb_internal_encoding();
66 mb_internal_encoding('ASCII');
67 }
68 try {
69 $i = 0;
70 $tag = self::parseTag($value, $i, $flags);
71 switch ($value[$i]) {
72 case '[':
73 $result = self::parseSequence($value, $flags, $i, $references);
74 ++$i;
75 break;
76 case '{':
77 $result = self::parseMapping($value, $flags, $i, $references);
78 ++$i;
79 break;
80 default:
81 $result = self::parseScalar($value, $flags, null, $i, \true, $references);
82 }
83 // some comments are allowed at the end
84 if (preg_replace('/\s*#.*$/A', '', substr($value, $i))) {
85 throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
86 }
87 if (null !== $tag && '' !== $tag) {
88 return new TaggedValue($tag, $result);
89 }
90 return $result;
91 } finally {
92 if (isset($mbEncoding)) {
93 mb_internal_encoding($mbEncoding);
94 }
95 }
96 }
97 /**
98 * Dumps a given PHP variable to a YAML string.
99 *
100 * @param mixed $value The PHP variable to convert
101 * @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
102 *
103 * @throws DumpException When trying to dump PHP resource
104 */
105 public static function dump($value, int $flags = 0): string
106 {
107 switch (\true) {
108 case \is_resource($value):
109 if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
110 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
111 }
112 return self::dumpNull($flags);
113 case $value instanceof \DateTimeInterface:
114 return $value->format('c');
115 case $value instanceof \UnitEnum:
116 return sprintf('!php/const %s::%s', \get_class($value), $value->name);
117 case \is_object($value):
118 if ($value instanceof TaggedValue) {
119 return '!' . $value->getTag() . ' ' . self::dump($value->getValue(), $flags);
120 }
121 if (Yaml::DUMP_OBJECT & $flags) {
122 return '!php/object ' . self::dump(serialize($value));
123 }
124 if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) {
125 $output = [];
126 foreach ($value as $key => $val) {
127 $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
128 }
129 return sprintf('{ %s }', implode(', ', $output));
130 }
131 if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
132 throw new DumpException('Object support when dumping a YAML file has been disabled.');
133 }
134 return self::dumpNull($flags);
135 case \is_array($value):
136 return self::dumpArray($value, $flags);
137 case null === $value:
138 return self::dumpNull($flags);
139 case \true === $value:
140 return 'true';
141 case \false === $value:
142 return 'false';
143 case \is_int($value):
144 return $value;
145 case is_numeric($value) && \false === strpbrk($value, "\f\n\r\t\v"):
146 $locale = setlocale(\LC_NUMERIC, 0);
147 if (\false !== $locale) {
148 setlocale(\LC_NUMERIC, 'C');
149 }
150 if (\is_float($value)) {
151 $repr = (string) $value;
152 if (is_infinite($value)) {
153 $repr = str_ireplace('INF', '.Inf', $repr);
154 } elseif (floor($value) == $value && $repr == $value) {
155 // Preserve float data type since storing a whole number will result in integer value.
156 if (\false === strpos($repr, 'E')) {
157 $repr = $repr . '.0';
158 }
159 }
160 } else {
161 $repr = \is_string($value) ? "'{$value}'" : (string) $value;
162 }
163 if (\false !== $locale) {
164 setlocale(\LC_NUMERIC, $locale);
165 }
166 return $repr;
167 case '' == $value:
168 return "''";
169 case self::isBinaryString($value):
170 return '!!binary ' . base64_encode($value);
171 case Escaper::requiresDoubleQuoting($value):
172 return Escaper::escapeWithDoubleQuotes($value);
173 case Escaper::requiresSingleQuoting($value):
174 case Parser::preg_match('{^[0-9]+[_0-9]*$}', $value):
175 case Parser::preg_match(self::getHexRegex(), $value):
176 case Parser::preg_match(self::getTimestampRegex(), $value):
177 return Escaper::escapeWithSingleQuotes($value);
178 default:
179 return $value;
180 }
181 }
182 /**
183 * Check if given array is hash or just normal indexed array.
184 *
185 * @param array|\ArrayObject|\stdClass $value The PHP array or array-like object to check
186 */
187 public static function isHash($value): bool
188 {
189 if ($value instanceof \stdClass || $value instanceof \ArrayObject) {
190 return \true;
191 }
192 $expectedKey = 0;
193 foreach ($value as $key => $val) {
194 if ($key !== $expectedKey++) {
195 return \true;
196 }
197 }
198 return \false;
199 }
200 /**
201 * Dumps a PHP array to a YAML string.
202 *
203 * @param array $value The PHP array to dump
204 * @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
205 */
206 private static function dumpArray(array $value, int $flags): string
207 {
208 // array
209 if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) {
210 $output = [];
211 foreach ($value as $val) {
212 $output[] = self::dump($val, $flags);
213 }
214 return sprintf('[%s]', implode(', ', $output));
215 }
216 // hash
217 $output = [];
218 foreach ($value as $key => $val) {
219 $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
220 }
221 return sprintf('{ %s }', implode(', ', $output));
222 }
223 private static function dumpNull(int $flags): string
224 {
225 if (Yaml::DUMP_NULL_AS_TILDE & $flags) {
226 return '~';
227 }
228 return 'null';
229 }
230 /**
231 * Parses a YAML scalar.
232 *
233 * @return mixed
234 *
235 * @throws ParseException When malformed inline YAML string is parsed
236 */
237 public static function parseScalar(string $scalar, int $flags = 0, ?array $delimiters = null, int &$i = 0, bool $evaluate = \true, array &$references = [], ?bool &$isQuoted = null)
238 {
239 if (\in_array($scalar[$i], ['"', "'"], \true)) {
240 // quoted scalar
241 $isQuoted = \true;
242 $output = self::parseQuotedScalar($scalar, $i);
243 if (null !== $delimiters) {
244 $tmp = ltrim(substr($scalar, $i), " \n");
245 if ('' === $tmp) {
246 throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode('', $delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
247 }
248 if (!\in_array($tmp[0], $delimiters)) {
249 throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
250 }
251 }
252 } else {
253 // "normal" string
254 $isQuoted = \false;
255 if (!$delimiters) {
256 $output = substr($scalar, $i);
257 $i += \strlen($output);
258 // remove comments
259 if (Parser::preg_match('/[ \t]+#/', $output, $match, \PREG_OFFSET_CAPTURE)) {
260 $output = substr($output, 0, $match[0][1]);
261 }
262 } elseif (Parser::preg_match('/^(.*?)(' . implode('|', $delimiters) . ')/', substr($scalar, $i), $match)) {
263 $output = $match[1];
264 $i += \strlen($output);
265 $output = trim($output);
266 } else {
267 throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename);
268 }
269 // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >)
270 if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0] || '%' === $output[0])) {
271 throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]), self::$parsedLineNumber + 1, $output, self::$parsedFilename);
272 }
273 if ($evaluate) {
274 $output = self::evaluateScalar($output, $flags, $references, $isQuoted);
275 }
276 }
277 return $output;
278 }
279 /**
280 * Parses a YAML quoted scalar.
281 *
282 * @throws ParseException When malformed inline YAML string is parsed
283 */
284 private static function parseQuotedScalar(string $scalar, int &$i = 0): string
285 {
286 if (!Parser::preg_match('/' . self::REGEX_QUOTED_STRING . '/Au', substr($scalar, $i), $match)) {
287 throw new ParseException(sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
288 }
289 $output = substr($match[0], 1, -1);
290 $unescaper = new Unescaper();
291 if ('"' == $scalar[$i]) {
292 $output = $unescaper->unescapeDoubleQuotedString($output);
293 } else {
294 $output = $unescaper->unescapeSingleQuotedString($output);
295 }
296 $i += \strlen($match[0]);
297 return $output;
298 }
299 /**
300 * Parses a YAML sequence.
301 *
302 * @throws ParseException When malformed inline YAML string is parsed
303 */
304 private static function parseSequence(string $sequence, int $flags, int &$i = 0, array &$references = []): array
305 {
306 $output = [];
307 $len = \strlen($sequence);
308 ++$i;
309 // [foo, bar, ...]
310 $lastToken = null;
311 while ($i < $len) {
312 if (']' === $sequence[$i]) {
313 return $output;
314 }
315 if (',' === $sequence[$i] || ' ' === $sequence[$i]) {
316 if (',' === $sequence[$i] && (null === $lastToken || 'separator' === $lastToken)) {
317 $output[] = null;
318 } elseif (',' === $sequence[$i]) {
319 $lastToken = 'separator';
320 }
321 ++$i;
322 continue;
323 }
324 $tag = self::parseTag($sequence, $i, $flags);
325 switch ($sequence[$i]) {
326 case '[':
327 // nested sequence
328 $value = self::parseSequence($sequence, $flags, $i, $references);
329 break;
330 case '{':
331 // nested mapping
332 $value = self::parseMapping($sequence, $flags, $i, $references);
333 break;
334 default:
335 $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references, $isQuoted);
336 // the value can be an array if a reference has been resolved to an array var
337 if (\is_string($value) && !$isQuoted && \false !== strpos($value, ': ')) {
338 // embedded mapping?
339 try {
340 $pos = 0;
341 $value = self::parseMapping('{' . $value . '}', $flags, $pos, $references);
342 } catch (\InvalidArgumentException $e) {
343 // no, it's not
344 }
345 }
346 if (!$isQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
347 $references[$matches['ref']] = $matches['value'];
348 $value = $matches['value'];
349 }
350 --$i;
351 }
352 if (null !== $tag && '' !== $tag) {
353 $value = new TaggedValue($tag, $value);
354 }
355 $output[] = $value;
356 $lastToken = 'value';
357 ++$i;
358 }
359 throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename);
360 }
361 /**
362 * Parses a YAML mapping.
363 *
364 * @return array|\stdClass
365 *
366 * @throws ParseException When malformed inline YAML string is parsed
367 */
368 private static function parseMapping(string $mapping, int $flags, int &$i = 0, array &$references = [])
369 {
370 $output = [];
371 $len = \strlen($mapping);
372 ++$i;
373 $allowOverwrite = \false;
374 // {foo: bar, bar:foo, ...}
375 while ($i < $len) {
376 switch ($mapping[$i]) {
377 case ' ':
378 case ',':
379 case "\n":
380 ++$i;
381 continue 2;
382 case '}':
383 if (self::$objectForMap) {
384 return (object) $output;
385 }
386 return $output;
387 }
388 // key
389 $offsetBeforeKeyParsing = $i;
390 $isKeyQuoted = \in_array($mapping[$i], ['"', "'"], \true);
391 $key = self::parseScalar($mapping, $flags, [':', ' '], $i, \false);
392 if ($offsetBeforeKeyParsing === $i) {
393 throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping);
394 }
395 if ('!php/const' === $key) {
396 $key .= ' ' . self::parseScalar($mapping, $flags, [':'], $i, \false);
397 $key = self::evaluateScalar($key, $flags);
398 }
399 if (\false === $i = strpos($mapping, ':', $i)) {
400 break;
401 }
402 if (!$isKeyQuoted) {
403 $evaluatedKey = self::evaluateScalar($key, $flags, $references);
404 if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) {
405 throw new ParseException('Implicit casting of incompatible mapping keys to strings is not supported. Quote your evaluable mapping keys instead.', self::$parsedLineNumber + 1, $mapping);
406 }
407 }
408 if (!$isKeyQuoted && (!isset($mapping[$i + 1]) || !\in_array($mapping[$i + 1], [' ', ',', '[', ']', '{', '}', "\n"], \true))) {
409 throw new ParseException('Colons must be followed by a space or an indication character (i.e. " ", ",", "[", "]", "{", "}").', self::$parsedLineNumber + 1, $mapping);
410 }
411 if ('<<' === $key) {
412 $allowOverwrite = \true;
413 }
414 while ($i < $len) {
415 if (':' === $mapping[$i] || ' ' === $mapping[$i] || "\n" === $mapping[$i]) {
416 ++$i;
417 continue;
418 }
419 $tag = self::parseTag($mapping, $i, $flags);
420 switch ($mapping[$i]) {
421 case '[':
422 // nested sequence
423 $value = self::parseSequence($mapping, $flags, $i, $references);
424 // Spec: Keys MUST be unique; first one wins.
425 // Parser cannot abort this mapping earlier, since lines
426 // are processed sequentially.
427 // But overwriting is allowed when a merge node is used in current block.
428 if ('<<' === $key) {
429 foreach ($value as $parsedValue) {
430 $output += $parsedValue;
431 }
432 } elseif ($allowOverwrite || !isset($output[$key])) {
433 if (null !== $tag) {
434 $output[$key] = new TaggedValue($tag, $value);
435 } else {
436 $output[$key] = $value;
437 }
438 } elseif (isset($output[$key])) {
439 throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
440 }
441 break;
442 case '{':
443 // nested mapping
444 $value = self::parseMapping($mapping, $flags, $i, $references);
445 // Spec: Keys MUST be unique; first one wins.
446 // Parser cannot abort this mapping earlier, since lines
447 // are processed sequentially.
448 // But overwriting is allowed when a merge node is used in current block.
449 if ('<<' === $key) {
450 $output += $value;
451 } elseif ($allowOverwrite || !isset($output[$key])) {
452 if (null !== $tag) {
453 $output[$key] = new TaggedValue($tag, $value);
454 } else {
455 $output[$key] = $value;
456 }
457 } elseif (isset($output[$key])) {
458 throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
459 }
460 break;
461 default:
462 $value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references, $isValueQuoted);
463 // Spec: Keys MUST be unique; first one wins.
464 // Parser cannot abort this mapping earlier, since lines
465 // are processed sequentially.
466 // But overwriting is allowed when a merge node is used in current block.
467 if ('<<' === $key) {
468 $output += $value;
469 } elseif ($allowOverwrite || !isset($output[$key])) {
470 if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && !self::isBinaryString($value) && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) {
471 $references[$matches['ref']] = $matches['value'];
472 $value = $matches['value'];
473 }
474 if (null !== $tag) {
475 $output[$key] = new TaggedValue($tag, $value);
476 } else {
477 $output[$key] = $value;
478 }
479 } elseif (isset($output[$key])) {
480 throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping);
481 }
482 --$i;
483 }
484 ++$i;
485 continue 2;
486 }
487 }
488 throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename);
489 }
490 /**
491 * Evaluates scalars and replaces magic values.
492 *
493 * @return mixed
494 *
495 * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved
496 */
497 private static function evaluateScalar(string $scalar, int $flags, array &$references = [], ?bool &$isQuotedString = null)
498 {
499 $isQuotedString = \false;
500 $scalar = trim($scalar);
501 if (0 === strpos($scalar, '*')) {
502 if (\false !== $pos = strpos($scalar, '#')) {
503 $value = substr($scalar, 1, $pos - 2);
504 } else {
505 $value = substr($scalar, 1);
506 }
507 // an unquoted *
508 if (\false === $value || '' === $value) {
509 throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename);
510 }
511 if (!\array_key_exists($value, $references)) {
512 throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
513 }
514 return $references[$value];
515 }
516 $scalarLower = strtolower($scalar);
517 switch (\true) {
518 case 'null' === $scalarLower:
519 case '' === $scalar:
520 case '~' === $scalar:
521 return null;
522 case 'true' === $scalarLower:
523 return \true;
524 case 'false' === $scalarLower:
525 return \false;
526 case '!' === $scalar[0]:
527 switch (\true) {
528 case 0 === strpos($scalar, '!!str '):
529 $s = (string) substr($scalar, 6);
530 if (\in_array($s[0] ?? '', ['"', "'"], \true)) {
531 $isQuotedString = \true;
532 $s = self::parseQuotedScalar($s);
533 }
534 return $s;
535 case 0 === strpos($scalar, '! '):
536 return substr($scalar, 2);
537 case 0 === strpos($scalar, '!php/object'):
538 if (self::$objectSupport) {
539 if (!isset($scalar[12])) {
540 trigger_deprecation('symfony/yaml', '5.1', 'Using the !php/object tag without a value is deprecated.');
541 return \false;
542 }
543 return unserialize(self::parseScalar(substr($scalar, 12)));
544 }
545 if (self::$exceptionOnInvalidType) {
546 throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
547 }
548 return null;
549 case 0 === strpos($scalar, '!php/const'):
550 if (self::$constantSupport) {
551 if (!isset($scalar[11])) {
552 trigger_deprecation('symfony/yaml', '5.1', 'Using the !php/const tag without a value is deprecated.');
553 return '';
554 }
555 $i = 0;
556 if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, \false))) {
557 return \constant($const);
558 }
559 throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
560 }
561 if (self::$exceptionOnInvalidType) {
562 throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
563 }
564 return null;
565 case 0 === strpos($scalar, '!!float '):
566 return (float) substr($scalar, 8);
567 case 0 === strpos($scalar, '!!binary '):
568 return self::evaluateBinaryScalar(substr($scalar, 9));
569 }
570 throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename);
571 case preg_match('/^(?:\+|-)?0o(?P<value>[0-7_]++)$/', $scalar, $matches):
572 $value = str_replace('_', '', $matches['value']);
573 if ('-' === $scalar[0]) {
574 return -octdec($value);
575 }
576 return octdec($value);
577 case \in_array($scalar[0], ['+', '-', '.'], \true) || is_numeric($scalar[0]):
578 if (Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar)) {
579 $scalar = str_replace('_', '', $scalar);
580 }
581 switch (\true) {
582 case ctype_digit($scalar):
583 if (preg_match('/^0[0-7]+$/', $scalar)) {
584 trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0. Use "%s" to represent the octal number.', '0o' . substr($scalar, 1));
585 return octdec($scalar);
586 }
587 $cast = (int) $scalar;
588 return $scalar === (string) $cast ? $cast : $scalar;
589 case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
590 if (preg_match('/^-0[0-7]+$/', $scalar)) {
591 trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0. Use "%s" to represent the octal number.', '-0o' . substr($scalar, 2));
592 return -octdec(substr($scalar, 1));
593 }
594 $cast = (int) $scalar;
595 return $scalar === (string) $cast ? $cast : $scalar;
596 case is_numeric($scalar):
597 case Parser::preg_match(self::getHexRegex(), $scalar):
598 $scalar = str_replace('_', '', $scalar);
599 return '0x' === $scalar[0] . $scalar[1] ? hexdec($scalar) : (float) $scalar;
600 case '.inf' === $scalarLower:
601 case '.nan' === $scalarLower:
602 return -log(0);
603 case '-.inf' === $scalarLower:
604 return log(0);
605 case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar):
606 return (float) str_replace('_', '', $scalar);
607 case Parser::preg_match(self::getTimestampRegex(), $scalar):
608 try {
609 // When no timezone is provided in the parsed date, YAML spec says we must assume UTC.
610 $time = new \DateTime($scalar, new \DateTimeZone('UTC'));
611 } catch (\Exception $e) {
612 // Some dates accepted by the regex are not valid dates.
613 throw new ParseException(\sprintf('The date "%s" could not be parsed as it is an invalid date.', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename, $e);
614 }
615 if (Yaml::PARSE_DATETIME & $flags) {
616 return $time;
617 }
618 try {
619 if (\false !== $scalar = $time->getTimestamp()) {
620 return $scalar;
621 }
622 } catch (\ValueError $e) {
623 // no-op
624 }
625 return $time->format('U');
626 }
627 }
628 return (string) $scalar;
629 }
630 private static function parseTag(string $value, int &$i, int $flags): ?string
631 {
632 if ('!' !== $value[$i]) {
633 return null;
634 }
635 $tagLength = strcspn($value, " \t\n[]{},", $i + 1);
636 $tag = substr($value, $i + 1, $tagLength);
637 $nextOffset = $i + $tagLength + 1;
638 $nextOffset += strspn($value, ' ', $nextOffset);
639 if ('' === $tag && (!isset($value[$nextOffset]) || \in_array($value[$nextOffset], [']', '}', ','], \true))) {
640 throw new ParseException('Using the unquoted scalar value "!" is not supported. You must quote it.', self::$parsedLineNumber + 1, $value, self::$parsedFilename);
641 }
642 // Is followed by a scalar and is a built-in tag
643 if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], \true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) {
644 // Manage in {@link self::evaluateScalar()}
645 return null;
646 }
647 $i = $nextOffset;
648 // Built-in tags
649 if ('' !== $tag && '!' === $tag[0]) {
650 throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
651 }
652 if ('' !== $tag && !isset($value[$i])) {
653 throw new ParseException(sprintf('Missing value for tag "%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
654 }
655 if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) {
656 return $tag;
657 }
658 throw new ParseException(sprintf('Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename);
659 }
660 public static function evaluateBinaryScalar(string $scalar): string
661 {
662 $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar));
663 if (0 !== \strlen($parsedBinaryData) % 4) {
664 throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', \strlen($parsedBinaryData)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
665 }
666 if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) {
667 throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
668 }
669 return base64_decode($parsedBinaryData, \true);
670 }
671 private static function isBinaryString(string $value): bool
672 {
673 return !preg_match('//u', $value) || preg_match('/[^\x00\x07-\x0d\x1B\x20-\xff]/', $value);
674 }
675 /**
676 * Gets a regex that matches a YAML date.
677 *
678 * @see http://www.yaml.org/spec/1.2/spec.html#id2761573
679 */
680 private static function getTimestampRegex(): string
681 {
682 return <<<EOF
683 ~^
684 (?P<year>[0-9][0-9][0-9][0-9])
685 -(?P<month>[0-9][0-9]?)
686 -(?P<day>[0-9][0-9]?)
687 (?:(?:[Tt]|[ \t]+)
688 (?P<hour>[0-9][0-9]?)
689 :(?P<minute>[0-9][0-9])
690 :(?P<second>[0-9][0-9])
691 (?:\\.(?P<fraction>[0-9]*))?
692 (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
693 (?::(?P<tz_minute>[0-9][0-9]))?))?)?
694 \$~x
695 EOF;
696 }
697 /**
698 * Gets a regex that matches a YAML number in hexadecimal notation.
699 */
700 private static function getHexRegex(): string
701 {
702 return '~^0x[0-9a-f_]++$~i';
703 }
704 }
705