Browse Source

PSR SPIP 4

master
Cerdic 2 weeks ago
parent
commit
6f751ae4e3
  1. 54
      demo/yaml_fonctions.php
  2. 9
      inc/libyaml.php
  3. 5
      inc/sfyaml.php
  4. 5
      inc/spyc.php
  5. 5
      inc/symfony.php
  6. 29
      inc/yaml.php
  7. 14
      phpcs.xml.dist
  8. 127
      sfyaml/sfYaml.php
  9. 59
      sfyaml/sfYamlDumper.php
  10. 614
      sfyaml/sfYamlInline.php
  11. 886
      sfyaml/sfYamlParser.php
  12. 2
      yaml_fonctions.php

54
demo/yaml_fonctions.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -12,7 +13,7 @@ function ajouter_libyaml($librairies) {
return $librairies;
}
function decoder_fichier_yaml($filename, $options = array()) {
function decoder_fichier_yaml($filename, $options = []) {
include_spip('inc/yaml');
$file = find_in_path($filename);
@ -23,21 +24,21 @@ function decoder_fichier_yaml($filename, $options = array()) {
$timestamp_fin = microtime(true);
$duree = ($timestamp_fin - $timestamp_debut) * 1000;
return array(
return [
'lib' => sinon($options['library'], 'sfyaml'),
'fichier' => $file,
'duree' => "${duree} ms",
'yaml' => $parsed);
'yaml' => $parsed];
}
function comparer_decodage($fichier, $libraries, $options = array()) {
function comparer_decodage($fichier, $libraries, $options = []) {
include_spip('inc/yaml');
$compared = array();
$first = array();
$compared = [];
$first = [];
foreach ($libraries as $_library) {
$options = array_merge($options, array('library' => $_library));
$options = array_merge($options, ['library' => $_library]);
$parsed = yaml_decode_file($fichier, $options);
if (!$compared) {
$first = $parsed;
@ -53,23 +54,24 @@ function comparer_decodage($fichier, $libraries, $options = array()) {
function array_diff_assoc_recursive($array1, $array2, $fichier) {
$difference = array();
foreach ($array1 as $_key => $_value) {
if (is_array($_value)) {
if (!isset($array2[$_key]) || !is_array($array2[$_key])) {
$difference[$_key] = $_value;
} else {
$new_diff = array_diff_assoc_recursive($_value, $array2[$_key], $fichier);
if (!empty($new_diff))
$difference[$_key] = $new_diff;
}
} elseif (!is_array($array2)) {
echo $fichier, ' - ', $_key, ' - ', $_value, '<br />';
} elseif (!array_key_exists($_key, $array2) || ($array2[$_key] !== $_value)) {
$difference[$_key] = $_value;
}
}
return $difference;
$difference = [];
foreach ($array1 as $_key => $_value) {
if (is_array($_value)) {
if (!isset($array2[$_key]) || !is_array($array2[$_key])) {
$difference[$_key] = $_value;
} else {
$new_diff = array_diff_assoc_recursive($_value, $array2[$_key], $fichier);
if (!empty($new_diff)) {
$difference[$_key] = $new_diff;
}
}
} elseif (!is_array($array2)) {
echo $fichier, ' - ', $_key, ' - ', $_value, '<br />';
} elseif (!array_key_exists($_key, $array2) || ($array2[$_key] !== $_value)) {
$difference[$_key] = $_value;
}
}
return $difference;
}

9
inc/libyaml.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -17,7 +18,7 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* @return string
* Chaîne YAML construite.
*/
function libyaml_yaml_encode($structure, $options = array()) {
function libyaml_yaml_encode($structure, $options = []) {
// Traitement des options
// -- par défaut la librairie positionne l'indentation à 2 qui est la valeur par défaut
@ -30,7 +31,7 @@ function libyaml_yaml_encode($structure, $options = array()) {
$yaml = yaml_emit($structure);
// Suppression des --- et ... de début et fin.
$yaml = preg_replace(array("#^\-\-\-.*?\n#s", "#\.\.\.\s*$#"), array('', ''), $yaml);
$yaml = preg_replace(["#^\-\-\-.*?\n#s", '#\.\.\.\s*$#'], ['', ''], $yaml);
return $yaml;
}
@ -49,7 +50,7 @@ function libyaml_yaml_encode($structure, $options = array()) {
* @return bool|mixed
* Structure PHP produite par le parsing de la chaîne YAML.
*/
function libyaml_yaml_decode($input, $options = array()) {
function libyaml_yaml_decode($input, $options = []) {
return yaml_parse($input,0);
return yaml_parse($input, 0);
}

5
inc/sfyaml.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -18,7 +19,7 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* @return string
* Chaîne YAML construite.
*/
function sfyaml_yaml_encode($structure, $options = array()) {
function sfyaml_yaml_encode($structure, $options = []) {
require_once _DIR_PLUGIN_YAML . 'sfyaml/sfYaml.php';
require_once _DIR_PLUGIN_YAML . 'sfyaml/sfYamlDumper.php';
@ -54,7 +55,7 @@ function sfyaml_yaml_encode($structure, $options = array()) {
* @return bool|mixed
* Structure PHP produite par le parsing de la chaîne YAML.
*/
function sfyaml_yaml_decode($input, $options = array()) {
function sfyaml_yaml_decode($input, $options = []) {
require_once _DIR_PLUGIN_YAML . 'sfyaml/sfYaml.php';
require_once _DIR_PLUGIN_YAML . 'sfyaml/sfYamlParser.php';

5
inc/spyc.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -19,7 +20,7 @@ require_once _DIR_PLUGIN_YAML . 'vendor/autoload.php';
* @return string
* Chaîne YAML construite.
*/
function spyc_yaml_encode($structure, $options = array()) {
function spyc_yaml_encode($structure, $options = []) {
// Traitement des options
if (empty($options['indent']) or (isset($options['indent']) and !is_int($options['indent']))) {
@ -43,7 +44,7 @@ function spyc_yaml_encode($structure, $options = array()) {
* @return bool|mixed
* Structure PHP produite par le parsing de la chaîne YAML.
*/
function spyc_yaml_decode($input, $options = array()) {
function spyc_yaml_decode($input, $options = []) {
return Spyc::YAMLLoadString($input);
}

5
inc/symfony.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -22,7 +23,7 @@ use Symfony\Component\Yaml\Exception\ParseException;
* @return string
* Chaîne YAML construite.
*/
function symfony_yaml_encode($structure, $options = array()) {
function symfony_yaml_encode($structure, $options = []) {
// Traitement des options du dump
if (empty($options['inline']) or (isset($options['inline']) and !is_int($options['inline']))) {
@ -55,7 +56,7 @@ function symfony_yaml_encode($structure, $options = array()) {
* @return bool|mixed
* Structure PHP produite par le parsing de la chaîne YAML.
*/
function symfony_yaml_decode($input = true, $options = array()) {
function symfony_yaml_decode($input = true, $options = []) {
$parsed = false;

29
inc/yaml.php

@ -1,4 +1,5 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
@ -35,7 +36,7 @@ if (!defined('_LIB_YAML')) {
* @return string
* Chaîne YAML construite, prête pour être éventuellement écrite dans un fichier.
*/
function yaml_encode($structure, $options = array()) {
function yaml_encode($structure, $options = []) {
// Déterminer la librairie à utiliser
$librairie = _LIB_YAML;
@ -63,7 +64,7 @@ if (!function_exists('yaml_decode')) {
*
* @return mixed
*/
function yaml_decode($input, $options = array()) {
function yaml_decode($input, $options = []) {
// Déterminer la librairie à utiliser
$librairie = _LIB_YAML;
@ -90,9 +91,9 @@ if (!function_exists('yaml_decode')) {
*
* @return array|mixed
*/
function yaml_decode_file($fichier, $options = array()) {
function yaml_decode_file($fichier, $options = []) {
$retour = array();
$retour = [];
// Traitement des options
if (empty($options['include'])) {
@ -121,22 +122,22 @@ function yaml_decode_file($fichier, $options = array()) {
* On passe donc par find_in_path() pour trouver le fichier
* @param array $tableau
*/
function decode_inclusions($parsed, $options = array()) {
function decode_inclusions($parsed, $options = []) {
if (is_array($parsed)) {
$retour = array();
$retour = [];
foreach ($parsed as $cle => $valeur) {
if (is_string($valeur) && substr($valeur, 0, 8) == 'inclure:' && substr($valeur, -5) == '.yaml') {
$inclusion = find_in_path(substr($valeur, 8));
if ($inclusion) {
$retour = array_merge($retour, yaml_decode_file($inclusion, $options));
} else {
$retour = array_merge($retour, array($cle => $valeur));
$retour = array_merge($retour, [$cle => $valeur]);
}
} elseif (is_array($valeur)) {
$retour = array_merge($retour, array($cle => decode_inclusions($valeur, $options)));
$retour = array_merge($retour, [$cle => decode_inclusions($valeur, $options)]);
} else {
$retour = array_merge($retour, array($cle => $valeur));
$retour = array_merge($retour, [$cle => $valeur]);
}
}
} elseif (is_string($parsed) && substr($parsed, 0, 8) == 'inclure:' && substr($parsed, -5) == '.yaml') {
@ -161,7 +162,7 @@ function decode_inclusions($parsed, $options = array()) {
* On passe donc par find_in_path() pour trouver le fichier
* @param array $tableau
*/
function yaml_charger_inclusions($tableau, $options = array()) {
function yaml_charger_inclusions($tableau, $options = []) {
// Eviter de traiter l'inclure avec la nouvelle approche
if (isset($options['include'])) {
@ -169,19 +170,19 @@ function yaml_charger_inclusions($tableau, $options = array()) {
}
if (is_array($tableau)) {
$retour = array();
$retour = [];
foreach ($tableau as $cle => $valeur) {
if (is_string($valeur) && substr($valeur, 0, 8) == 'inclure:' && substr($valeur, -5) == '.yaml') {
$inclusion = find_in_path(substr($valeur, 8));
if ($inclusion) {
$retour = array_merge($retour, yaml_charger_inclusions(yaml_decode_file($inclusion), $options));
} else {
$retour = array_merge($retour, array($cle => $valeur));
$retour = array_merge($retour, [$cle => $valeur]);
}
} elseif (is_array($valeur)) {
$retour = array_merge($retour, array($cle => yaml_charger_inclusions($valeur, $options)));
$retour = array_merge($retour, [$cle => yaml_charger_inclusions($valeur, $options)]);
} else {
$retour = array_merge($retour, array($cle => $valeur));
$retour = array_merge($retour, [$cle => $valeur]);
}
}
} elseif (is_string($tableau) && substr($tableau, 0, 8) == 'inclure:' && substr($tableau, -5) == '.yaml') {

14
phpcs.xml.dist

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<ruleset>
<file>.</file>
<exclude-pattern>vendor/*</exclude-pattern>
<exclude-pattern>lang/*</exclude-pattern>
<rule ref="SPIP40"/>
<config name="ignore_warnings_on_exit" value="1"/>
<arg name="cache" value=".php_cs.cache"/>
<arg name="report-full" value=".php_cs.txt"/>
<arg name="report-summary"/>
<arg value="s"/>
</ruleset>

127
sfyaml/sfYaml.php

@ -19,22 +19,19 @@
*/
class sfYaml
{
static protected
$spec = '1.2';
static protected $spec = '1.2';
/**
* Sets the YAML specification version to use.
*
* @param string $version The YAML specification version
*/
static public function setSpecVersion($version)
{
if (!in_array($version, array('1.1', '1.2')))
{
throw new InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version));
}
self::$spec = $version;
public static function setSpecVersion($version) {
if (!in_array($version, ['1.1', '1.2'])) {
throw new InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version));
}
self::$spec = $version;
}
/**
@ -42,9 +39,8 @@ class sfYaml
*
* @return string The YAML specification version
*/
static public function getSpecVersion()
{
return self::$spec;
public static function getSpecVersion() {
return self::$spec;
}
/**
@ -65,53 +61,50 @@ class sfYaml
*
* @throws InvalidArgumentException If the YAML is not valid
*/
public static function load($input)
{
$file = '';
// if input is a file, load it
if (strpos($input, "\n") === false && is_file($input))
{
$file = $input;
$content = $yaml = file_get_contents($input);
// if the file contains valid PHP, process it
if (strpos($content, '<'.'?') !== false
AND !(defined('_YAML_EVAL_PHP') AND !_YAML_EVAL_PHP))
{
ob_start();
$retval = eval('?'.'>'.$yaml);
$content = ob_get_clean();
// syntax error?
if ($retval === false)
$content = $yaml;
}
// if an array is returned by the config file assume it's in plain php form else in YAML
$input = is_array($retval) ? $retval : $content;
}
// if an array is returned by the config file assume it's in plain php form else in YAML
if (is_array($input))
{
return $input;
}
require_once dirname(__FILE__).'/sfYamlParser.php';
$yaml = new sfYamlParser();
try
{
$ret = $yaml->parse($input);
}
catch (Exception $e)
{
throw new InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
}
return $ret;
public static function load($input) {
$file = '';
// if input is a file, load it
if (strpos($input, "\n") === false && is_file($input)) {
$file = $input;
$content = $yaml = file_get_contents($input);
// if the file contains valid PHP, process it
if (
strpos($content, '<' . '?') !== false
and !(defined('_YAML_EVAL_PHP') and !_YAML_EVAL_PHP)
) {
ob_start();
$retval = eval('?' . '>' . $yaml);
$content = ob_get_clean();
// syntax error?
if ($retval === false) {
$content = $yaml;
}
}
// if an array is returned by the config file assume it's in plain php form else in YAML
$input = is_array($retval) ? $retval : $content;
}
// if an array is returned by the config file assume it's in plain php form else in YAML
if (is_array($input)) {
return $input;
}
require_once dirname(__FILE__) . '/sfYamlParser.php';
$yaml = new sfYamlParser();
try {
$ret = $yaml->parse($input);
}
catch (Exception $e) {
throw new InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
}
return $ret;
}
/**
@ -125,13 +118,12 @@ class sfYaml
*
* @return string A YAML string representing the original PHP array
*/
public static function dump($array, $inline = 2, $indent = 2)
{
require_once dirname(__FILE__).'/sfYamlDumper.php';
public static function dump($array, $inline = 2, $indent = 2) {
require_once dirname(__FILE__) . '/sfYamlDumper.php';
$yaml = new sfYamlDumper($indent);
$yaml = new sfYamlDumper($indent);
return $yaml->dump($array, $inline, 0);
return $yaml->dump($array, $inline, 0);
}
}
@ -140,7 +132,6 @@ class sfYaml
*
* @param string $string The string to echo with new line
*/
function echoln($string)
{
echo $string."\n";
function echoln($string) {
echo $string . "\n";
}

59
sfyaml/sfYamlDumper.php

@ -8,7 +8,7 @@
* file that was distributed with this source code.
*/
require_once(dirname(__FILE__).'/sfYamlInline.php');
require_once(dirname(__FILE__) . '/sfYamlInline.php');
/**
* sfYamlDumper dumps PHP variables to YAML strings.
@ -29,14 +29,12 @@ class sfYamlDumper
*
* @param integer $indent The amount of spaces to use for indentation of nested nodes.
*/
public function __construct($indentation = 2)
{
if ($indentation < 1) {
$this->indentation = 2;
} else {
$this->indentation = $indentation;
}
public function __construct($indentation = 2) {
if ($indentation < 1) {
$this->indentation = 2;
} else {
$this->indentation = $indentation;
}
}
/**
@ -48,32 +46,29 @@ class sfYamlDumper
*
* @return string The YAML representation of the PHP value
*/
public function dump($input, $inline = 0, $indent = 0)
{
$output = '';
$prefix = $indent ? str_repeat(' ', $indent) : '';
public function dump($input, $inline = 0, $indent = 0) {
$output = '';
$prefix = $indent ? str_repeat(' ', $indent) : '';
if ($inline <= 0 || !is_array($input) || empty($input))
{
$output .= $prefix.sfYamlInline::dump($input);
}
else
{
$isAHash = array_keys($input) !== range(0, count($input) - 1);
if ($inline <= 0 || !is_array($input) || empty($input)) {
$output .= $prefix . sfYamlInline::dump($input);
}
else {
$isAHash = array_keys($input) !== range(0, count($input) - 1);
foreach ($input as $key => $value)
{
$willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
foreach ($input as $key => $value) {
$willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
$output .= sprintf('%s%s%s%s',
$prefix,
$isAHash ? sfYamlInline::dump($key).':' : '-',
$willBeInlined ? ' ' : "\n",
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation)
).($willBeInlined ? "\n" : '');
}
}
$output .= sprintf(
'%s%s%s%s',
$prefix,
$isAHash ? sfYamlInline::dump($key) . ':' : '-',
$willBeInlined ? ' ' : "\n",
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation)
) . ($willBeInlined ? "\n" : '');
}
}
return $output;
return $output;
}
}

614
sfyaml/sfYamlInline.php

@ -8,7 +8,7 @@
* file that was distributed with this source code.
*/
require_once dirname(__FILE__).'/sfYaml.php';
require_once dirname(__FILE__) . '/sfYaml.php';
/**
* sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
@ -29,39 +29,34 @@ class sfYamlInline
*
* @return array A PHP array representing the YAML string
*/
static public function load($value)
{
$value = trim($value);
if (0 == strlen($value))
{
return '';
}
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
{
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('ASCII');
}
switch ($value[0])
{
case '[':
$result = self::parseSequence($value);
break;
case '{':
$result = self::parseMapping($value);
break;
default:
$result = self::parseScalar($value);
}
if (isset($mbEncoding))
{
mb_internal_encoding($mbEncoding);
}
return $result;
public static function load($value) {
$value = trim($value);
if (0 == strlen($value)) {
return '';
}
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('ASCII');
}
switch ($value[0]) {
case '[':
$result = self::parseSequence($value);
break;
case '{':
$result = self::parseMapping($value);
break;
default:
$result = self::parseScalar($value);
}
if (isset($mbEncoding)) {
mb_internal_encoding($mbEncoding);
}
return $result;
}
/**
@ -71,54 +66,50 @@ class sfYamlInline
*
* @return string The YAML string representing the PHP array
*/
static public function dump($value)
{
if ('1.1' === sfYaml::getSpecVersion())
{
$trueValues = array('true', 'on', '+', 'yes', 'y');
$falseValues = array('false', 'off', '-', 'no', 'n');
}
else
{
$trueValues = array('true');
$falseValues = array('false');
}
switch (true)
{
case is_resource($value):
throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
case is_object($value):
return '!!php/object:'.serialize($value);
case is_array($value):
return self::dumpArray($value);
case null === $value:
return 'null';
case true === $value:
return 'true';
case false === $value:
return 'false';
case ctype_digit($value):
return is_string($value) ? "'$value'" : (int) $value;
case is_numeric($value):
return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
case false !== strpos($value, "\n") || false !== strpos($value, "\r"):
return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value):
return sprintf("'%s'", str_replace('\'', '\'\'', $value));
case '' == $value:
return "''";
case preg_match(self::getTimestampRegex(), $value):
return "'$value'";
case in_array(strtolower($value), $trueValues):
return "'$value'";
case in_array(strtolower($value), $falseValues):
return "'$value'";
case in_array(strtolower($value), array('null', '~')):
return "'$value'";
default:
return $value;
}
public static function dump($value) {
if ('1.1' === sfYaml::getSpecVersion()) {
$trueValues = ['true', 'on', '+', 'yes', 'y'];
$falseValues = ['false', 'off', '-', 'no', 'n'];
}
else {
$trueValues = ['true'];
$falseValues = ['false'];
}
switch (true) {
case is_resource($value):
throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
case is_object($value):
return '!!php/object:' . serialize($value);
case is_array($value):
return self::dumpArray($value);
case null === $value:
return 'null';
case true === $value:
return 'true';
case false === $value:
return 'false';
case ctype_digit($value):
return is_string($value) ? "'$value'" : (int) $value;
case is_numeric($value):
return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
case false !== strpos($value, "\n") || false !== strpos($value, "\r"):
return sprintf('"%s"', str_replace(['"', "\n", "\r"], ['\\"', '\n', '\r'], $value));
case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value):
return sprintf("'%s'", str_replace('\'', '\'\'', $value));
case '' == $value:
return "''";
case preg_match(self::getTimestampRegex(), $value):
return "'$value'";
case in_array(strtolower($value), $trueValues):
return "'$value'";
case in_array(strtolower($value), $falseValues):
return "'$value'";
case in_array(strtolower($value), ['null', '~']):
return "'$value'";
default:
return $value;
}
}
/**
@ -128,32 +119,31 @@ class sfYamlInline
*
* @return string The YAML string representing the PHP array
*/
static protected function dumpArray($value)
{
// array
$keys = array_keys($value);
if (
(1 == count($keys) && '0' == $keys[0])
||
(count($keys) > 1 && array_reduce($keys, function($v,$w) { return (integer) $v + (integer) $w;}, 0) == count($keys) * (count($keys) - 1) / 2))
{
$output = array();
foreach ($value as $val)
{
$output[] = self::dump($val);
}
return sprintf('[%s]', implode(', ', $output));
}
// mapping
$output = array();
foreach ($value as $key => $val)
{
$output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
}
return sprintf('{ %s }', implode(', ', $output));
protected static function dumpArray($value) {
// array
$keys = array_keys($value);
if (
(1 == count($keys) && '0' == $keys[0])
||
(count($keys) > 1 && array_reduce($keys, function ($v, $w) {
return (int) $v + (int) $w;
}, 0) == count($keys) * (count($keys) - 1) / 2)
) {
$output = [];
foreach ($value as $val) {
$output[] = self::dump($val);
}
return sprintf('[%s]', implode(', ', $output));
}
// mapping
$output = [];
foreach ($value as $key => $val) {
$output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
}
return sprintf('{ %s }', implode(', ', $output));
}
/**
@ -167,41 +157,34 @@ class sfYamlInline
*
* @return string A YAML string
*/
static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
{
if (in_array($scalar[$i], $stringDelimiters))
{
// quoted scalar
$output = self::parseQuotedScalar($scalar, $i);
}
else
{
// "normal" string
if (!$delimiters)
{
$output = substr($scalar, $i);
$i += strlen($output);
// remove comments
if (false !== $strpos = strpos($output, ' #'))
{
$output = rtrim(substr($output, 0, $strpos));
}
}
else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
{
$output = $match[1];
$i += strlen($output);
}
else
{
throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
}
$output = $evaluate ? self::evaluateScalar($output) : $output;
}
return $output;
public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = ['"', "'"], &$i = 0, $evaluate = true) {
if (in_array($scalar[$i], $stringDelimiters)) {
// quoted scalar
$output = self::parseQuotedScalar($scalar, $i);
}
else {
// "normal" string
if (!$delimiters) {
$output = substr($scalar, $i);
$i += strlen($output);
// remove comments
if (false !== $strpos = strpos($output, ' #')) {
$output = rtrim(substr($output, 0, $strpos));
}
}
elseif (preg_match('/^(.+?)(' . implode('|', $delimiters) . ')/', substr($scalar, $i), $match)) {
$output = $match[1];
$i += strlen($output);
}
else {
throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
}
$output = $evaluate ? self::evaluateScalar($output) : $output;
}
return $output;
}
/**
@ -212,32 +195,30 @@ class sfYamlInline
*
* @return string A YAML string
*/
static protected function parseQuotedScalar($scalar, &$i)
{
if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match))
{
throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
}
$output = substr($match[0], 1, strlen($match[0]) - 2);
if ('"' == $scalar[$i])
{
// evaluate the string
$output = str_replace(array('\\"', '\\n', '\\r'), array('"', "\n", "\r"), $output);
if (strpos($output,'\\x')!==false){
$output = preg_replace_callback(',\\\\x([0-9a-f]+),', function($m) {return chr(hexdec($m[1]));}, $output);
protected static function parseQuotedScalar($scalar, &$i) {
if (!preg_match('/' . self::REGEX_QUOTED_STRING . '/Au', substr($scalar, $i), $match)) {
throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
}
$output = substr($match[0], 1, strlen($match[0]) - 2);
if ('"' == $scalar[$i]) {
// evaluate the string
$output = str_replace(['\\"', '\\n', '\\r'], ['"', "\n", "\r"], $output);
if (strpos($output, '\\x') !== false) {
$output = preg_replace_callback(',\\\\x([0-9a-f]+),', function ($m) {
return chr(hexdec($m[1]));
}, $output);
}
}
else
{
// unescape '
$output = str_replace('\'\'', '\'', $output);
}
}
else {
// unescape '
$output = str_replace('\'\'', '\'', $output);
}
$i += strlen($match[0]);
$i += strlen($match[0]);
return $output;
return $output;
}
/**
@ -248,56 +229,50 @@ class sfYamlInline
*
* @return string A YAML string
*/
static protected function parseSequence($sequence, &$i = 0)
{
$output = array();
$len = strlen($sequence);
$i += 1;
// [foo, bar, ...]
while ($i < $len)
{
switch ($sequence[$i])
{
case '[':
// nested sequence
$output[] = self::parseSequence($sequence, $i);
break;
case '{':
// nested mapping
$output[] = self::parseMapping($sequence, $i);
break;
case ']':
return $output;
case ',':
case ' ':
break;
default:
$isQuoted = in_array($sequence[$i], array('"', "'"));
$value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
if (!$isQuoted && false !== strpos($value, ': '))
{
// embedded mapping?
try
{
$value = self::parseMapping('{'.$value.'}');
}
catch (InvalidArgumentException $e)
{
// no, it's not
}
}
$output[] = $value;
--$i;
}
++$i;
}
throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
protected static function parseSequence($sequence, &$i = 0) {
$output = [];
$len = strlen($sequence);
$i += 1;
// [foo, bar, ...]
while ($i < $len) {
switch ($sequence[$i]) {
case '[':
// nested sequence
$output[] = self::parseSequence($sequence, $i);
break;
case '{':
// nested mapping
$output[] = self::parseMapping($sequence, $i);
break;
case ']':
return $output;
case ',':
case ' ':
break;
default:
$isQuoted = in_array($sequence[$i], ['"', "'"]);
$value = self::parseScalar($sequence, [',', ']'], ['"', "'"], $i);
if (!$isQuoted && false !== strpos($value, ': ')) {
// embedded mapping?
try {
$value = self::parseMapping('{' . $value . '}');
}
catch (InvalidArgumentException $e) {
// no, it's not
}
}
$output[] = $value;
--$i;
}
++$i;
}
throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
}
/**
@ -308,63 +283,57 @@ class sfYamlInline
*
* @return string A YAML string
*/
static protected function parseMapping($mapping, &$i = 0)
{
$output = array();
$len = strlen($mapping);
$i += 1;
// {foo: bar, bar:foo, ...}
while ($i < $len)
{
switch ($mapping[$i])
{
case ' ':
case ',':
++$i;
continue 2;
case '}':
return $output;
}
// key
$key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
// value
$done = false;
while ($i < $len)
{
switch ($mapping[$i])
{
case '[':
// nested sequence
$output[$key] = self::parseSequence($mapping, $i);
$done = true;
break;
case '{':
// nested mapping
$output[$key] = self::parseMapping($mapping, $i);
$done = true;
break;
case ':':
case ' ':
break;
default:
$output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
$done = true;
--$i;
}
++$i;
if ($done)
{
continue 2;
}
}
}
throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
protected static function parseMapping($mapping, &$i = 0) {
$output = [];
$len = strlen($mapping);
$i += 1;
// {foo: bar, bar:foo, ...}
while ($i < $len) {
switch ($mapping[$i]) {
case ' ':
case ',':
++$i;
continue 2;
case '}':
return $output;
}
// key
$key = self::parseScalar($mapping, [':', ' '], ['"', "'"], $i, false);
// value
$done = false;
while ($i < $len) {
switch ($mapping[$i]) {
case '[':
// nested sequence
$output[$key] = self::parseSequence($mapping, $i);
$done = true;
break;
case '{':
// nested mapping
$output[$key] = self::parseMapping($mapping, $i);
$done = true;
break;
case ':':
case ' ':
break;
default:
$output[$key] = self::parseScalar($mapping, [',', '}'], ['"', "'"], $i);
$done = true;
--$i;
}
++$i;
if ($done) {
continue 2;
}
}
}
throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
}
/**
@ -374,60 +343,55 @@ class sfYamlInline
*
* @return string A YAML string
*/
static protected function evaluateScalar($scalar)
{
$scalar = trim($scalar);
if ('1.1' === sfYaml::getSpecVersion())
{
$trueValues = array('true', 'on', '+', 'yes', 'y');
$falseValues = array('false', 'off', '-', 'no', 'n');
}
else
{
$trueValues = array('true');
$falseValues = array('false');
}
switch (true)
{
case 'null' == strtolower($scalar):
case '' == $scalar:
case '~' == $scalar:
return null;
case 0 === strpos($scalar, '!str'):
return (string) substr($scalar, 5);
case 0 === strpos($scalar, '! '):
return intval(self::parseScalar(substr($scalar, 2)));
case 0 === strpos($scalar, '!!php/object:'):
return unserialize(substr($scalar, 13));
case ctype_digit($scalar):
$raw = $scalar;
$cast = intval($scalar);
return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
case in_array(strtolower($scalar), $trueValues):
return true;
case in_array(strtolower($scalar), $falseValues):
return false;
case is_numeric($scalar):
return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
case 0 == strcasecmp($scalar, '.inf'):
case 0 == strcasecmp($scalar, '.NaN'):
return -log(0);
case 0 == strcasecmp($scalar, '-.inf'):
return log(0);
case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
return floatval(str_replace(',', '', $scalar));
case preg_match(self::getTimestampRegex(), $scalar):
return strtotime($scalar);
default:
return (string) $scalar;
}
protected static function evaluateScalar($scalar) {
$scalar = trim($scalar);
if ('1.1' === sfYaml::getSpecVersion()) {
$trueValues = ['true', 'on', '+', 'yes', 'y'];
$falseValues = ['false', 'off', '-', 'no', 'n'];
}
else {
$trueValues = ['true'];
$falseValues = ['false'];
}
switch (true) {
case 'null' == strtolower($scalar):
case '' == $scalar:
case '~' == $scalar:
return null;
case 0 === strpos($scalar, '!str'):
return (string) substr($scalar, 5);
case 0 === strpos($scalar, '! '):
return intval(self::parseScalar(substr($scalar, 2)));
case 0 === strpos($scalar, '!!php/object:'):
return unserialize(substr($scalar, 13));
case ctype_digit($scalar):
$raw = $scalar;
$cast = intval($scalar);
return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
case in_array(strtolower($scalar), $trueValues):
return true;
case in_array(strtolower($scalar), $falseValues):
return false;
case is_numeric($scalar):
return '0x' == $scalar[0] . $scalar[1] ? hexdec($scalar) : floatval($scalar);
case 0 == strcasecmp($scalar, '.inf'):
case 0 == strcasecmp($scalar, '.NaN'):
return -log(0);
case 0 == strcasecmp($scalar, '-.inf'):
return log(0);
case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
return floatval(str_replace(',', '', $scalar));
case preg_match(self::getTimestampRegex(), $scalar):
return strtotime($scalar);
default:
return (string) $scalar;
}
}
static protected function getTimestampRegex()
{
return <<<EOF
protected static function getTimestampRegex() {
return <<<EOF
~^
(?P<year>[0-9][0-9][0-9][0-9])
-(?P<month>[0-9][0-9]?)

886
sfyaml/sfYamlParser.php

@ -8,10 +8,9 @@
* file that was distributed with this source code.
*/
require_once(dirname(__FILE__).'/sfYamlInline.php');
require_once(dirname(__FILE__) . '/sfYamlInline.php');
if (!defined('PREG_BAD_UTF8_OFFSET_ERROR'))
{
if (!defined('PREG_BAD_UTF8_OFFSET_ERROR')) {
define('PREG_BAD_UTF8_OFFSET_ERROR', 5);
}
@ -26,20 +25,19 @@ if (!defined('PREG_BAD_UTF8_OFFSET_ERROR'))
class sfYamlParser
{
protected
$offset = 0,
$lines = array(),
$currentLineNb = -1,
$currentLine = '',
$refs = array();
$offset = 0,
$lines = [],
$currentLineNb = -1,
$currentLine = '',
$refs = [];
/**
* Constructor
*
* @param integer $offset The offset of YAML document (used for line numbers in error messages)
*/
public function __construct($offset = 0)
{
$this->offset = $offset;
public function __construct($offset = 0) {
$this->offset = $offset;
}
/**
@ -51,232 +49,193 @@ class sfYamlParser
*
* @throws InvalidArgumentException If the YAML is not valid
*/
public function parse($value)
{
$this->currentLineNb = -1;
$this->currentLine = '';
$this->lines = explode("\n", $this->cleanup($value));
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
{
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('UTF-8');
}
$data = array();
while ($this->moveToNextLine())
{
if ($this->isCurrentLineEmpty())
{
continue;
}
// tab?
if (preg_match('#^\t+#', $this->currentLine))
{
throw new InvalidArgumentException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
$isRef = $isInPlace = $isProcessed = false;
if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values))
{
if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches))
{
$isRef = $matches['ref'];
$values['value'] = $matches['value'];
}
// array
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
{
$c = $this->getRealCurrentLineNb() + 1;
$parser = new sfYamlParser($c);
$parser->refs =& $this->refs;
$data[] = $parser->parse($this->getNextEmbedBlock());
}
else
{
if (isset($values['leadspaces'])
&& ' ' == $values['leadspaces']
&& preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches))
{
// this is a compact notation element, add to next block and parse
$c = $this->getRealCurrentLineNb();
$parser = new sfYamlParser($c);
$parser->refs =& $this->refs;
$block = $values['value'];
if (!$this->isNextLineIndented())
{
$block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
}
$data[] = $parser->parse($block);
}
else
{
$data[] = $this->parseValue($values['value']);
}
}
}
else if (preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values))
{
$key = sfYamlInline::parseScalar($values['key']);
if ('<<' === $key)
{
if (isset($values['value']) && '*' === substr($values['value'], 0, 1))
{
$isInPlace = substr($values['value'], 1);
if (!array_key_exists($isInPlace, $this->refs))
{
throw new InvalidArgumentException(sprintf('Reference "%s" does not exist at line %s (%s).', $isInPlace, $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
}
else
{
if (isset($values['value']) && $values['value'] !== '')
{
$value = $values['value'];
}
else
{
$value = $this->getNextEmbedBlock();
}
$c = $this->getRealCurrentLineNb() + 1;
$parser = new sfYamlParser($c);
$parser->refs =& $this->refs;
$parsed = $parser->parse($value);
$merged = array();
if (!is_array($parsed))
{
throw new InvalidArgumentException(sprintf("YAML merge keys used with a scalar value instead of an array at line %s (%s)", $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
else if (isset($parsed[0]))
{
// Numeric array, merge individual elements
foreach (array_reverse($parsed) as $parsedItem)
{
if (!is_array($parsedItem))
{
throw new InvalidArgumentException(sprintf("Merge items must be arrays at line %s (%s).", $this->getRealCurrentLineNb() + 1, $parsedItem));
}
$merged = array_merge($parsedItem, $merged);
}
}
else
{
// Associative array, merge
$merged = array_merge($merged, $parsed);
}
$isProcessed = $merged;
}
}
else if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches))
{
$isRef = $matches['ref'];
$values['value'] = $matches['value'];
}
if ($isProcessed)
{
// Merge keys
$data = $isProcessed;
}
// hash
else if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
{
// if next line is less indented or equal, then it means that the current value is null
if ($this->isNextLineIndented())
{
$data[$key] = null;
}
else
{
$c = $this->getRealCurrentLineNb() + 1;
$parser = new sfYamlParser($c);
$parser->refs =& $this->refs;
$data[$key] = $parser->parse($this->getNextEmbedBlock());
}
}
else
{
if ($isInPlace)
{
$data = $this->refs[$isInPlace];
}
else
{
$data[$key] = $this->parseValue($values['value']);
}
}
}
else
{
// 1-liner followed by newline
if (2 == count($this->lines) && empty($this->lines[1]))
{
$value = sfYamlInline::load($this->lines[0]);
if (is_array($value))
{
$first = reset($value);
if ('*' === substr($first, 0, 1))
{
$data = array();
foreach ($value as $alias)
{
$data[] = $this->refs[substr($alias, 1)];
}
$value = $data;
}
}
if (isset($mbEncoding))
{
mb_internal_encoding($mbEncoding);
}
return $value;
}
switch (preg_last_error())
{
case PREG_INTERNAL_ERROR:
$error = 'Internal PCRE error on line';
break;
case PREG_BACKTRACK_LIMIT_ERROR:
$error = 'pcre.backtrack_limit reached on line';
break;
case PREG_RECURSION_LIMIT_ERROR:
$error = 'pcre.recursion_limit reached on line';
break;
case PREG_BAD_UTF8_ERROR:
$error = 'Malformed UTF-8 data on line';
break;