[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
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\Yaml; 13 14 use Symfony\Component\Yaml\Exception\ParseException; 15 use Symfony\Component\Yaml\Exception\DumpException; 16 17 /** 18 * Inline implements a YAML parser/dumper for the YAML inline syntax. 19 * 20 * @author Fabien Potencier <fabien@symfony.com> 21 */ 22 class Inline 23 { 24 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; 25 26 private static $exceptionOnInvalidType = false; 27 private static $objectSupport = false; 28 29 /** 30 * Converts a YAML string to a PHP array. 31 * 32 * @param string $value A YAML string 33 * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise 34 * @param bool $objectSupport true if object support is enabled, false otherwise 35 * @param array $references Mapping of variable names to values 36 * 37 * @return array A PHP array representing the YAML string 38 * 39 * @throws ParseException 40 */ 41 public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $references = array()) 42 { 43 self::$exceptionOnInvalidType = $exceptionOnInvalidType; 44 self::$objectSupport = $objectSupport; 45 46 $value = trim($value); 47 48 if ('' === $value) { 49 return ''; 50 } 51 52 if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { 53 $mbEncoding = mb_internal_encoding(); 54 mb_internal_encoding('ASCII'); 55 } 56 57 $i = 0; 58 switch ($value[0]) { 59 case '[': 60 $result = self::parseSequence($value, $i, $references); 61 ++$i; 62 break; 63 case '{': 64 $result = self::parseMapping($value, $i, $references); 65 ++$i; 66 break; 67 default: 68 $result = self::parseScalar($value, null, array('"', "'"), $i, true, $references); 69 } 70 71 // some comments are allowed at the end 72 if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { 73 throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); 74 } 75 76 if (isset($mbEncoding)) { 77 mb_internal_encoding($mbEncoding); 78 } 79 80 return $result; 81 } 82 83 /** 84 * Dumps a given PHP variable to a YAML string. 85 * 86 * @param mixed $value The PHP variable to convert 87 * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise 88 * @param bool $objectSupport true if object support is enabled, false otherwise 89 * 90 * @return string The YAML string representing the PHP array 91 * 92 * @throws DumpException When trying to dump PHP resource 93 */ 94 public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false) 95 { 96 switch (true) { 97 case is_resource($value): 98 if ($exceptionOnInvalidType) { 99 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value))); 100 } 101 102 return 'null'; 103 case is_object($value): 104 if ($objectSupport) { 105 return '!php/object:'.serialize($value); 106 } 107 108 if ($exceptionOnInvalidType) { 109 throw new DumpException('Object support when dumping a YAML file has been disabled.'); 110 } 111 112 return 'null'; 113 case is_array($value): 114 return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport); 115 case null === $value: 116 return 'null'; 117 case true === $value: 118 return 'true'; 119 case false === $value: 120 return 'false'; 121 case ctype_digit($value): 122 return is_string($value) ? "'$value'" : (int) $value; 123 case is_numeric($value): 124 $locale = setlocale(LC_NUMERIC, 0); 125 if (false !== $locale) { 126 setlocale(LC_NUMERIC, 'C'); 127 } 128 $repr = is_string($value) ? "'$value'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', (string) $value) : (string) $value); 129 130 if (false !== $locale) { 131 setlocale(LC_NUMERIC, $locale); 132 } 133 134 return $repr; 135 case '' == $value: 136 return "''"; 137 case Escaper::requiresDoubleQuoting($value): 138 return Escaper::escapeWithDoubleQuotes($value); 139 case Escaper::requiresSingleQuoting($value): 140 case preg_match(self::getHexRegex(), $value): 141 case preg_match(self::getTimestampRegex(), $value): 142 return Escaper::escapeWithSingleQuotes($value); 143 default: 144 return $value; 145 } 146 } 147 148 /** 149 * Check if given array is hash or just normal indexed array. 150 * 151 * @internal 152 * 153 * @param array $value The PHP array to check 154 * 155 * @return bool true if value is hash array, false otherwise 156 */ 157 public static function isHash(array $value) 158 { 159 $expectedKey = 0; 160 161 foreach ($value as $key => $val) { 162 if ($key !== $expectedKey++) { 163 return true; 164 } 165 } 166 167 return false; 168 } 169 170 /** 171 * Dumps a PHP array to a YAML string. 172 * 173 * @param array $value The PHP array to dump 174 * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise 175 * @param bool $objectSupport true if object support is enabled, false otherwise 176 * 177 * @return string The YAML string representing the PHP array 178 */ 179 private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport) 180 { 181 // array 182 if ($value && !self::isHash($value)) { 183 $output = array(); 184 foreach ($value as $val) { 185 $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport); 186 } 187 188 return sprintf('[%s]', implode(', ', $output)); 189 } 190 191 // hash 192 $output = array(); 193 foreach ($value as $key => $val) { 194 $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport)); 195 } 196 197 return sprintf('{ %s }', implode(', ', $output)); 198 } 199 200 /** 201 * Parses a scalar to a YAML string. 202 * 203 * @param string $scalar 204 * @param string $delimiters 205 * @param array $stringDelimiters 206 * @param int &$i 207 * @param bool $evaluate 208 * @param array $references 209 * 210 * @return string A YAML string 211 * 212 * @throws ParseException When malformed inline YAML string is parsed 213 */ 214 public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true, $references = array()) 215 { 216 if (in_array($scalar[$i], $stringDelimiters)) { 217 // quoted scalar 218 $output = self::parseQuotedScalar($scalar, $i); 219 220 if (null !== $delimiters) { 221 $tmp = ltrim(substr($scalar, $i), ' '); 222 if (!in_array($tmp[0], $delimiters)) { 223 throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); 224 } 225 } 226 } else { 227 // "normal" string 228 if (!$delimiters) { 229 $output = substr($scalar, $i); 230 $i += strlen($output); 231 232 // remove comments 233 if (preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { 234 $output = substr($output, 0, $match[0][1]); 235 } 236 } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { 237 $output = $match[1]; 238 $i += strlen($output); 239 } else { 240 throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar)); 241 } 242 243 if ($evaluate) { 244 $output = self::evaluateScalar($output, $references); 245 } 246 } 247 248 return $output; 249 } 250 251 /** 252 * Parses a quoted scalar to YAML. 253 * 254 * @param string $scalar 255 * @param int &$i 256 * 257 * @return string A YAML string 258 * 259 * @throws ParseException When malformed inline YAML string is parsed 260 */ 261 private static function parseQuotedScalar($scalar, &$i) 262 { 263 if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { 264 throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i))); 265 } 266 267 $output = substr($match[0], 1, strlen($match[0]) - 2); 268 269 $unescaper = new Unescaper(); 270 if ('"' == $scalar[$i]) { 271 $output = $unescaper->unescapeDoubleQuotedString($output); 272 } else { 273 $output = $unescaper->unescapeSingleQuotedString($output); 274 } 275 276 $i += strlen($match[0]); 277 278 return $output; 279 } 280 281 /** 282 * Parses a sequence to a YAML string. 283 * 284 * @param string $sequence 285 * @param int &$i 286 * @param array $references 287 * 288 * @return string A YAML string 289 * 290 * @throws ParseException When malformed inline YAML string is parsed 291 */ 292 private static function parseSequence($sequence, &$i = 0, $references = array()) 293 { 294 $output = array(); 295 $len = strlen($sequence); 296 ++$i; 297 298 // [foo, bar, ...] 299 while ($i < $len) { 300 switch ($sequence[$i]) { 301 case '[': 302 // nested sequence 303 $output[] = self::parseSequence($sequence, $i, $references); 304 break; 305 case '{': 306 // nested mapping 307 $output[] = self::parseMapping($sequence, $i, $references); 308 break; 309 case ']': 310 return $output; 311 case ',': 312 case ' ': 313 break; 314 default: 315 $isQuoted = in_array($sequence[$i], array('"', "'")); 316 $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i, true, $references); 317 318 // the value can be an array if a reference has been resolved to an array var 319 if (!is_array($value) && !$isQuoted && false !== strpos($value, ': ')) { 320 // embedded mapping? 321 try { 322 $pos = 0; 323 $value = self::parseMapping('{'.$value.'}', $pos, $references); 324 } catch (\InvalidArgumentException $e) { 325 // no, it's not 326 } 327 } 328 329 $output[] = $value; 330 331 --$i; 332 } 333 334 ++$i; 335 } 336 337 throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence)); 338 } 339 340 /** 341 * Parses a mapping to a YAML string. 342 * 343 * @param string $mapping 344 * @param int &$i 345 * @param array $references 346 * 347 * @return string A YAML string 348 * 349 * @throws ParseException When malformed inline YAML string is parsed 350 */ 351 private static function parseMapping($mapping, &$i = 0, $references = array()) 352 { 353 $output = array(); 354 $len = strlen($mapping); 355 ++$i; 356 357 // {foo: bar, bar:foo, ...} 358 while ($i < $len) { 359 switch ($mapping[$i]) { 360 case ' ': 361 case ',': 362 ++$i; 363 continue 2; 364 case '}': 365 return $output; 366 } 367 368 // key 369 $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); 370 371 // value 372 $done = false; 373 while ($i < $len) { 374 switch ($mapping[$i]) { 375 case '[': 376 // nested sequence 377 $output[$key] = self::parseSequence($mapping, $i, $references); 378 $done = true; 379 break; 380 case '{': 381 // nested mapping 382 $output[$key] = self::parseMapping($mapping, $i, $references); 383 $done = true; 384 break; 385 case ':': 386 case ' ': 387 break; 388 default: 389 $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i, true, $references); 390 $done = true; 391 --$i; 392 } 393 394 ++$i; 395 396 if ($done) { 397 continue 2; 398 } 399 } 400 } 401 402 throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping)); 403 } 404 405 /** 406 * Evaluates scalars and replaces magic values. 407 * 408 * @param string $scalar 409 * @param array $references 410 * 411 * @return string A YAML string 412 * 413 * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved 414 */ 415 private static function evaluateScalar($scalar, $references = array()) 416 { 417 $scalar = trim($scalar); 418 $scalarLower = strtolower($scalar); 419 420 if (0 === strpos($scalar, '*')) { 421 if (false !== $pos = strpos($scalar, '#')) { 422 $value = substr($scalar, 1, $pos - 2); 423 } else { 424 $value = substr($scalar, 1); 425 } 426 427 // an unquoted * 428 if (false === $value || '' === $value) { 429 throw new ParseException('A reference must contain at least one character.'); 430 } 431 432 if (!array_key_exists($value, $references)) { 433 throw new ParseException(sprintf('Reference "%s" does not exist.', $value)); 434 } 435 436 return $references[$value]; 437 } 438 439 switch (true) { 440 case 'null' === $scalarLower: 441 case '' === $scalar: 442 case '~' === $scalar: 443 return; 444 case 'true' === $scalarLower: 445 return true; 446 case 'false' === $scalarLower: 447 return false; 448 // Optimise for returning strings. 449 case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): 450 switch (true) { 451 case 0 === strpos($scalar, '!str'): 452 return (string) substr($scalar, 5); 453 case 0 === strpos($scalar, '! '): 454 return (int) self::parseScalar(substr($scalar, 2)); 455 case 0 === strpos($scalar, '!php/object:'): 456 if (self::$objectSupport) { 457 return unserialize(substr($scalar, 12)); 458 } 459 460 if (self::$exceptionOnInvalidType) { 461 throw new ParseException('Object support when parsing a YAML file has been disabled.'); 462 } 463 464 return; 465 case 0 === strpos($scalar, '!!php/object:'): 466 if (self::$objectSupport) { 467 return unserialize(substr($scalar, 13)); 468 } 469 470 if (self::$exceptionOnInvalidType) { 471 throw new ParseException('Object support when parsing a YAML file has been disabled.'); 472 } 473 474 return; 475 case ctype_digit($scalar): 476 $raw = $scalar; 477 $cast = (int) $scalar; 478 479 return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); 480 case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): 481 $raw = $scalar; 482 $cast = (int) $scalar; 483 484 return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw === (string) $cast) ? $cast : $raw); 485 case is_numeric($scalar): 486 case preg_match(self::getHexRegex(), $scalar): 487 return '0x' === $scalar[0].$scalar[1] ? hexdec($scalar) : (float) $scalar; 488 case '.inf' === $scalarLower: 489 case '.nan' === $scalarLower: 490 return -log(0); 491 case '-.inf' === $scalarLower: 492 return log(0); 493 case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): 494 return (float) str_replace(',', '', $scalar); 495 case preg_match(self::getTimestampRegex(), $scalar): 496 $timeZone = date_default_timezone_get(); 497 date_default_timezone_set('UTC'); 498 $time = strtotime($scalar); 499 date_default_timezone_set($timeZone); 500 501 return $time; 502 } 503 default: 504 return (string) $scalar; 505 } 506 } 507 508 /** 509 * Gets a regex that matches a YAML date. 510 * 511 * @return string The regular expression 512 * 513 * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 514 */ 515 private static function getTimestampRegex() 516 { 517 return <<<EOF 518 ~^ 519 (?P<year>[0-9][0-9][0-9][0-9]) 520 -(?P<month>[0-9][0-9]?) 521 -(?P<day>[0-9][0-9]?) 522 (?:(?:[Tt]|[ \t]+) 523 (?P<hour>[0-9][0-9]?) 524 :(?P<minute>[0-9][0-9]) 525 :(?P<second>[0-9][0-9]) 526 (?:\.(?P<fraction>[0-9]*))? 527 (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?) 528 (?::(?P<tz_minute>[0-9][0-9]))?))?)? 529 $~x 530 EOF; 531 } 532 533 /** 534 * Gets a regex that matches a YAML number in hexadecimal notation. 535 * 536 * @return string 537 */ 538 private static function getHexRegex() 539 { 540 return '~^0x[0-9a-f]++$~i'; 541 } 542 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |