Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/yaml/Inline.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | 7a779792577d |
children | c2387f117808 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
11 | 11 |
12 namespace Symfony\Component\Yaml; | 12 namespace Symfony\Component\Yaml; |
13 | 13 |
14 use Symfony\Component\Yaml\Exception\ParseException; | 14 use Symfony\Component\Yaml\Exception\ParseException; |
15 use Symfony\Component\Yaml\Exception\DumpException; | 15 use Symfony\Component\Yaml\Exception\DumpException; |
16 use Symfony\Component\Yaml\Tag\TaggedValue; | |
16 | 17 |
17 /** | 18 /** |
18 * Inline implements a YAML parser/dumper for the YAML inline syntax. | 19 * Inline implements a YAML parser/dumper for the YAML inline syntax. |
19 * | 20 * |
20 * @author Fabien Potencier <fabien@symfony.com> | 21 * @author Fabien Potencier <fabien@symfony.com> |
23 */ | 24 */ |
24 class Inline | 25 class Inline |
25 { | 26 { |
26 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')'; | 27 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')'; |
27 | 28 |
28 public static $parsedLineNumber; | 29 public static $parsedLineNumber = -1; |
30 public static $parsedFilename; | |
29 | 31 |
30 private static $exceptionOnInvalidType = false; | 32 private static $exceptionOnInvalidType = false; |
31 private static $objectSupport = false; | 33 private static $objectSupport = false; |
32 private static $objectForMap = false; | 34 private static $objectForMap = false; |
33 private static $constantSupport = false; | 35 private static $constantSupport = false; |
34 | 36 |
35 /** | 37 /** |
38 * @param int $flags | |
39 * @param int|null $parsedLineNumber | |
40 * @param string|null $parsedFilename | |
41 */ | |
42 public static function initialize($flags, $parsedLineNumber = null, $parsedFilename = null) | |
43 { | |
44 self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); | |
45 self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); | |
46 self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); | |
47 self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); | |
48 self::$parsedFilename = $parsedFilename; | |
49 | |
50 if (null !== $parsedLineNumber) { | |
51 self::$parsedLineNumber = $parsedLineNumber; | |
52 } | |
53 } | |
54 | |
55 /** | |
36 * Converts a YAML string to a PHP value. | 56 * Converts a YAML string to a PHP value. |
37 * | 57 * |
38 * @param string $value A YAML string | 58 * @param string $value A YAML string |
39 * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior | 59 * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior |
40 * @param array $references Mapping of variable names to values | 60 * @param array $references Mapping of variable names to values |
44 * @throws ParseException | 64 * @throws ParseException |
45 */ | 65 */ |
46 public static function parse($value, $flags = 0, $references = array()) | 66 public static function parse($value, $flags = 0, $references = array()) |
47 { | 67 { |
48 if (is_bool($flags)) { | 68 if (is_bool($flags)) { |
49 @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); | 69 @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); |
50 | 70 |
51 if ($flags) { | 71 if ($flags) { |
52 $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; | 72 $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; |
53 } else { | 73 } else { |
54 $flags = 0; | 74 $flags = 0; |
55 } | 75 } |
56 } | 76 } |
57 | 77 |
58 if (func_num_args() >= 3 && !is_array($references)) { | 78 if (func_num_args() >= 3 && !is_array($references)) { |
59 @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); | 79 @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); |
60 | 80 |
61 if ($references) { | 81 if ($references) { |
62 $flags |= Yaml::PARSE_OBJECT; | 82 $flags |= Yaml::PARSE_OBJECT; |
63 } | 83 } |
64 | 84 |
65 if (func_num_args() >= 4) { | 85 if (func_num_args() >= 4) { |
66 @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); | 86 @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); |
67 | 87 |
68 if (func_get_arg(3)) { | 88 if (func_get_arg(3)) { |
69 $flags |= Yaml::PARSE_OBJECT_FOR_MAP; | 89 $flags |= Yaml::PARSE_OBJECT_FOR_MAP; |
70 } | 90 } |
71 } | 91 } |
75 } else { | 95 } else { |
76 $references = array(); | 96 $references = array(); |
77 } | 97 } |
78 } | 98 } |
79 | 99 |
80 self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); | 100 self::initialize($flags); |
81 self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); | |
82 self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); | |
83 self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); | |
84 | 101 |
85 $value = trim($value); | 102 $value = trim($value); |
86 | 103 |
87 if ('' === $value) { | 104 if ('' === $value) { |
88 return ''; | 105 return ''; |
92 $mbEncoding = mb_internal_encoding(); | 109 $mbEncoding = mb_internal_encoding(); |
93 mb_internal_encoding('ASCII'); | 110 mb_internal_encoding('ASCII'); |
94 } | 111 } |
95 | 112 |
96 $i = 0; | 113 $i = 0; |
97 switch ($value[0]) { | 114 $tag = self::parseTag($value, $i, $flags); |
115 switch ($value[$i]) { | |
98 case '[': | 116 case '[': |
99 $result = self::parseSequence($value, $flags, $i, $references); | 117 $result = self::parseSequence($value, $flags, $i, $references); |
100 ++$i; | 118 ++$i; |
101 break; | 119 break; |
102 case '{': | 120 case '{': |
103 $result = self::parseMapping($value, $flags, $i, $references); | 121 $result = self::parseMapping($value, $flags, $i, $references); |
104 ++$i; | 122 ++$i; |
105 break; | 123 break; |
106 default: | 124 default: |
107 $result = self::parseScalar($value, $flags, null, array('"', "'"), $i, true, $references); | 125 $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); |
126 } | |
127 | |
128 if (null !== $tag) { | |
129 return new TaggedValue($tag, $result); | |
108 } | 130 } |
109 | 131 |
110 // some comments are allowed at the end | 132 // some comments are allowed at the end |
111 if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { | 133 if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { |
112 throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); | 134 throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename); |
113 } | 135 } |
114 | 136 |
115 if (isset($mbEncoding)) { | 137 if (isset($mbEncoding)) { |
116 mb_internal_encoding($mbEncoding); | 138 mb_internal_encoding($mbEncoding); |
117 } | 139 } |
130 * @throws DumpException When trying to dump PHP resource | 152 * @throws DumpException When trying to dump PHP resource |
131 */ | 153 */ |
132 public static function dump($value, $flags = 0) | 154 public static function dump($value, $flags = 0) |
133 { | 155 { |
134 if (is_bool($flags)) { | 156 if (is_bool($flags)) { |
135 @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); | 157 @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); |
136 | 158 |
137 if ($flags) { | 159 if ($flags) { |
138 $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; | 160 $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; |
139 } else { | 161 } else { |
140 $flags = 0; | 162 $flags = 0; |
141 } | 163 } |
142 } | 164 } |
143 | 165 |
144 if (func_num_args() >= 3) { | 166 if (func_num_args() >= 3) { |
145 @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); | 167 @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); |
146 | 168 |
147 if (func_get_arg(2)) { | 169 if (func_get_arg(2)) { |
148 $flags |= Yaml::DUMP_OBJECT; | 170 $flags |= Yaml::DUMP_OBJECT; |
149 } | 171 } |
150 } | 172 } |
157 | 179 |
158 return 'null'; | 180 return 'null'; |
159 case $value instanceof \DateTimeInterface: | 181 case $value instanceof \DateTimeInterface: |
160 return $value->format('c'); | 182 return $value->format('c'); |
161 case is_object($value): | 183 case is_object($value): |
184 if ($value instanceof TaggedValue) { | |
185 return '!'.$value->getTag().' '.self::dump($value->getValue(), $flags); | |
186 } | |
187 | |
162 if (Yaml::DUMP_OBJECT & $flags) { | 188 if (Yaml::DUMP_OBJECT & $flags) { |
163 return '!php/object:'.serialize($value); | 189 return '!php/object '.self::dump(serialize($value)); |
164 } | 190 } |
165 | 191 |
166 if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { | 192 if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { |
167 return self::dumpArray($value, $flags); | 193 return self::dumpArray($value, $flags & ~Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); |
168 } | 194 } |
169 | 195 |
170 if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { | 196 if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { |
171 throw new DumpException('Object support when dumping a YAML file has been disabled.'); | 197 throw new DumpException('Object support when dumping a YAML file has been disabled.'); |
172 } | 198 } |
254 * @return string The YAML string representing the PHP array | 280 * @return string The YAML string representing the PHP array |
255 */ | 281 */ |
256 private static function dumpArray($value, $flags) | 282 private static function dumpArray($value, $flags) |
257 { | 283 { |
258 // array | 284 // array |
259 if ($value && !self::isHash($value)) { | 285 if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) { |
260 $output = array(); | 286 $output = array(); |
261 foreach ($value as $val) { | 287 foreach ($value as $val) { |
262 $output[] = self::dump($val, $flags); | 288 $output[] = self::dump($val, $flags); |
263 } | 289 } |
264 | 290 |
278 * Parses a YAML scalar. | 304 * Parses a YAML scalar. |
279 * | 305 * |
280 * @param string $scalar | 306 * @param string $scalar |
281 * @param int $flags | 307 * @param int $flags |
282 * @param string[] $delimiters | 308 * @param string[] $delimiters |
283 * @param string[] $stringDelimiters | |
284 * @param int &$i | 309 * @param int &$i |
285 * @param bool $evaluate | 310 * @param bool $evaluate |
286 * @param array $references | 311 * @param array $references |
287 * | 312 * |
288 * @return string | 313 * @return string |
289 * | 314 * |
290 * @throws ParseException When malformed inline YAML string is parsed | 315 * @throws ParseException When malformed inline YAML string is parsed |
291 * | 316 * |
292 * @internal | 317 * @internal |
293 */ | 318 */ |
294 public static function parseScalar($scalar, $flags = 0, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true, $references = array()) | 319 public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = array(), $legacyOmittedKeySupport = false) |
295 { | 320 { |
296 if (in_array($scalar[$i], $stringDelimiters)) { | 321 if (in_array($scalar[$i], array('"', "'"))) { |
297 // quoted scalar | 322 // quoted scalar |
298 $output = self::parseQuotedScalar($scalar, $i); | 323 $output = self::parseQuotedScalar($scalar, $i); |
299 | 324 |
300 if (null !== $delimiters) { | 325 if (null !== $delimiters) { |
301 $tmp = ltrim(substr($scalar, $i), ' '); | 326 $tmp = ltrim(substr($scalar, $i), ' '); |
302 if (!in_array($tmp[0], $delimiters)) { | 327 if (!in_array($tmp[0], $delimiters)) { |
303 throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); | 328 throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
304 } | 329 } |
305 } | 330 } |
306 } else { | 331 } else { |
307 // "normal" string | 332 // "normal" string |
308 if (!$delimiters) { | 333 if (!$delimiters) { |
311 | 336 |
312 // remove comments | 337 // remove comments |
313 if (Parser::preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { | 338 if (Parser::preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { |
314 $output = substr($output, 0, $match[0][1]); | 339 $output = substr($output, 0, $match[0][1]); |
315 } | 340 } |
316 } elseif (Parser::preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { | 341 } elseif (Parser::preg_match('/^(.'.($legacyOmittedKeySupport ? '+' : '*').'?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { |
317 $output = $match[1]; | 342 $output = $match[1]; |
318 $i += strlen($output); | 343 $i += strlen($output); |
319 } else { | 344 } else { |
320 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar)); | 345 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename); |
321 } | 346 } |
322 | 347 |
323 // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) | 348 // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) |
324 if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) { | 349 if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) { |
325 throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0])); | 350 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); |
326 } | 351 } |
327 | 352 |
328 if ($output && '%' === $output[0]) { | 353 if ($output && '%' === $output[0]) { |
329 @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output), E_USER_DEPRECATED); | 354 @trigger_error(self::getDeprecationMessage(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output)), E_USER_DEPRECATED); |
330 } | 355 } |
331 | 356 |
332 if ($evaluate) { | 357 if ($evaluate) { |
333 $output = self::evaluateScalar($output, $flags, $references); | 358 $output = self::evaluateScalar($output, $flags, $references); |
334 } | 359 } |
348 * @throws ParseException When malformed inline YAML string is parsed | 373 * @throws ParseException When malformed inline YAML string is parsed |
349 */ | 374 */ |
350 private static function parseQuotedScalar($scalar, &$i) | 375 private static function parseQuotedScalar($scalar, &$i) |
351 { | 376 { |
352 if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { | 377 if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { |
353 throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i))); | 378 throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
354 } | 379 } |
355 | 380 |
356 $output = substr($match[0], 1, strlen($match[0]) - 2); | 381 $output = substr($match[0], 1, strlen($match[0]) - 2); |
357 | 382 |
358 $unescaper = new Unescaper(); | 383 $unescaper = new Unescaper(); |
385 $len = strlen($sequence); | 410 $len = strlen($sequence); |
386 ++$i; | 411 ++$i; |
387 | 412 |
388 // [foo, bar, ...] | 413 // [foo, bar, ...] |
389 while ($i < $len) { | 414 while ($i < $len) { |
415 if (']' === $sequence[$i]) { | |
416 return $output; | |
417 } | |
418 if (',' === $sequence[$i] || ' ' === $sequence[$i]) { | |
419 ++$i; | |
420 | |
421 continue; | |
422 } | |
423 | |
424 $tag = self::parseTag($sequence, $i, $flags); | |
390 switch ($sequence[$i]) { | 425 switch ($sequence[$i]) { |
391 case '[': | 426 case '[': |
392 // nested sequence | 427 // nested sequence |
393 $output[] = self::parseSequence($sequence, $flags, $i, $references); | 428 $value = self::parseSequence($sequence, $flags, $i, $references); |
394 break; | 429 break; |
395 case '{': | 430 case '{': |
396 // nested mapping | 431 // nested mapping |
397 $output[] = self::parseMapping($sequence, $flags, $i, $references); | 432 $value = self::parseMapping($sequence, $flags, $i, $references); |
398 break; | |
399 case ']': | |
400 return $output; | |
401 case ',': | |
402 case ' ': | |
403 break; | 433 break; |
404 default: | 434 default: |
405 $isQuoted = in_array($sequence[$i], array('"', "'")); | 435 $isQuoted = in_array($sequence[$i], array('"', "'")); |
406 $value = self::parseScalar($sequence, $flags, array(',', ']'), array('"', "'"), $i, true, $references); | 436 $value = self::parseScalar($sequence, $flags, array(',', ']'), $i, null === $tag, $references); |
407 | 437 |
408 // the value can be an array if a reference has been resolved to an array var | 438 // the value can be an array if a reference has been resolved to an array var |
409 if (is_string($value) && !$isQuoted && false !== strpos($value, ': ')) { | 439 if (is_string($value) && !$isQuoted && false !== strpos($value, ': ')) { |
410 // embedded mapping? | 440 // embedded mapping? |
411 try { | 441 try { |
414 } catch (\InvalidArgumentException $e) { | 444 } catch (\InvalidArgumentException $e) { |
415 // no, it's not | 445 // no, it's not |
416 } | 446 } |
417 } | 447 } |
418 | 448 |
419 $output[] = $value; | |
420 | |
421 --$i; | 449 --$i; |
422 } | 450 } |
423 | 451 |
452 if (null !== $tag) { | |
453 $value = new TaggedValue($tag, $value); | |
454 } | |
455 | |
456 $output[] = $value; | |
457 | |
424 ++$i; | 458 ++$i; |
425 } | 459 } |
426 | 460 |
427 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence)); | 461 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename); |
428 } | 462 } |
429 | 463 |
430 /** | 464 /** |
431 * Parses a YAML mapping. | 465 * Parses a YAML mapping. |
432 * | 466 * |
442 private static function parseMapping($mapping, $flags, &$i = 0, $references = array()) | 476 private static function parseMapping($mapping, $flags, &$i = 0, $references = array()) |
443 { | 477 { |
444 $output = array(); | 478 $output = array(); |
445 $len = strlen($mapping); | 479 $len = strlen($mapping); |
446 ++$i; | 480 ++$i; |
481 $allowOverwrite = false; | |
447 | 482 |
448 // {foo: bar, bar:foo, ...} | 483 // {foo: bar, bar:foo, ...} |
449 while ($i < $len) { | 484 while ($i < $len) { |
450 switch ($mapping[$i]) { | 485 switch ($mapping[$i]) { |
451 case ' ': | 486 case ' ': |
460 return $output; | 495 return $output; |
461 } | 496 } |
462 | 497 |
463 // key | 498 // key |
464 $isKeyQuoted = in_array($mapping[$i], array('"', "'"), true); | 499 $isKeyQuoted = in_array($mapping[$i], array('"', "'"), true); |
465 $key = self::parseScalar($mapping, $flags, array(':', ' '), array('"', "'"), $i, false); | 500 $key = self::parseScalar($mapping, $flags, array(':', ' '), $i, false, array(), true); |
466 | 501 |
467 if (':' !== $key && false === $i = strpos($mapping, ':', $i)) { | 502 if (':' !== $key && false === $i = strpos($mapping, ':', $i)) { |
468 break; | 503 break; |
469 } | 504 } |
470 | 505 |
506 if (':' === $key) { | |
507 @trigger_error(self::getDeprecationMessage('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); | |
508 } | |
509 | |
510 if (!$isKeyQuoted) { | |
511 $evaluatedKey = self::evaluateScalar($key, $flags, $references); | |
512 | |
513 if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { | |
514 @trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), E_USER_DEPRECATED); | |
515 } | |
516 } | |
517 | |
471 if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { | 518 if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { |
472 @trigger_error('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.', E_USER_DEPRECATED); | 519 @trigger_error(self::getDeprecationMessage('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since Symfony 3.2 and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); |
473 } | 520 } |
474 | 521 |
475 // value | 522 if ('<<' === $key) { |
476 $done = false; | 523 $allowOverwrite = true; |
524 } | |
477 | 525 |
478 while ($i < $len) { | 526 while ($i < $len) { |
527 if (':' === $mapping[$i] || ' ' === $mapping[$i]) { | |
528 ++$i; | |
529 | |
530 continue; | |
531 } | |
532 | |
533 $tag = self::parseTag($mapping, $i, $flags); | |
479 switch ($mapping[$i]) { | 534 switch ($mapping[$i]) { |
480 case '[': | 535 case '[': |
481 // nested sequence | 536 // nested sequence |
482 $value = self::parseSequence($mapping, $flags, $i, $references); | 537 $value = self::parseSequence($mapping, $flags, $i, $references); |
483 // Spec: Keys MUST be unique; first one wins. | 538 // Spec: Keys MUST be unique; first one wins. |
484 // Parser cannot abort this mapping earlier, since lines | 539 // Parser cannot abort this mapping earlier, since lines |
485 // are processed sequentially. | 540 // are processed sequentially. |
486 if (!isset($output[$key])) { | 541 // But overwriting is allowed when a merge node is used in current block. |
487 $output[$key] = $value; | 542 if ('<<' === $key) { |
488 } else { | 543 foreach ($value as $parsedValue) { |
489 @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); | 544 $output += $parsedValue; |
490 } | 545 } |
491 $done = true; | 546 } elseif ($allowOverwrite || !isset($output[$key])) { |
547 if (null !== $tag) { | |
548 $output[$key] = new TaggedValue($tag, $value); | |
549 } else { | |
550 $output[$key] = $value; | |
551 } | |
552 } elseif (isset($output[$key])) { | |
553 @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); | |
554 } | |
492 break; | 555 break; |
493 case '{': | 556 case '{': |
494 // nested mapping | 557 // nested mapping |
495 $value = self::parseMapping($mapping, $flags, $i, $references); | 558 $value = self::parseMapping($mapping, $flags, $i, $references); |
496 // Spec: Keys MUST be unique; first one wins. | 559 // Spec: Keys MUST be unique; first one wins. |
497 // Parser cannot abort this mapping earlier, since lines | 560 // Parser cannot abort this mapping earlier, since lines |
498 // are processed sequentially. | 561 // are processed sequentially. |
499 if (!isset($output[$key])) { | 562 // But overwriting is allowed when a merge node is used in current block. |
500 $output[$key] = $value; | 563 if ('<<' === $key) { |
501 } else { | 564 $output += $value; |
502 @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); | 565 } elseif ($allowOverwrite || !isset($output[$key])) { |
503 } | 566 if (null !== $tag) { |
504 $done = true; | 567 $output[$key] = new TaggedValue($tag, $value); |
505 break; | 568 } else { |
506 case ':': | 569 $output[$key] = $value; |
507 case ' ': | 570 } |
571 } elseif (isset($output[$key])) { | |
572 @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); | |
573 } | |
508 break; | 574 break; |
509 default: | 575 default: |
510 $value = self::parseScalar($mapping, $flags, array(',', '}'), array('"', "'"), $i, true, $references); | 576 $value = self::parseScalar($mapping, $flags, array(',', '}'), $i, null === $tag, $references); |
511 // Spec: Keys MUST be unique; first one wins. | 577 // Spec: Keys MUST be unique; first one wins. |
512 // Parser cannot abort this mapping earlier, since lines | 578 // Parser cannot abort this mapping earlier, since lines |
513 // are processed sequentially. | 579 // are processed sequentially. |
514 if (!isset($output[$key])) { | 580 // But overwriting is allowed when a merge node is used in current block. |
515 $output[$key] = $value; | 581 if ('<<' === $key) { |
516 } else { | 582 $output += $value; |
517 @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); | 583 } elseif ($allowOverwrite || !isset($output[$key])) { |
518 } | 584 if (null !== $tag) { |
519 $done = true; | 585 $output[$key] = new TaggedValue($tag, $value); |
586 } else { | |
587 $output[$key] = $value; | |
588 } | |
589 } elseif (isset($output[$key])) { | |
590 @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); | |
591 } | |
520 --$i; | 592 --$i; |
521 } | 593 } |
522 | |
523 ++$i; | 594 ++$i; |
524 | 595 |
525 if ($done) { | 596 continue 2; |
526 continue 2; | 597 } |
527 } | 598 } |
528 } | 599 |
529 } | 600 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename); |
530 | |
531 throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping)); | |
532 } | 601 } |
533 | 602 |
534 /** | 603 /** |
535 * Evaluates scalars and replaces magic values. | 604 * Evaluates scalars and replaces magic values. |
536 * | 605 * |
554 $value = substr($scalar, 1); | 623 $value = substr($scalar, 1); |
555 } | 624 } |
556 | 625 |
557 // an unquoted * | 626 // an unquoted * |
558 if (false === $value || '' === $value) { | 627 if (false === $value || '' === $value) { |
559 throw new ParseException('A reference must contain at least one character.'); | 628 throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename); |
560 } | 629 } |
561 | 630 |
562 if (!array_key_exists($value, $references)) { | 631 if (!array_key_exists($value, $references)) { |
563 throw new ParseException(sprintf('Reference "%s" does not exist.', $value)); | 632 throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename); |
564 } | 633 } |
565 | 634 |
566 return $references[$value]; | 635 return $references[$value]; |
567 } | 636 } |
568 | 637 |
573 return; | 642 return; |
574 case 'true' === $scalarLower: | 643 case 'true' === $scalarLower: |
575 return true; | 644 return true; |
576 case 'false' === $scalarLower: | 645 case 'false' === $scalarLower: |
577 return false; | 646 return false; |
578 // Optimise for returning strings. | 647 case '!' === $scalar[0]: |
579 case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): | |
580 switch (true) { | 648 switch (true) { |
581 case 0 === strpos($scalar, '!str'): | 649 case 0 === strpos($scalar, '!str'): |
650 @trigger_error(self::getDeprecationMessage('Support for the !str tag is deprecated since Symfony 3.4. Use the !!str tag instead.'), E_USER_DEPRECATED); | |
651 | |
582 return (string) substr($scalar, 5); | 652 return (string) substr($scalar, 5); |
653 case 0 === strpos($scalar, '!!str '): | |
654 return (string) substr($scalar, 6); | |
583 case 0 === strpos($scalar, '! '): | 655 case 0 === strpos($scalar, '! '): |
656 @trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), E_USER_DEPRECATED); | |
657 | |
584 return (int) self::parseScalar(substr($scalar, 2), $flags); | 658 return (int) self::parseScalar(substr($scalar, 2), $flags); |
585 case 0 === strpos($scalar, '!php/object:'): | 659 case 0 === strpos($scalar, '!php/object:'): |
586 if (self::$objectSupport) { | 660 if (self::$objectSupport) { |
661 @trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); | |
662 | |
587 return unserialize(substr($scalar, 12)); | 663 return unserialize(substr($scalar, 12)); |
588 } | 664 } |
589 | 665 |
590 if (self::$exceptionOnInvalidType) { | 666 if (self::$exceptionOnInvalidType) { |
591 throw new ParseException('Object support when parsing a YAML file has been disabled.'); | 667 throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
592 } | 668 } |
593 | 669 |
594 return; | 670 return; |
595 case 0 === strpos($scalar, '!!php/object:'): | 671 case 0 === strpos($scalar, '!!php/object:'): |
596 if (self::$objectSupport) { | 672 if (self::$objectSupport) { |
597 @trigger_error('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead.', E_USER_DEPRECATED); | 673 @trigger_error(self::getDeprecationMessage('The !!php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); |
598 | 674 |
599 return unserialize(substr($scalar, 13)); | 675 return unserialize(substr($scalar, 13)); |
600 } | 676 } |
601 | 677 |
602 if (self::$exceptionOnInvalidType) { | 678 if (self::$exceptionOnInvalidType) { |
603 throw new ParseException('Object support when parsing a YAML file has been disabled.'); | 679 throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
680 } | |
681 | |
682 return; | |
683 case 0 === strpos($scalar, '!php/object'): | |
684 if (self::$objectSupport) { | |
685 return unserialize(self::parseScalar(substr($scalar, 12))); | |
686 } | |
687 | |
688 if (self::$exceptionOnInvalidType) { | |
689 throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); | |
604 } | 690 } |
605 | 691 |
606 return; | 692 return; |
607 case 0 === strpos($scalar, '!php/const:'): | 693 case 0 === strpos($scalar, '!php/const:'): |
608 if (self::$constantSupport) { | 694 if (self::$constantSupport) { |
695 @trigger_error(self::getDeprecationMessage('The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.'), E_USER_DEPRECATED); | |
696 | |
609 if (defined($const = substr($scalar, 11))) { | 697 if (defined($const = substr($scalar, 11))) { |
610 return constant($const); | 698 return constant($const); |
611 } | 699 } |
612 | 700 |
613 throw new ParseException(sprintf('The constant "%s" is not defined.', $const)); | 701 throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
614 } | 702 } |
615 if (self::$exceptionOnInvalidType) { | 703 if (self::$exceptionOnInvalidType) { |
616 throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); | 704 throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
705 } | |
706 | |
707 return; | |
708 case 0 === strpos($scalar, '!php/const'): | |
709 if (self::$constantSupport) { | |
710 $i = 0; | |
711 if (defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) { | |
712 return constant($const); | |
713 } | |
714 | |
715 throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); | |
716 } | |
717 if (self::$exceptionOnInvalidType) { | |
718 throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); | |
617 } | 719 } |
618 | 720 |
619 return; | 721 return; |
620 case 0 === strpos($scalar, '!!float '): | 722 case 0 === strpos($scalar, '!!float '): |
621 return (float) substr($scalar, 8); | 723 return (float) substr($scalar, 8); |
724 case 0 === strpos($scalar, '!!binary '): | |
725 return self::evaluateBinaryScalar(substr($scalar, 9)); | |
726 default: | |
727 @trigger_error(self::getDeprecationMessage(sprintf('Using the unquoted scalar value "%s" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar)), E_USER_DEPRECATED); | |
728 } | |
729 | |
730 // Optimize for returning strings. | |
731 // no break | |
732 case '+' === $scalar[0] || '-' === $scalar[0] || '.' === $scalar[0] || is_numeric($scalar[0]): | |
733 switch (true) { | |
622 case Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar): | 734 case Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar): |
623 $scalar = str_replace('_', '', (string) $scalar); | 735 $scalar = str_replace('_', '', (string) $scalar); |
624 // omitting the break / return as integers are handled in the next case | 736 // omitting the break / return as integers are handled in the next case |
737 // no break | |
625 case ctype_digit($scalar): | 738 case ctype_digit($scalar): |
626 $raw = $scalar; | 739 $raw = $scalar; |
627 $cast = (int) $scalar; | 740 $cast = (int) $scalar; |
628 | 741 |
629 return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); | 742 return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); |
640 case '.inf' === $scalarLower: | 753 case '.inf' === $scalarLower: |
641 case '.nan' === $scalarLower: | 754 case '.nan' === $scalarLower: |
642 return -log(0); | 755 return -log(0); |
643 case '-.inf' === $scalarLower: | 756 case '-.inf' === $scalarLower: |
644 return log(0); | 757 return log(0); |
645 case 0 === strpos($scalar, '!!binary '): | |
646 return self::evaluateBinaryScalar(substr($scalar, 9)); | |
647 case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): | 758 case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): |
648 case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): | 759 case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): |
649 if (false !== strpos($scalar, ',')) { | 760 if (false !== strpos($scalar, ',')) { |
650 @trigger_error('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); | 761 @trigger_error(self::getDeprecationMessage('Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0.'), E_USER_DEPRECATED); |
651 } | 762 } |
652 | 763 |
653 return (float) str_replace(array(',', '_'), '', $scalar); | 764 return (float) str_replace(array(',', '_'), '', $scalar); |
654 case Parser::preg_match(self::getTimestampRegex(), $scalar): | 765 case Parser::preg_match(self::getTimestampRegex(), $scalar): |
655 if (Yaml::PARSE_DATETIME & $flags) { | 766 if (Yaml::PARSE_DATETIME & $flags) { |
662 $time = strtotime($scalar); | 773 $time = strtotime($scalar); |
663 date_default_timezone_set($timeZone); | 774 date_default_timezone_set($timeZone); |
664 | 775 |
665 return $time; | 776 return $time; |
666 } | 777 } |
667 default: | 778 } |
668 return (string) $scalar; | 779 |
669 } | 780 return (string) $scalar; |
781 } | |
782 | |
783 /** | |
784 * @param string $value | |
785 * @param int &$i | |
786 * @param int $flags | |
787 * | |
788 * @return null|string | |
789 */ | |
790 private static function parseTag($value, &$i, $flags) | |
791 { | |
792 if ('!' !== $value[$i]) { | |
793 return; | |
794 } | |
795 | |
796 $tagLength = strcspn($value, " \t\n", $i + 1); | |
797 $tag = substr($value, $i + 1, $tagLength); | |
798 | |
799 $nextOffset = $i + $tagLength + 1; | |
800 $nextOffset += strspn($value, ' ', $nextOffset); | |
801 | |
802 // Is followed by a scalar | |
803 if ((!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && 'tagged' !== $tag) { | |
804 // Manage non-whitelisted scalars in {@link self::evaluateScalar()} | |
805 return; | |
806 } | |
807 | |
808 // Built-in tags | |
809 if ($tag && '!' === $tag[0]) { | |
810 throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename); | |
811 } | |
812 | |
813 if (Yaml::PARSE_CUSTOM_TAGS & $flags) { | |
814 $i = $nextOffset; | |
815 | |
816 return $tag; | |
817 } | |
818 | |
819 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); | |
670 } | 820 } |
671 | 821 |
672 /** | 822 /** |
673 * @param string $scalar | 823 * @param string $scalar |
674 * | 824 * |
679 public static function evaluateBinaryScalar($scalar) | 829 public static function evaluateBinaryScalar($scalar) |
680 { | 830 { |
681 $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar)); | 831 $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar)); |
682 | 832 |
683 if (0 !== (strlen($parsedBinaryData) % 4)) { | 833 if (0 !== (strlen($parsedBinaryData) % 4)) { |
684 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))); | 834 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); |
685 } | 835 } |
686 | 836 |
687 if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) { | 837 if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) { |
688 throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData)); | 838 throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); |
689 } | 839 } |
690 | 840 |
691 return base64_decode($parsedBinaryData, true); | 841 return base64_decode($parsedBinaryData, true); |
692 } | 842 } |
693 | 843 |
728 */ | 878 */ |
729 private static function getHexRegex() | 879 private static function getHexRegex() |
730 { | 880 { |
731 return '~^0x[0-9a-f_]++$~i'; | 881 return '~^0x[0-9a-f_]++$~i'; |
732 } | 882 } |
883 | |
884 private static function getDeprecationMessage($message) | |
885 { | |
886 $message = rtrim($message, '.'); | |
887 | |
888 if (null !== self::$parsedFilename) { | |
889 $message .= ' in '.self::$parsedFilename; | |
890 } | |
891 | |
892 if (-1 !== self::$parsedLineNumber) { | |
893 $message .= ' on line '.(self::$parsedLineNumber + 1); | |
894 } | |
895 | |
896 return $message.'.'; | |
897 } | |
733 } | 898 } |