@ -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 ] ? )