6645dd793a1bcca2be549a7676a296b8e5b91340
4 * This file is part of the symfony package.
5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 if (!defined('_ECRIRE_INC_VERSION')) return;
14 * sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
18 * @author Fabien Potencier <fabien.potencier@symfony-project.com>
19 * @version SVN: $Id: sfYamlInline.class.php 16177 2009-03-11 08:32:48Z fabien $
24 * Convert a YAML string to a PHP array.
26 * @param string $value A YAML string
28 * @return array A PHP array representing the YAML string
30 static public function load($value)
32 $value = trim($value);
34 if (0 == strlen($value))
42 return self
::parseSequence($value);
44 return self
::parseMapping($value);
46 return self
::parseScalar($value);
51 * Dumps a given PHP variable to a YAML string.
53 * @param mixed $value The PHP variable to convert
55 * @return string The YAML string representing the PHP array
57 static public function dump($value)
59 $trueValues = '1.1' == sfYaml
::getSpecVersion() ?
array('true', 'on', '+', 'yes', 'y') : array('true');
60 $falseValues = '1.1' == sfYaml
::getSpecVersion() ?
array('false', 'off', '-', 'no', 'n') : array('false');
64 case is_resource($value):
65 throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
66 case is_object($value):
67 return '!!php/object:'.serialize($value);
68 case is_array($value):
69 return self
::dumpArray($value);
74 case false === $value:
76 case ctype_digit($value):
77 return is_string($value) ?
"'$value'" : (int) $value;
78 case is_numeric($value):
79 return is_infinite($value) ?
str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ?
"'$value'" : $value);
80 case false !== strpos($value, "\n"):
81 return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
82 case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \#] | \A[ - ? | < > = ! % @ ]/x', $value):
83 return sprintf("'%s'", str_replace('\'', '\'\'', $value));
86 case preg_match(self
::getTimestampRegex(), $value):
88 case in_array(strtolower($value), $trueValues):
90 case in_array(strtolower($value), $falseValues):
92 case in_array(strtolower($value), array('null', '~')):
100 * Dumps a PHP array to a YAML string.
102 * @param array $value The PHP array to dump
104 * @return string The YAML string representing the PHP array
106 static protected function dumpArray($value)
109 $keys = array_keys($value);
111 (1 == count($keys) && '0' == $keys[0])
113 (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
116 foreach ($value as $val)
118 $output[] = self
::dump($val);
121 return sprintf('[%s]', implode(', ', $output));
126 foreach ($value as $key => $val)
128 $output[] = sprintf('%s: %s', self
::dump($key), self
::dump($val));
131 return sprintf('{ %s }', implode(', ', $output));
135 * Parses a scalar to a YAML string.
137 * @param scalar $scalar
138 * @param string $delimiters
139 * @param array $stringDelimiter
141 * @param boolean $evaluate
143 * @return string A YAML string
145 static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
147 if (in_array($scalar[$i], $stringDelimiters))
150 $output = self
::parseQuotedScalar($scalar, $i);
152 // skip next delimiter
160 $output = substr($scalar, $i);
161 $i +
= strlen($output);
164 if (false !== $strpos = strpos($output, ' #'))
166 $output = rtrim(substr($output, 0, $strpos));
169 else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
172 $i +
= strlen($output);
176 throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
179 $output = $evaluate ? self
::evaluateScalar($output) : $output;
186 * Parses a quoted scalar to YAML.
188 * @param string $scalar
191 * @return string A YAML string
193 static protected function parseQuotedScalar($scalar, &$i)
195 $delimiter = $scalar[$i];
198 $len = strlen($scalar);
199 $escaped = '"' == $delimiter ?
'\\"' : "''";
203 if (isset($scalar[$i +
1]) && $escaped == $scalar[$i].$scalar[$i +
1])
205 $buffer .= $delimiter;
208 else if ($delimiter == $scalar[$i])
214 $buffer .= $scalar[$i];
220 if ('"' == $delimiter)
222 // evaluate the string
223 $buffer = str_replace(array('\\n', '\\r'), array("\n", "\r"), $buffer);
224 if (strpos($buffer,'\\x')!==false){
225 $buffer = preg_replace_callback(',\\\\x([0-9a-f]+),', create_function('$m', 'return chr(hexdec($m[1]));'), $buffer);
233 * Parses a sequence to a YAML string.
235 * @param string $sequence
238 * @return string A YAML string
240 static protected function parseSequence($sequence, &$i = 0)
243 $len = strlen($sequence);
249 switch ($sequence[$i])
253 $output[] = self
::parseSequence($sequence, $i);
257 $output[] = self
::parseMapping($sequence, $i);
265 $isQuoted = in_array($sequence[$i], array('"', "'"));
266 $value = self
::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
268 if (!$isQuoted && false !== strpos($value, ': '))
273 $value = self
::parseMapping('{'.$value.'}');
275 catch (InvalidArgumentException
$e)
289 throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
293 * Parses a mapping to a YAML string.
295 * @param string $mapping
298 * @return string A YAML string
300 static protected function parseMapping($mapping, &$i = 0)
303 $len = strlen($mapping);
306 // {foo: bar, bar:foo, ...}
309 switch ($mapping[$i])
320 $key = self
::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
326 switch ($mapping[$i])
330 $output[$key] = self
::parseSequence($mapping, $i);
335 $output[$key] = self
::parseMapping($mapping, $i);
342 $output[$key] = self
::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
356 throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
360 * Evaluates scalars and replaces magic values.
362 * @param string $scalar
364 * @return string A YAML string
366 static protected function evaluateScalar($scalar)
368 $scalar = trim($scalar);
370 $trueValues = '1.1' == sfYaml
::getSpecVersion() ?
array('true', 'on', '+', 'yes', 'y') : array('true');
371 $falseValues = '1.1' == sfYaml
::getSpecVersion() ?
array('false', 'off', '-', 'no', 'n') : array('false');
375 case 'null' == strtolower($scalar):
379 case 0 === strpos($scalar, '!str'):
380 return (string) substr($scalar, 5);
381 case 0 === strpos($scalar, '! '):
382 return intval(self
::parseScalar(substr($scalar, 2)));
383 case 0 === strpos($scalar, '!!php/object:'):
384 return unserialize(substr($scalar, 13));
385 case ctype_digit($scalar):
387 $cast = intval($scalar);
388 return '0' == $scalar[0] ?
octdec($scalar) : (((string) $raw == (string) $cast) ?
$cast : $raw);
389 case in_array(strtolower($scalar), $trueValues):
391 case in_array(strtolower($scalar), $falseValues):
393 case is_numeric($scalar):
394 return '0x' == $scalar[0].$scalar[1] ?
hexdec($scalar) : floatval($scalar);
395 case 0 == strcasecmp($scalar, '.inf'):
396 case 0 == strcasecmp($scalar, '.NaN'):
398 case 0 == strcasecmp($scalar, '-.inf'):
400 case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
401 return floatval(str_replace(',', '', $scalar));
402 case preg_match(self
::getTimestampRegex(), $scalar):
403 return strtotime($scalar);
405 return (string) $scalar;
409 static protected function getTimestampRegex()
413 (?P<year>[0-9][0-9][0-9][0-9])
414 -(?P<month>[0-9][0-9]?)
415 -(?P<day>[0-9][0-9]?)
417 (?P<hour>[0-9][0-9]?)
418 :(?P<minute>[0-9][0-9])
419 :(?P<second>[0-9][0-9])
420 (?:\.(?P<fraction>[0-9]*))?
421 (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
422 (?::(?P<tz_minute>[0-9][0-9]))?))?)?