init
This commit is contained in:
commit
e8973f8ebb
1
DEBIAN/conffiles
Normal file
1
DEBIAN/conffiles
Normal file
|
@ -0,0 +1 @@
|
|||
/etc/wetddump/mysql.yml
|
8
DEBIAN/control
Normal file
8
DEBIAN/control
Normal file
|
@ -0,0 +1,8 @@
|
|||
Package: wetddump
|
||||
Version: 0.4
|
||||
Section: base
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
Depends: php5 (>= 5.3.3-7+squeeze15), mysql-server (>= 5.1.66-0+squeeze1)|percona-xtradb-cluster-56, rsync
|
||||
Maintainer: Simon Vieille <simon@webetdesign.com>
|
||||
Description: Backup manager
|
2
DEBIAN/postins
Executable file
2
DEBIAN/postins
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
|
1
DEBIAN/postrm
Executable file
1
DEBIAN/postrm
Executable file
|
@ -0,0 +1 @@
|
|||
#!/bin/sh
|
14
etc/wetddump/mysql.yml
Normal file
14
etc/wetddump/mysql.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
settings:
|
||||
dir: '/var/lib/mysqldump/'
|
||||
log: '/var/log/wetddump/mysql.log'
|
||||
mysql: '/var/lib/mysql/'
|
||||
complete:
|
||||
dir: 'complete/'
|
||||
enabled: false
|
||||
mysqldump:
|
||||
dir: 'sql/'
|
||||
enabled: true
|
||||
options: ['--add-drop-table', '--events', '--add-drop-database', '--databases']
|
||||
ignore:
|
||||
tables: []
|
||||
databases: ['information_schema']
|
76
usr/bin/wetddump-mysql
Executable file
76
usr/bin/wetddump-mysql
Executable file
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/php5
|
||||
<?php
|
||||
|
||||
require_once '/usr/share/wetddump/functions.php';
|
||||
|
||||
mySfYaml::load('/etc/wetddump/mysql.yml');
|
||||
|
||||
$log = mySfYaml::get('settings_log', '/var/log/wetddump/mysql.log');
|
||||
$dir = mySfYaml::get('settings_dir', '/var/wetddump/mysqldump');
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
$cmd = sprintf('mkdir -p %s', escapeshellarg($dir));
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
}
|
||||
|
||||
$cmd = sprintf('chdir %s', $dir);
|
||||
log_($cmd, $log);
|
||||
chdir($dir);
|
||||
|
||||
if (mySfYaml::get('settings_complete_enabled')) {
|
||||
$cdir = mySfYaml::get('settings_complete_dir', 'complete/');
|
||||
|
||||
$cmd = sprintf('rm -rf %s', escapeshellarg($cdir));
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
|
||||
$cmd = sprintf('mkdir -p %s', escapeshellarg($cdir));
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
|
||||
$cmd = sprintf('rsync -avz --delete %s/* %s', mySfYaml::get('settings_mysql'), $cdir);
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
}
|
||||
|
||||
if (mySfYaml::get('settings_mysqldump_enabled')) {
|
||||
$cdir = mySfYaml::get('settings_mysqldump_dir', 'sql/');
|
||||
|
||||
$cmd = sprintf('rm -rf %s', escapeshellarg($cdir));
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
|
||||
$cmd = sprintf('mkdir -p %s', escapeshellarg($cdir));
|
||||
log_($cmd, $log);
|
||||
exec_($cmd);
|
||||
|
||||
$bases = getMysqlDatabases();
|
||||
|
||||
foreach ($bases as $k => $base) {
|
||||
if (in_array($base, mySfYaml::get('settings_mysqldump_ignore_databases', array('information_schema')))) {
|
||||
log_(sprintf('Ignore "%s"', $base), $log);
|
||||
continue;
|
||||
}
|
||||
|
||||
$options = mySfYaml::get('settings_mysqldump_options', array());
|
||||
|
||||
if ($it = mySfYaml::get('settings_mysqldump_ignore_tables', array())) {
|
||||
foreach ($it as $table) {
|
||||
list($_base, $_table) = explode('.', $table);
|
||||
|
||||
if ($base == $_base) {
|
||||
$options[] = sprintf('--ignore-table=%s', $table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cmd = getMysqldumpCmd($base, implode(' ', $options), sprintf('%s/dump.%s.%s.gz', $cdir, $base, date('Y-m-d')));
|
||||
log_('Dump of '.$base, $log);
|
||||
exec_($cmd);
|
||||
}
|
||||
|
||||
$cmd = getMysqlPrivilegesDumpCmd(sprintf('%s/privileges.%s.sql', $cdir, date('Y-m-d')));
|
||||
log_('Dump of privileges', $log);
|
||||
exec_($cmd);
|
||||
}
|
7
usr/bin/wetddump-mysql-privileges
Executable file
7
usr/bin/wetddump-mysql-privileges
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
mysql -B -N $@ -e "SELECT DISTINCT CONCAT(
|
||||
'SHOW GRANTS FOR \'', user, '\'@\'', host, '\';'
|
||||
) AS query FROM mysql.user" | \
|
||||
mysql $@ | \
|
||||
sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
|
62
usr/share/wetddump/functions.php
Normal file
62
usr/share/wetddump/functions.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
function log_($message, $log)
|
||||
{
|
||||
$message = sprintf('[%s] %s', date('Y-m-d H:i:s'), trim($message)).PHP_EOL;
|
||||
echo $message;
|
||||
file_put_contents($log, $message, FILE_APPEND);
|
||||
}
|
||||
|
||||
function exec_($cmd)
|
||||
{
|
||||
return shell_exec($cmd);
|
||||
}
|
||||
|
||||
function __autoload($class_name)
|
||||
{
|
||||
require sprintf('/usr/share/wetddump/%s.class.php', $class_name);
|
||||
}
|
||||
|
||||
function getMysqldumpUser()
|
||||
{
|
||||
return 'debian-sys-maint';
|
||||
}
|
||||
|
||||
function getMysqldumpPassword()
|
||||
{
|
||||
return trim(shell_exec('grep password /etc/mysql/debian.cnf | egrep -v "^#" | head -n 1 | sed "s/password = //"'));
|
||||
}
|
||||
|
||||
function getMysqlDatabases()
|
||||
{
|
||||
mysql_connect('localhost', getMysqldumpUser(), getMysqldumpPassword()) or die(mysql_error());
|
||||
$results = mysql_query('SHOW DATABASES');
|
||||
$bases = array();
|
||||
|
||||
while ($fetch = mysql_fetch_array($results)) {
|
||||
$bases[] = $fetch[0];
|
||||
}
|
||||
|
||||
return $bases;
|
||||
}
|
||||
|
||||
function getMysqldumpCmd($db, $options, $output)
|
||||
{
|
||||
$cmd = sprintf(
|
||||
'mysqldump -u%s -p%s %s %s | gzip -9 > %s',
|
||||
getMysqldumpUser(), getMysqldumpPassword(), $options, $db,
|
||||
$output
|
||||
);
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
function getMysqlPrivilegesDumpCmd($output)
|
||||
{
|
||||
$cmd = sprintf(
|
||||
'wetddump-mysql-privileges -u%s -p%s > %s',
|
||||
getMysqldumpUser(), getMysqldumpPassword(), $output
|
||||
);
|
||||
|
||||
return $cmd;
|
||||
}
|
81
usr/share/wetddump/mySfYaml.class.php
Normal file
81
usr/share/wetddump/mySfYaml.class.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
class mySfYaml extends sfYaml
|
||||
{
|
||||
private static $file_loaded = false;
|
||||
private static $global_config = null;
|
||||
|
||||
public static function load($input)
|
||||
{
|
||||
self::$global_config = parent::load($input);
|
||||
self::$file_loaded = true;
|
||||
|
||||
return self::$global_config;
|
||||
}
|
||||
|
||||
public static function merge($input)
|
||||
{
|
||||
if (!self::$file_loaded) {
|
||||
return self::load($input);
|
||||
}
|
||||
|
||||
$config = sfYaml::load($input);
|
||||
|
||||
if ($config) {
|
||||
self::recursiveMerge(self::$global_config, $config);
|
||||
}
|
||||
|
||||
return self::$global_config;
|
||||
}
|
||||
|
||||
private static function recursiveMerge(&$global_config, $config)
|
||||
{
|
||||
foreach ($config as $key => $value) {
|
||||
if (!isset($global_config[$key])) {
|
||||
$global_config[$key] = $value;
|
||||
} else {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $vkey => $vvalue) {
|
||||
if (!isset($global_config[$key][$vkey])) {
|
||||
$global_config[$key][$vkey] = $vvalue;
|
||||
} else {
|
||||
self::recursiveMerge($global_config[$key], $value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$global_config[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getAll()
|
||||
{
|
||||
return self::$global_config;
|
||||
}
|
||||
|
||||
public static function get($var, $default = null)
|
||||
{
|
||||
if (!self::$file_loaded) {
|
||||
throw new Exception('Yaml file is not loaded yet, please see sfYaml::load method');
|
||||
}
|
||||
|
||||
$road = self::$global_config;
|
||||
|
||||
$parts = explode('_', $var);
|
||||
|
||||
while (true) {
|
||||
$shift = array_shift($parts);
|
||||
|
||||
if (isset($road[$shift])) {
|
||||
if (empty($parts)) {
|
||||
return $road[$shift];
|
||||
} else {
|
||||
$road = $road[$shift];
|
||||
}
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
126
usr/share/wetddump/sfYaml.class.php
Normal file
126
usr/share/wetddump/sfYaml.class.php
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the symfony package.
|
||||
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* sfYaml offers convenience methods to load and dump YAML.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage yaml
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @version SVN: $Id: sfYaml.class.php 8988 2008-05-15 20:24:26Z fabien $
|
||||
*/
|
||||
class sfYaml
|
||||
{
|
||||
protected static $spec = '1.2';
|
||||
|
||||
/**
|
||||
* Sets the YAML specification version to use.
|
||||
*
|
||||
* @param string $version The YAML specification version
|
||||
*/
|
||||
public static 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the YAML specification version to use.
|
||||
*
|
||||
* @return string The YAML specification version
|
||||
*/
|
||||
public static function getSpecVersion()
|
||||
{
|
||||
return self::$spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads YAML into a PHP array.
|
||||
*
|
||||
* The load method, when supplied with a YAML stream (string or file),
|
||||
* will do its best to convert YAML in a file into a PHP array.
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* $array = sfYaml::load('config.yml');
|
||||
* print_r($array);
|
||||
* </code>
|
||||
*
|
||||
* @param string $input Path of YAML file or string containing YAML
|
||||
*
|
||||
* @return array The YAML converted to a PHP array
|
||||
*
|
||||
* @throws InvalidArgumentException If the YAML is not valid
|
||||
*/
|
||||
public static function load($input)
|
||||
{
|
||||
$file = '';
|
||||
|
||||
// if input is a file, process it
|
||||
if (strpos($input, "\n") === false && is_file($input)) {
|
||||
$file = $input;
|
||||
|
||||
ob_start();
|
||||
$retval = include($input);
|
||||
$content = ob_get_clean();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps a PHP array to a YAML string.
|
||||
*
|
||||
* The dump method, when supplied with an array, will do its best
|
||||
* to convert the array into friendly YAML.
|
||||
*
|
||||
* @param array $array PHP array
|
||||
* @param integer $inline The level where you switch to inline YAML
|
||||
*
|
||||
* @return string A YAML string representing the original PHP array
|
||||
*/
|
||||
public static function dump($array, $inline = 2)
|
||||
{
|
||||
require_once dirname(__FILE__).'/sfYamlDumper.php';
|
||||
|
||||
$yaml = new sfYamlDumper();
|
||||
|
||||
return $yaml->dump($array, $inline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps echo to automatically provide a newline.
|
||||
*
|
||||
* @param string $string The string to echo with new line
|
||||
*/
|
||||
function echoln($string)
|
||||
{
|
||||
echo $string."\n";
|
||||
}
|
54
usr/share/wetddump/sfYamlDumper.class.php
Normal file
54
usr/share/wetddump/sfYamlDumper.class.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the symfony package.
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* sfYamlDumper dumps PHP variables to YAML strings.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage yaml
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @version SVN: $Id: sfYamlDumper.class.php 10575 2008-08-01 13:08:42Z nicolas $
|
||||
*/
|
||||
class sfYamlDumper
|
||||
{
|
||||
/**
|
||||
* Dumps a PHP value to YAML.
|
||||
*
|
||||
* @param mixed $input The PHP value
|
||||
* @param integer $inline The level where you switch to inline YAML
|
||||
* @param integer $indent The level o indentation indentation (used internally)
|
||||
*
|
||||
* @return string The YAML representation of the PHP value
|
||||
*/
|
||||
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);
|
||||
|
||||
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 + 2)
|
||||
).($willBeInlined ? "\n" : '');
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
440
usr/share/wetddump/sfYamlInline.class.php
Normal file
440
usr/share/wetddump/sfYamlInline.class.php
Normal file
|
@ -0,0 +1,440 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the symfony package.
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage yaml
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @version SVN: $Id: sfYamlInline.class.php 16177 2009-03-11 08:32:48Z fabien $
|
||||
*/
|
||||
class sfYamlInline
|
||||
{
|
||||
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
|
||||
|
||||
/**
|
||||
* Convert a YAML string to a PHP array.
|
||||
*
|
||||
* @param string $value A YAML string
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps a given PHP variable to a YAML string.
|
||||
*
|
||||
* @param mixed $value The PHP variable to convert
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps a PHP array to a YAML string.
|
||||
*
|
||||
* @param array $value The PHP array to dump
|
||||
*
|
||||
* @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, create_function('$v,$w', 'return (integer) $v + $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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a scalar to a YAML string.
|
||||
*
|
||||
* @param scalar $scalar
|
||||
* @param string $delimiters
|
||||
* @param array $stringDelimiter
|
||||
* @param integer $i
|
||||
* @param boolean $evaluate
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a quoted scalar to YAML.
|
||||
*
|
||||
* @param string $scalar
|
||||
* @param integer $i
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// unescape '
|
||||
$output = str_replace('\'\'', '\'', $output);
|
||||
}
|
||||
|
||||
$i += strlen($match[0]);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a sequence to a YAML string.
|
||||
*
|
||||
* @param string $sequence
|
||||
* @param integer $i
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a mapping to a YAML string.
|
||||
*
|
||||
* @param string $mapping
|
||||
* @param integer $i
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates scalars and replaces magic values.
|
||||
*
|
||||
* @param string $scalar
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
static protected function getTimestampRegex()
|
||||
{
|
||||
return <<<EOF
|
||||
~^
|
||||
(?P<year>[0-9][0-9][0-9][0-9])
|
||||
-(?P<month>[0-9][0-9]?)
|
||||
-(?P<day>[0-9][0-9]?)
|
||||
(?:(?:[Tt]|[ \t]+)
|
||||
(?P<hour>[0-9][0-9]?)
|
||||
:(?P<minute>[0-9][0-9])
|
||||
:(?P<second>[0-9][0-9])
|
||||
(?:\.(?P<fraction>[0-9]*))?
|
||||
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
|
||||
(?::(?P<tz_minute>[0-9][0-9]))?))?)?
|
||||
$~x
|
||||
EOF;
|
||||
}
|
||||
}
|
620
usr/share/wetddump/sfYamlParser.class.php
Normal file
620
usr/share/wetddump/sfYamlParser.class.php
Normal file
|
@ -0,0 +1,620 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the symfony package.
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (!defined('PREG_BAD_UTF8_OFFSET_ERROR'))
|
||||
{
|
||||
define('PREG_BAD_UTF8_OFFSET_ERROR', 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* sfYamlParser parses YAML strings to convert them to PHP arrays.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage yaml
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @version SVN: $Id: sfYamlParser.class.php 10832 2008-08-13 07:46:08Z fabien $
|
||||
*/
|
||||
class sfYamlParser
|
||||
{
|
||||
protected
|
||||
$offset = 0,
|
||||
$lines = array(),
|
||||
$currentLineNb = -1,
|
||||
$currentLine = '',
|
||||
$refs = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param integer $offset The offset of YAML document (used for line numbers in error messages)
|
||||
*/
|
||||
public function __construct($offset = 0)
|
||||
{
|
||||
$this->offset = $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a YAML string to a PHP value.
|
||||
*
|
||||
* @param string $value A YAML string
|
||||
*
|
||||
* @return mixed A PHP value
|
||||
*
|
||||
* @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;
|
||||
case PREG_BAD_UTF8_OFFSET_ERROR:
|
||||
$error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point on line';
|
||||
break;
|
||||
default:
|
||||
$error = 'Unable to parse line';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('%s %d (%s).', $error, $this->getRealCurrentLineNb() + 1, $this->currentLine));
|
||||
}
|
||||
|
||||
if ($isRef)
|
||||
{
|
||||
$this->refs[$isRef] = end($data);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mbEncoding))
|
||||
{
|
||||
mb_internal_encoding($mbEncoding);
|
||||
}
|
||||
|
||||
return empty($data) ? null : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current line number (takes the offset into account).
|
||||
*
|
||||
* @return integer The current line number
|
||||
*/
|
||||
protected function getRealCurrentLineNb()
|
||||
{
|
||||
return $this->currentLineNb + $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current line indentation.
|
||||
*
|
||||
* @return integer The current line indentation
|
||||
*/
|
||||
protected function getCurrentLineIndentation()
|
||||
{
|
||||
return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next embed block of YAML.
|
||||
*
|
||||
* @param integer $indentation The indent level at which the block is to be read, or null for default
|
||||
*
|
||||
* @return string A YAML string
|
||||
*/
|
||||
protected function getNextEmbedBlock($indentation = null)
|
||||
{
|
||||
$this->moveToNextLine();
|
||||
|
||||
if (null === $indentation)
|
||||
{
|
||||
$newIndent = $this->getCurrentLineIndentation();
|
||||
|
||||
if (!$this->isCurrentLineEmpty() && 0 == $newIndent)
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$newIndent = $indentation;
|
||||
}
|
||||
|
||||
$data = array(substr($this->currentLine, $newIndent));
|
||||
|
||||
while ($this->moveToNextLine())
|
||||
{
|
||||
if ($this->isCurrentLineEmpty())
|
||||
{
|
||||
if ($this->isCurrentLineBlank())
|
||||
{
|
||||
$data[] = substr($this->currentLine, $newIndent);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$indent = $this->getCurrentLineIndentation();
|
||||
|
||||
if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match))
|
||||
{
|
||||
// empty line
|
||||
$data[] = $match['text'];
|
||||
}
|
||||
else if ($indent >= $newIndent)
|
||||
{
|
||||
$data[] = substr($this->currentLine, $newIndent);
|
||||
}
|
||||
else if (0 == $indent)
|
||||
{
|
||||
$this->moveToPreviousLine();
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the parser to the next line.
|
||||
*/
|
||||
protected function moveToNextLine()
|
||||
{
|
||||
if ($this->currentLineNb >= count($this->lines) - 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->currentLine = $this->lines[++$this->currentLineNb];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the parser to the previous line.
|
||||
*/
|
||||
protected function moveToPreviousLine()
|
||||
{
|
||||
$this->currentLine = $this->lines[--$this->currentLineNb];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a YAML value.
|
||||
*
|
||||
* @param string $value A YAML value
|
||||
*
|
||||
* @return mixed A PHP value
|
||||
*/
|
||||
protected function parseValue($value)
|
||||
{
|
||||
if ('*' === substr($value, 0, 1))
|
||||
{
|
||||
if (false !== $pos = strpos($value, '#'))
|
||||
{
|
||||
$value = substr($value, 1, $pos - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = substr($value, 1);
|
||||
}
|
||||
|
||||
if (!array_key_exists($value, $this->refs))
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine));
|
||||
}
|
||||
return $this->refs[$value];
|
||||
}
|
||||
|
||||
if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches))
|
||||
{
|
||||
$modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
|
||||
|
||||
return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return sfYamlInline::load($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a folded scalar.
|
||||
*
|
||||
* @param string $separator The separator that was used to begin this folded scalar (| or >)
|
||||
* @param string $indicator The indicator that was used to begin this folded scalar (+ or -)
|
||||
* @param integer $indentation The indentation that was used to begin this folded scalar
|
||||
*
|
||||
* @return string The text value
|
||||
*/
|
||||
protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
|
||||
{
|
||||
$separator = '|' == $separator ? "\n" : ' ';
|
||||
$text = '';
|
||||
|
||||
$notEOF = $this->moveToNextLine();
|
||||
|
||||
while ($notEOF && $this->isCurrentLineBlank())
|
||||
{
|
||||
$text .= "\n";
|
||||
|
||||
$notEOF = $this->moveToNextLine();
|
||||
}
|
||||
|
||||
if (!$notEOF)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!preg_match('#^(?P<indent>'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P<text>.*)$#u', $this->currentLine, $matches))
|
||||
{
|
||||
$this->moveToPreviousLine();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
$textIndent = $matches['indent'];
|
||||
$previousIndent = 0;
|
||||
|
||||
$text .= $matches['text'].$separator;
|
||||
while ($this->currentLineNb + 1 < count($this->lines))
|
||||
{
|
||||
$this->moveToNextLine();
|
||||
|
||||
if (preg_match('#^(?P<indent> {'.strlen($textIndent).',})(?P<text>.+)$#u', $this->currentLine, $matches))
|
||||
{
|
||||
if (' ' == $separator && $previousIndent != $matches['indent'])
|
||||
{
|
||||
$text = substr($text, 0, -1)."\n";
|
||||
}
|
||||
$previousIndent = $matches['indent'];
|
||||
|
||||
$text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator);
|
||||
}
|
||||
else if (preg_match('#^(?P<text> *)$#', $this->currentLine, $matches))
|
||||
{
|
||||
$text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->moveToPreviousLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (' ' == $separator)
|
||||
{
|
||||
// replace last separator by a newline
|
||||
$text = preg_replace('/ (\n*)$/', "\n$1", $text);
|
||||
}
|
||||
|
||||
switch ($indicator)
|
||||
{
|
||||
case '':
|
||||
$text = preg_replace('#\n+$#s', "\n", $text);
|
||||
break;
|
||||
case '+':
|
||||
break;
|
||||
case '-':
|
||||
$text = preg_replace('#\n+$#s', '', $text);
|
||||
break;
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the next line is indented.
|
||||
*
|
||||
* @return Boolean Returns true if the next line is indented, false otherwise
|
||||
*/
|
||||
protected function isNextLineIndented()
|
||||
{
|
||||
$currentIndentation = $this->getCurrentLineIndentation();
|
||||
$notEOF = $this->moveToNextLine();
|
||||
|
||||
while ($notEOF && $this->isCurrentLineEmpty())
|
||||
{
|
||||
$notEOF = $this->moveToNextLine();
|
||||
}
|
||||
|
||||
if (false === $notEOF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = false;
|
||||
if ($this->getCurrentLineIndentation() <= $currentIndentation)
|
||||
{
|
||||
$ret = true;
|
||||
}
|
||||
|
||||
$this->moveToPreviousLine();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current line is blank or if it is a comment line.
|
||||
*
|
||||
* @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
|
||||
*/
|
||||
protected function isCurrentLineEmpty()
|
||||
{
|
||||
return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current line is blank.
|
||||
*
|
||||
* @return Boolean Returns true if the current line is blank, false otherwise
|
||||
*/
|
||||
protected function isCurrentLineBlank()
|
||||
{
|
||||
return '' == trim($this->currentLine, ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current line is a comment line.
|
||||
*
|
||||
* @return Boolean Returns true if the current line is a comment line, false otherwise
|
||||
*/
|
||||
protected function isCurrentLineComment()
|
||||
{
|
||||
//checking explicitly the first char of the trim is faster than loops or strpos
|
||||
$ltrimmedLine = ltrim($this->currentLine, ' ');
|
||||
return $ltrimmedLine[0] === '#';
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanups a YAML string to be parsed.
|
||||
*
|
||||
* @param string $value The input YAML string
|
||||
*
|
||||
* @return string A cleaned up YAML string
|
||||
*/
|
||||
protected function cleanup($value)
|
||||
{
|
||||
$value = str_replace(array("\r\n", "\r"), "\n", $value);
|
||||
|
||||
if (!preg_match("#\n$#", $value))
|
||||
{
|
||||
$value .= "\n";
|
||||
}
|
||||
|
||||
// strip YAML header
|
||||
$count = 0;
|
||||
$value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#su', '', $value, -1, $count);
|
||||
$this->offset += $count;
|
||||
|
||||
// remove leading comments
|
||||
$trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
|
||||
if ($count == 1)
|
||||
{
|
||||
// items have been removed, update the offset
|
||||
$this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
|
||||
$value = $trimmedValue;
|
||||
}
|
||||
|
||||
// remove start of the document marker (---)
|
||||
$trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
|
||||
if ($count == 1)
|
||||
{
|
||||
// items have been removed, update the offset
|
||||
$this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
|
||||
$value = $trimmedValue;
|
||||
|
||||
// remove end of the document marker (...)
|
||||
$value = preg_replace('#\.\.\.\s*$#s', '', $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
0
var/log/wetddump/mysql.log
Normal file
0
var/log/wetddump/mysql.log
Normal file
Loading…
Reference in a new issue