[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/yaml/Symfony/Component/Yaml/ -> Inline.php (source)

   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  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1