--- /dev/null
+/package.xml/1.10/Sat Feb 16 18:11:07 2008//
+D/examples////
+D/lib////
+D/test////
--- /dev/null
+framework/Yaml
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+D/Horde////
--- /dev/null
+framework/Yaml/examples
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+D/Yaml////
--- /dev/null
+framework/Yaml/examples/Horde
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+/dump.php/1.1/Wed Mar 5 20:37:57 2008//
+/example.yaml/1.1/Wed Mar 5 20:37:57 2008//
+/load.php/1.1/Wed Mar 5 20:37:57 2008//
+D
--- /dev/null
+framework/Yaml/examples/Horde/Yaml
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+<?php
+/**
+ * @package Horde_Yaml
+ */
+
+require_once dirname(dirname(dirname(__FILE__))) . '/Yaml/__autoload.php';
+
+$array[] = 'Sequence item';
+$array['The Key'] = 'Mapped value';
+$array[] = array('A sequence','of a sequence');
+$array[] = array('first' => 'A sequence','second' => 'of mapped values');
+$array['Mapped'] = array('A sequence','which is mapped');
+$array['A Note'] = 'What if your text is too long?';
+$array['Another Note'] = 'If that is the case, the dumper will probably fold your text by using a block. Kinda like this.';
+$array['The trick?'] = 'The trick is that we overrode the default indent, 2, to 4 and the default wordwrap, 40, to 60.';
+$array['Old Dog'] = "And if you want\n to preserve line breaks, \ngo ahead!";
+
+echo "A PHP array run through Horde_Yaml::dump():\n";
+var_dump(Horde_Yaml::dump($array, 4, 60));
--- /dev/null
+#
+# S P Y C
+# a simple php yaml class
+# v0.2(.4)
+#
+# author: [chris wanstrath, chris@ozmm.org]
+# websites: [http://www.yaml.org, http://spyc.sourceforge.net/]
+# license: [MIT License, http://www.opensource.org/licenses/mit-license.php]
+# copyright: (c) 2005-2006 Chris Wanstrath
+#
+# spyc.yml - A file containing the YAML that Spyc understands.
+
+# Mappings - with proper types
+String: Anyone's name, really.
+Int: 13
+True: true
+False: false
+Zero: 0
+Null: NULL
+Float: 5.34
+
+# A sequence
+- PHP Class
+- Basic YAML Loader
+- Very Basic YAML Dumper
+
+# A sequence of a sequence
+-
+ - YAML is so easy to learn.
+ - Your config files will never be the same.
+
+# Sequence of mappings
+-
+ cpu: 1.5ghz
+ ram: 1 gig
+ os : os x 10.4.1
+
+# Mapped sequence
+domains:
+ - yaml.org
+ - php.net
+
+# A sequence like this.
+- program: Adium
+ platform: OS X
+ type: Chat Client
+
+# A folded block as a mapped value
+no time: >
+ There isn't any time
+ for your tricks!
+
+ Do you understand?
+
+# A literal block as a mapped value
+some time: |
+ There is nothing but time
+ for your tricks.
+
+# Crazy combinations
+databases:
+ - name: spartan
+ notes:
+ - Needs to be backed up
+ - Needs to be normalized
+ type: mysql
+
+# You can be a bit tricky
+"if: you'd": like
+
+# Inline sequences
+- [One, Two, Three, Four]
+
+# Nested Inline Sequences
+- [One, [Two, And, Three], Four, Five]
+
+# Nested Nested Inline Sequences
+- [This, [Is, Getting, [Ridiculous, Guys]], Seriously, [Show, Mercy]]
+
+# Inline mappings
+- {name: chris, age: young, brand: lucky strike}
+
+# Nested inline mappings
+- {name: mark, age: older than chris, brand: [marlboro, lucky strike]}
+
+# References -- they're shaky, but functional
+dynamic languages: &DLANGS
+ - Perl
+ - Python
+ - PHP
+ - Ruby
+compiled languages: &CLANGS
+ - C/C++
+ - Java
+all languages:
+ - *DLANGS
+ - *CLANGS
+
+# Added in .2.2: Escaped quotes
+- you know, this shouldn't work. but it does.
+- 'that''s my value.'
+- 'again, that\'s my value.'
+- "here's to \"quotes\", boss."
+
+# added in .2.3
+- {name: "Foo, Bar's", age: 20}
+
+# Added in .2.4: bug [ 1418193 ] Quote Values in Nested Arrays
+- [a, ['1', "2"], b]
+
+# Added in .2.4: malformed YAML
+all
+ javascripts: [dom1.js, dom.js]
+
+# Added in .2
+1040: Ooo, a numeric key! # And working comments? Wow!
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * @package Horde_Yaml
+ */
+
+require_once dirname(dirname(dirname(__FILE__))) . '/Yaml/__autoload.php';
+
+$file = dirname(__FILE__) . '/example.yaml';
+echo "$file loaded into PHP:\n";
+var_dump(Horde_Yaml::loadFile($file));
--- /dev/null
+D/Horde////
--- /dev/null
+framework/Yaml/lib
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+/Yaml.php/1.5/Wed Jun 18 19:05:25 2008//
+D/Yaml////
--- /dev/null
+framework/Yaml/lib/Horde
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+<?php
+/**
+ * Horde YAML package
+ *
+ * This package is heavily inspired by the Spyc PHP YAML
+ * implementation (http://spyc.sourceforge.net/), and portions are
+ * copyright 2005-2006 Chris Wanstrath.
+ *
+ * @author Chris Wanstrath <chris@ozmm.org>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ */
+
+/**
+ * Horde YAML parser.
+ *
+ * This class can be used to read a YAML file and convert its contents
+ * into a PHP array. The native PHP parser supports a limited
+ * subsection of the YAML spec, but if the syck extension is present,
+ * that will be used for parsing.
+ *
+ * @category Horde
+ * @package Horde_Yaml
+ */
+class Horde_Yaml
+{
+ /**
+ * Callback used for alternate YAML loader, typically exported
+ * by a faster PHP extension. This function's first argument
+ * must accept a string with YAML content.
+ *
+ * @var callback
+ */
+ public static $loadfunc = 'syck_load';
+
+ /**
+ * Callback used for alternate YAML dumper, typically exported
+ * by a faster PHP extension. This function's first argument
+ * must accept a mixed variable to be dumped.
+ *
+ * @var callback
+ */
+ public static $dumpfunc = 'syck_dump';
+
+ /**
+ * Whitelist of classes that can be instantiated automatically
+ * when loading YAML docs that include serialized PHP objects.
+ *
+ * @var array
+ */
+ public static $allowedClasses = array('ArrayObject');
+
+ /**
+ * Load a string containing YAML and parse it into a PHP array.
+ * Returns an empty array on failure.
+ *
+ * @param string $yaml String containing YAML
+ * @return array PHP array representation of YAML content
+ */
+ public static function load($yaml)
+ {
+ if (!is_string($yaml) || !strlen($yaml)) {
+ $msg = 'YAML to parse must be a string and cannot be empty.';
+ throw new InvalidArgumentException($msg);
+ }
+
+ if (is_callable(self::$loadfunc)) {
+ return call_user_func(self::$loadfunc, $yaml);
+ return is_array($array) ? $array : array();
+ }
+
+ if (strpos($yaml, "\r") !== false) {
+ $yaml = str_replace(array("\r\n", "\r"), array("\n", "\n"), $yaml);
+ }
+ $lines = explode("\n", $yaml);
+ $loader = new Horde_Yaml_Loader;
+
+ while (list(,$line) = each($lines)) {
+ $loader->parse($line);
+ }
+
+ return $loader->toArray();
+ }
+
+ /**
+ * Load a file containing YAML and parse it into a PHP array.
+ *
+ * If the file cannot be opened, an exception is thrown. If the
+ * file is read but parsing fails, an empty array is returned.
+ *
+ * @param string $filename Filename to load
+ * @return array PHP array representation of YAML content
+ * @throws IllegalArgumentException If $filename is invalid
+ * @throws Horde_Yaml_Exception If the file cannot be opened.
+ */
+ public static function loadFile($filename)
+ {
+ if (!is_string($filename) || !strlen($filename)) {
+ $msg = 'Filename must be a string and cannot be empty';
+ throw new InvalidArgumentException($msg);
+ }
+
+ $stream = @fopen($filename, 'rb');
+ if (!$stream) {
+ throw new Horde_Yaml_Exception('Failed to open file: ', error_get_last());
+ }
+
+ return self::loadStream($stream);
+ }
+
+ /**
+ * Load YAML from a PHP stream resource.
+ *
+ * @param resource $stream PHP stream resource
+ * @return array PHP array representation of YAML content
+ */
+ public static function loadStream($stream)
+ {
+ if (! is_resource($stream) || get_resource_type($stream) != 'stream') {
+ throw new InvalidArgumentException('Stream must be a stream resource');
+ }
+
+ if (is_callable(self::$loadfunc)) {
+ return call_user_func(self::$loadfunc, stream_get_contents($stream));
+ }
+
+ $loader = new Horde_Yaml_Loader;
+ while (!feof($stream)) {
+ $loader->parse(stream_get_line($stream, 100000, "\n"));
+ }
+
+ return $loader->toArray();
+ }
+
+ /**
+ * Dump a PHP array to YAML.
+ *
+ * The dump method, when supplied with an array, will do its best
+ * to convert the array into friendly YAML.
+ *
+ * @param array|Traversable $array PHP array or traversable object
+ * @param integer $options Options to pass to dumper
+ * @return string YAML representation of $value
+ */
+ public static function dump($value, $options = array())
+ {
+ if (is_callable(self::$dumpfunc)) {
+ return call_user_func(self::$dumpfunc, $value);
+ }
+
+ $dumper = new Horde_Yaml_Dumper();
+ return $dumper->dump($value, $options);
+ }
+
+}
--- /dev/null
+/Dumper.php/1.5/Wed Jun 18 19:05:26 2008//
+/Exception.php/1.3/Wed Jun 18 19:05:26 2008//
+/Loader.php/1.6/Wed Jun 18 19:05:26 2008//
+/Node.php/1.3/Wed Jun 18 19:05:26 2008//
+D
--- /dev/null
+framework/Yaml/lib/Horde/Yaml
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+<?php
+/**
+ * Horde YAML package
+ *
+ * This package is heavily inspired by the Spyc PHP YAML
+ * implementation (http://spyc.sourceforge.net/), and portions are
+ * copyright 2005-2006 Chris Wanstrath.
+ *
+ * @author Chris Wanstrath <chris@ozmm.org>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ */
+
+/**
+ * Dump PHP data structures to YAML.
+ *
+ * @category Horde
+ * @package Horde_Yaml
+ */
+class Horde_Yaml_Dumper
+{
+ protected $_options = array();
+
+ /**
+ * Dump PHP array to YAML
+ *
+ * The dump method, when supplied with an array, will do its best
+ * to convert the array into valid YAML.
+ *
+ * Options:
+ * `indent`:
+ * number of spaces to indent children (default 2)
+ * `wordwrap`:
+ * wordwrap column number (default 40)
+ *
+ * @param array|Traversable $array PHP array or traversable object
+ * @param integer $options Options for dumping
+ * @return string YAML representation of $value
+ */
+ public function dump($value, $options = array())
+ {
+ // validate & merge default options
+ if (!is_array($options)) {
+ throw new InvalidArgumentException('Options must be an array');
+ }
+
+ $defaults = array('indent' => 2,
+ 'wordwrap' => 40);
+ $this->_options = array_merge($defaults, $options);
+
+ if (! is_int($this->_options['indent'])) {
+ throw new InvalidArgumentException('Indent must be an integer');
+ }
+
+ if (! is_int($this->_options['wordwrap'])) {
+ throw new InvalidArgumentException('Wordwrap column must be an integer');
+ }
+
+ // new YAML document
+ $dump = "---\n";
+
+ // iterate through array and yamlize it
+ foreach ($value as $key => $value) {
+ $dump .= $this->_yamlize($key, $value, 0);
+ }
+ return $dump;
+ }
+
+ /**
+ * Attempts to convert a key / value array item to YAML
+ *
+ * @param string $key The name of the key
+ * @param string|array $value The value of the item
+ * @param integer $indent The indent of the current node
+ * @return string
+ */
+ protected function _yamlize($key, $value, $indent)
+ {
+ if ($value instanceof Serializable) {
+ // Dump serializable objects as !php/object::classname serialize_data
+ $data = '!php/object::' . get_class($value) . ' ' . $value->serialize();
+ $string = $this->_dumpNode($key, $data, $indent);
+ } elseif (is_array($value) || $value instanceof Traversable) {
+ // It has children. Make it the right kind of item.
+ $string = $this->_dumpNode($key, null, $indent);
+
+ // Add the indent.
+ $indent += $this->_options['indent'];
+
+ // Yamlize the array.
+ $string .= $this->_yamlizeArray($value, $indent);
+ } elseif (!is_array($value)) {
+ // No children.
+ $string = $this->_dumpNode($key, $value, $indent);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Attempts to convert an array to YAML
+ *
+ * @param array $array The array you want to convert
+ * @param integer $indent The indent of the current level
+ * @return string
+ */
+ protected function _yamlizeArray($array, $indent)
+ {
+ if (!is_array($array)) {
+ return false;
+ }
+
+ $string = '';
+ foreach ($array as $key => $value) {
+ $string .= $this->_yamlize($key, $value, $indent);
+ }
+ return $string;
+ }
+
+ /**
+ * Returns YAML from a key and a value
+ *
+ * @param string $key The name of the key
+ * @param string $value The value of the item
+ * @param integer $indent The indent of the current node
+ * @return string
+ */
+ protected function _dumpNode($key, $value, $indent)
+ {
+ // Do some folding here, for blocks.
+ if (strpos($value, "\n") !== false
+ || strpos($value, ': ') !== false
+ || strpos($value, '- ') !== false) {
+ $value = $this->_doLiteralBlock($value, $indent);
+ } else {
+ $value = $this->_fold($value, $indent);
+ }
+
+ if (is_bool($value)) {
+ $value = ($value) ? 'true' : 'false';
+ } elseif (is_float($value)) {
+ if (is_nan($value)) {
+ $value = '.NAN';
+ } elseif ($value === INF) {
+ $value = '.INF';
+ } elseif ($value === -INF) {
+ $value = '-.INF';
+ }
+ }
+
+ $spaces = str_repeat(' ', $indent);
+
+ if (is_int($key)) {
+ // It's a sequence.
+ $string = $spaces . '- ' . $value . "\n";
+ } else {
+ // It's mapped.
+ $string = $spaces . $key . ': ' . $value . "\n";
+ }
+
+ return $string;
+ }
+
+ /**
+ * Creates a literal block for dumping
+ *
+ * @param string $value
+ * @param integer $indent The value of the indent.
+ * @return string
+ */
+ protected function _doLiteralBlock($value, $indent)
+ {
+ $exploded = explode("\n", $value);
+ $newValue = '|';
+ $indent += $this->_options['indent'];
+ $spaces = str_repeat(' ', $indent);
+ foreach ($exploded as $line) {
+ $newValue .= "\n" . $spaces . trim($line);
+ }
+ return $newValue;
+ }
+
+ /**
+ * Folds a string of text, if necessary
+ *
+ * @param $value The string you wish to fold
+ * @return string
+ */
+ protected function _fold($value, $indent)
+ {
+ // Don't do anything if wordwrap is set to 0
+ if (! $this->_options['wordwrap']) {
+ return $value;
+ }
+
+ if (strlen($value) > $this->_options['wordwrap']) {
+ $indent += $this->_options['indent'];
+ $indent = str_repeat(' ', $indent);
+ $wrapped = wordwrap($value, $this->_options['wordwrap'], "\n$indent");
+ $value = ">\n" . $indent . $wrapped;
+ }
+
+ return $value;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Horde YAML package
+ *
+ * This package is heavily inspired by the Spyc PHP YAML
+ * implementation (http://spyc.sourceforge.net/), and portions are
+ * copyright 2005-2006 Chris Wanstrath.
+ *
+ * @author Chris Wanstrath <chris@ozmm.org>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ */
+
+/**
+ * Exception class for exceptions thrown by Horde_Yaml
+ *
+ * @category Horde
+ * @package Horde_Yaml
+ */
+class Horde_Yaml_Exception extends Exception
+{
+
+ public function __construct($message = null, $code_or_lasterror = 0)
+ {
+ if (is_array($code_or_lasterror)) {
+ if ($message) {
+ $message .= $code_or_lasterror['message'];
+ } else {
+ $message = $code_or_lasterror['message'];
+ }
+
+ $this->file = $code_or_lasterror['file'];
+ $this->line = $code_or_lasterror['line'];
+ $code = $code_or_lasterror['type'];
+ } else {
+ $code = $code_or_lasterror;
+ }
+
+ parent::__construct($message, $code);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Horde YAML package
+ *
+ * This package is heavily inspired by the Spyc PHP YAML
+ * implementation (http://spyc.sourceforge.net/), and portions are
+ * copyright 2005-2006 Chris Wanstrath.
+ *
+ * @author Chris Wanstrath <chris@ozmm.org>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ */
+
+/**
+ * Parse YAML strings into PHP data structures
+ *
+ * @category Horde
+ * @package Horde_Yaml
+ */
+class Horde_Yaml_Loader
+{
+ /**
+ * List of nodes with references
+ * @var array
+ */
+ protected $_haveRefs = array();
+
+ /**
+ * All nodes
+ * @var array
+ */
+ protected $_allNodes = array();
+
+ /**
+ * Array of node parents
+ * @var array
+ */
+ protected $_allParent = array();
+
+ /**
+ * Last indent level
+ * @var integer
+ */
+ protected $_lastIndent = 0;
+
+ /**
+ * Last node id
+ * @var integer
+ */
+ protected $_lastNode = null;
+
+ /**
+ * Is the parser inside a block?
+ * @var boolean
+ */
+ protected $_inBlock = false;
+
+ /**
+ * @var boolean
+ */
+ protected $_isInline = false;
+
+ /**
+ * Next node id to use
+ * @var integer
+ */
+ protected $_nodeId = 1;
+
+ /**
+ * Last line number parsed.
+ * @var integer
+ */
+ protected $_lineNumber = 0;
+
+ /**
+ * Create a new YAML parser.
+ */
+ public function __construct()
+ {
+ $base = new Horde_Yaml_Node($this->_nodeId++);
+ $base->indent = 0;
+ $this->_lastNode = $base->id;
+ }
+
+ /**
+ * Return the PHP built from all YAML parsed so far.
+ *
+ * @return array PHP version of parsed YAML
+ */
+ public function toArray()
+ {
+ // Here we travel through node-space and pick out references
+ // (& and *).
+ $this->_linkReferences();
+
+ // Build the PHP array out of node-space.
+ return $this->_buildArray();
+ }
+
+ /**
+ * Parse a line of a YAML file.
+ *
+ * @param string $line The line of YAML to parse.
+ * @return Horde_Yaml_Node YAML Node
+ */
+ public function parse($line)
+ {
+ // Keep track of how many lines we've parsed for friendlier
+ // error messages.
+ ++$this->_lineNumber;
+
+ $trimmed = trim($line);
+
+ // If the line starts with a tab (instead of a space), throw a fit.
+ if (preg_match('/^ *(\t) *[^\t ]/', $line)) {
+ $msg = "Line {$this->_lineNumber} indent contains a tab. "
+ . 'YAML only allows spaces for indentation.';
+ throw new Horde_Yaml_Exception($msg);
+ }
+
+ if (!$this->_inBlock && empty($trimmed)) {
+ return;
+ } elseif ($this->_inBlock && empty($trimmed)) {
+ $last =& $this->_allNodes[$this->_lastNode];
+ $last->data[key($last->data)] .= "\n";
+ } elseif ($trimmed[0] != '#' && substr($trimmed, 0, 3) != '---') {
+ // Create a new node and get its indent
+ $node = new Horde_Yaml_Node($this->_nodeId++);
+ $node->indent = $this->_getIndent($line);
+
+ // Check where the node lies in the hierarchy
+ if ($this->_lastIndent == $node->indent) {
+ // If we're in a block, add the text to the parent's data
+ if ($this->_inBlock) {
+ $parent =& $this->_allNodes[$this->_lastNode];
+ $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd;
+ } else {
+ // The current node's parent is the same as the previous node's
+ if (isset($this->_allNodes[$this->_lastNode])) {
+ $node->parent = $this->_allNodes[$this->_lastNode]->parent;
+ }
+ }
+ } elseif ($this->_lastIndent < $node->indent) {
+ if ($this->_inBlock) {
+ $parent =& $this->_allNodes[$this->_lastNode];
+ $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd;
+ } elseif (!$this->_inBlock) {
+ // The current node's parent is the previous node
+ $node->parent = $this->_lastNode;
+
+ // If the value of the last node's data was > or |
+ // we need to start blocking i.e. taking in all
+ // lines as a text value until we drop our indent.
+ $parent =& $this->_allNodes[$node->parent];
+ $this->_allNodes[$node->parent]->children = true;
+ if (is_array($parent->data)) {
+ if (isset($parent->data[key($parent->data)])) {
+ $chk = $parent->data[key($parent->data)];
+ if ($chk === '>') {
+ $this->_inBlock = true;
+ $this->_blockEnd = '';
+ $parent->data[key($parent->data)] =
+ str_replace('>', '', $parent->data[key($parent->data)]);
+ $parent->data[key($parent->data)] .= trim($line) . ' ';
+ $this->_allNodes[$node->parent]->children = false;
+ $this->_lastIndent = $node->indent;
+ } elseif ($chk === '|') {
+ $this->_inBlock = true;
+ $this->_blockEnd = "\n";
+ $parent->data[key($parent->data)] =
+ str_replace('|', '', $parent->data[key($parent->data)]);
+ $parent->data[key($parent->data)] .= trim($line) . "\n";
+ $this->_allNodes[$node->parent]->children = false;
+ $this->_lastIndent = $node->indent;
+ }
+ }
+ }
+ }
+ } elseif ($this->_lastIndent > $node->indent) {
+ // Any block we had going is dead now
+ if ($this->_inBlock) {
+ $this->_inBlock = false;
+ if ($this->_blockEnd == "\n") {
+ $last =& $this->_allNodes[$this->_lastNode];
+ $last->data[key($last->data)] =
+ trim($last->data[key($last->data)]);
+ }
+ }
+
+ // We don't know the parent of the node so we have to
+ // find it
+ foreach ($this->_indentSort[$node->indent] as $n) {
+ if ($n->indent == $node->indent) {
+ $node->parent = $n->parent;
+ }
+ }
+ }
+
+ if (!$this->_inBlock) {
+ // Set these properties with information from our
+ // current node
+ $this->_lastIndent = $node->indent;
+
+ // Set the last node
+ $this->_lastNode = $node->id;
+
+ // Parse the YAML line and return its data
+ $node->data = $this->_parseLine($line);
+
+ // Add the node to the master list
+ $this->_allNodes[$node->id] = $node;
+
+ // Add a reference to the parent list
+ $this->_allParent[intval($node->parent)][] = $node->id;
+
+ // Add a reference to the node in an indent array
+ $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id];
+
+ // Add a reference to the node in a References array
+ // if this node has a YAML reference in it.
+ $is_array = is_array($node->data);
+ $key = key($node->data);
+ $isset = isset($node->data[$key]);
+ if ($isset) {
+ $nodeval = $node->data[$key];
+ }
+ if (($is_array && $isset && !is_array($nodeval) && !is_object($nodeval))
+ && (strlen($nodeval) && ($nodeval[0] == '&' || $nodeval[0] == '*') && $nodeval[1] != ' ')) {
+ $this->_haveRefs[] =& $this->_allNodes[$node->id];
+ } elseif ($is_array && $isset && is_array($nodeval)) {
+ // Incomplete reference making code. Needs to be
+ // cleaned up.
+ foreach ($node->data[$key] as $d) {
+ if (!is_array($d) && strlen($d) && (($d[0] == '&' || $d[0] == '*') && $d[1] != ' ')) {
+ $this->_haveRefs[] =& $this->_allNodes[$node->id];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Finds and returns the indentation of a YAML line
+ *
+ * @param string $line A line from the YAML file
+ * @return int Indentation level
+ */
+ protected function _getIndent($line)
+ {
+ if (preg_match('/^\s+/', $line, $match)) {
+ return strlen($match[0]);
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Parses YAML code and returns an array for a node
+ *
+ * @param string $line A line from the YAML file
+ * @return array
+ */
+ protected function _parseLine($line)
+ {
+ $array = array();
+
+ $line = trim($line);
+ if (preg_match('/^-(.*):$/', $line)) {
+ // It's a mapped sequence
+ $key = trim(substr(substr($line, 1), 0, -1));
+ $array[$key] = '';
+ } elseif ($line[0] == '-' && substr($line, 0, 3) != '---') {
+ // It's a list item but not a new stream
+ if (strlen($line) > 1) {
+ // Set the type of the value. Int, string, etc
+ $array[] = $this->_toType(trim(substr($line, 1)));
+ } else {
+ $array[] = array();
+ }
+ } elseif (preg_match('/^(.+):/', $line, $key)) {
+ // It's a key/value pair most likely
+ // If the key is in double quotes pull it out
+ if (preg_match('/^(["\'](.*)["\'](\s)*:)/', $line, $matches)) {
+ $value = trim(str_replace($matches[1], '', $line));
+ $key = $matches[2];
+ } else {
+ // Do some guesswork as to the key and the value
+ $explode = explode(':', $line);
+ $key = trim(array_shift($explode));
+ $value = trim(implode(':', $explode));
+ }
+
+ // Set the type of the value. Int, string, etc
+ $value = $this->_toType($value);
+ if (empty($key)) {
+ $array[] = $value;
+ } else {
+ $array[$key] = $value;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Finds the type of the passed value, returns the value as the new type.
+ *
+ * @param string $value
+ * @return mixed
+ */
+ protected function _toType($value)
+ {
+ // Check for PHP specials
+ self::_unserialize($value);
+ if (!is_scalar($value)) {
+ return $value;
+ }
+
+ // Used in a lot of cases.
+ $lower_value = strtolower($value);
+
+ if (preg_match('/^("(.*)"|\'(.*)\')/', $value, $matches)) {
+ $value = (string)str_replace(array('\'\'', '\\\''), "'", end($matches));
+ $value = str_replace('\\"', '"', $value);
+ } elseif (preg_match('/^\\[(\s*)\\]$/', $value)) {
+ // empty inline mapping
+ $value = array();
+ } elseif (preg_match('/^\\[(.+)\\]$/', $value, $matches)) {
+ // Inline Sequence
+
+ // Take out strings sequences and mappings
+ $explode = $this->_inlineEscape($matches[1]);
+
+ // Propogate value array
+ $value = array();
+ foreach ($explode as $v) {
+ $value[] = $this->_toType($v);
+ }
+ } elseif (preg_match('/^\\{(\s*)\\}$/', $value)) {
+ // empty inline mapping
+ $value = array();
+ } elseif (strpos($value, ': ') !== false && !preg_match('/^{(.+)/', $value)) {
+ // inline mapping
+ $array = explode(': ', $value);
+ $key = trim($array[0]);
+ array_shift($array);
+ $value = trim(implode(': ', $array));
+ $value = $this->_toType($value);
+ $value = array($key => $value);
+ } elseif (preg_match("/{(.+)}$/", $value, $matches)) {
+ // Inline Mapping
+
+ // Take out strings sequences and mappings
+ $explode = $this->_inlineEscape($matches[1]);
+
+ // Propogate value array
+ $array = array();
+ foreach ($explode as $v) {
+ $array = $array + $this->_toType($v);
+ }
+ $value = $array;
+ } elseif ($lower_value == 'null' || $value == '' || $value == '~') {
+ $value = null;
+ } elseif ($lower_value == '.nan') {
+ $value = NAN;
+ } elseif ($lower_value == '.inf') {
+ $value = INF;
+ } elseif ($lower_value == '-.inf') {
+ $value = -INF;
+ } elseif (ctype_digit($value)) {
+ $value = (int)$value;
+ } elseif (in_array($lower_value,
+ array('true', 'on', '+', 'yes', 'y'))) {
+ $value = true;
+ } elseif (in_array($lower_value,
+ array('false', 'off', '-', 'no', 'n'))) {
+ $value = false;
+ } elseif (is_numeric($value)) {
+ $value = (float)$value;
+ } else {
+ // Just a normal string, right?
+ if (($pos = strpos($value, '#')) !== false) {
+ $value = substr($value, 0, $pos);
+ }
+ $value = trim($value);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Handle PHP serialized data.
+ *
+ * @param string &$data Data to check for serialized PHP types.
+ */
+ protected function _unserialize(&$data)
+ {
+ if (substr($data, 0, 5) != '!php/') {
+ return;
+ }
+
+ $first_space = strpos($data, ' ');
+ $type = substr($data, 5, $first_space - 5);
+ $class = null;
+ if (strpos($type, '::') !== false) {
+ list($type, $class) = explode('::', $type);
+
+ if (!in_array($class, Horde_Yaml::$allowedClasses)) {
+ throw new Horde_Yaml_Exception("$class is not in the list of allowed classes");
+ }
+ }
+
+ switch ($type) {
+ case 'object':
+ if (!class_exists($class)) {
+ throw new Horde_Yaml_Exception("$class is not defined");
+ }
+
+ $reflector = new ReflectionClass($class);
+ if (!$reflector->implementsInterface('Serializable')) {
+ throw new Horde_Yaml_Exception("$class does not implement Serializable");
+ }
+
+ $class_data = substr($data, $first_space + 1);
+ $serialized = 'C:' . strlen($class) . ':"' . $class . '":' . strlen($class_data) . ':{' . $class_data . '}';
+ $data = unserialize($serialized);
+ break;
+
+ case 'array':
+ case 'hash':
+ $array_data = substr($data, $first_space + 1);
+ $array_data = Horde_Yaml::load('a: ' . $array_data);
+
+ if (is_null($class)) {
+ $data = $array_data['a'];
+ } else {
+ if (!class_exists($class)) {
+ throw new Horde_Yaml_Exception("$class is not defined");
+ }
+
+ $array = new $class;
+ if (!$array instanceof ArrayAccess) {
+ throw new Horde_Yaml_Exception("$class does not implement ArrayAccess");
+ }
+
+ foreach ($array_data['a'] as $key => $val) {
+ $array[$key] = $val;
+ }
+
+ $data = $array;
+ }
+ break;
+ }
+ }
+
+ /**
+ * Used in inlines to check for more inlines or quoted strings
+ *
+ * @todo There should be a cleaner way to do this. While
+ * pure sequences seem to be nesting just fine,
+ * pure mappings and mappings with sequences inside
+ * can't go very deep. This needs to be fixed.
+ *
+ * @param string $inline Inline data
+ * @return array
+ */
+ protected function _inlineEscape($inline)
+ {
+ $saved_strings = array();
+
+ // Check for strings
+ $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
+ if (preg_match_all($regex, $inline, $strings)) {
+ $saved_strings = $strings[0];
+ $inline = preg_replace($regex, 'YAMLString', $inline);
+ }
+
+ // Check for sequences
+ if (preg_match_all('/\[(.+)\]/U', $inline, $seqs)) {
+ $inline = preg_replace('/\[(.+)\]/U', 'YAMLSeq', $inline);
+ $seqs = $seqs[0];
+ }
+
+ // Check for mappings
+ if (preg_match_all('/{(.+)}/U', $inline, $maps)) {
+ $inline = preg_replace('/{(.+)}/U', 'YAMLMap', $inline);
+ $maps = $maps[0];
+ }
+
+ $explode = explode(', ', $inline);
+
+ // Re-add the sequences
+ if (!empty($seqs)) {
+ $i = 0;
+ foreach ($explode as $key => $value) {
+ if (strpos($value, 'YAMLSeq') !== false) {
+ $explode[$key] = str_replace('YAMLSeq', $seqs[$i], $value);
+ ++$i;
+ }
+ }
+ }
+
+ // Re-add the mappings
+ if (!empty($maps)) {
+ $i = 0;
+ foreach ($explode as $key => $value) {
+ if (strpos($value, 'YAMLMap') !== false) {
+ $explode[$key] = str_replace('YAMLMap', $maps[$i], $value);
+ ++$i;
+ }
+ }
+ }
+
+ // Re-add the strings
+ if (!empty($saved_strings)) {
+ $i = 0;
+ foreach ($explode as $key => $value) {
+ while (strpos($value, 'YAMLString') !== false) {
+ $explode[$key] = preg_replace('/YAMLString/', $saved_strings[$i], $value, 1);
+ ++$i;
+ $value = $explode[$key];
+ }
+ }
+ }
+
+ return $explode;
+ }
+
+ /**
+ * Builds the PHP array from all the YAML nodes we've gathered
+ *
+ * @return array
+ */
+ protected function _buildArray()
+ {
+ $trunk = array();
+ if (!isset($this->_indentSort[0])) {
+ return $trunk;
+ }
+
+ foreach ($this->_indentSort[0] as $n) {
+ if (empty($n->parent)) {
+ $this->_nodeArrayizeData($n);
+
+ // Check for references and copy the needed data to complete them.
+ $this->_makeReferences($n);
+
+ // Merge our data with the big array we're building
+ $trunk = $this->_array_kmerge($trunk, $n->data);
+ }
+ }
+
+ return $trunk;
+ }
+
+ /**
+ * Traverses node-space and sets references (& and *) accordingly
+ *
+ * @return bool
+ */
+ protected function _linkReferences()
+ {
+ if (is_array($this->_haveRefs)) {
+ foreach ($this->_haveRefs as $node) {
+ if (!empty($node->data)) {
+ $key = key($node->data);
+ // If it's an array, don't check.
+ if (is_array($node->data[$key])) {
+ foreach ($node->data[$key] as $k => $v) {
+ $this->_linkRef($node, $key, $k, $v);
+ }
+ } else {
+ $this->_linkRef($node, $key);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Helper for _linkReferences()
+ *
+ * @param Horde_Yaml_Node $n Node
+ * @param string $k Key
+ * @param mixed $v Value
+ * @return void
+ */
+ function _linkRef(&$n, $key, $k = null, $v = null)
+ {
+ if (empty($k) && empty($v)) {
+ // Look for &refs
+ if (preg_match('/^&([^ ]+)/', $n->data[$key], $matches)) {
+ // Flag the node so we know it's a reference
+ $this->_allNodes[$n->id]->ref = substr($matches[0], 1);
+ $this->_allNodes[$n->id]->data[$key] =
+ substr($n->data[$key], strlen($matches[0]) + 1);
+ // Look for *refs
+ } elseif (preg_match('/^\*([^ ]+)/', $n->data[$key], $matches)) {
+ $ref = substr($matches[0], 1);
+ // Flag the node as having a reference
+ $this->_allNodes[$n->id]->refKey = $ref;
+ }
+ } elseif (!empty($k) && !empty($v)) {
+ if (preg_match('/^&([^ ]+)/', $v, $matches)) {
+ // Flag the node so we know it's a reference
+ $this->_allNodes[$n->id]->ref = substr($matches[0], 1);
+ $this->_allNodes[$n->id]->data[$key][$k] =
+ substr($v, strlen($matches[0]) + 1);
+ // Look for *refs
+ } elseif (preg_match('/^\*([^ ]+)/', $v, $matches)) {
+ $ref = substr($matches[0], 1);
+ // Flag the node as having a reference
+ $this->_allNodes[$n->id]->refKey = $ref;
+ }
+ }
+ }
+
+ /**
+ * Finds the children of a node and aids in the building of the PHP array
+ *
+ * @param int $nid The id of the node whose children we're gathering
+ * @return array
+ */
+ protected function _gatherChildren($nid)
+ {
+ $return = array();
+ $node =& $this->_allNodes[$nid];
+ if (is_array ($this->_allParent[$node->id])) {
+ foreach ($this->_allParent[$node->id] as $nodeZ) {
+ $z =& $this->_allNodes[$nodeZ];
+ // We found a child
+ $this->_nodeArrayizeData($z);
+
+ // Check for references
+ $this->_makeReferences($z);
+
+ // Merge with the big array we're returning, the big
+ // array being all the data of the children of our
+ // parent node
+ $return = $this->_array_kmerge($return, $z->data);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Turns a node's data and its children's data into a PHP array
+ *
+ * @param array $node The node which you want to arrayize
+ * @return boolean
+ */
+ protected function _nodeArrayizeData(&$node)
+ {
+ if ($node->children == true) {
+ if (is_array($node->data)) {
+ // This node has children, so we need to find them
+ $children = $this->_gatherChildren($node->id);
+
+ // We've gathered all our children's data and are ready to use it
+ $key = key($node->data);
+ $key = empty($key) ? 0 : $key;
+ // If it's an array, add to it of course
+ if (isset($node->data[$key])) {
+ if (is_array($node->data[$key])) {
+ $node->data[$key] = $this->_array_kmerge($node->data[$key], $children);
+ } else {
+ $node->data[$key] = $children;
+ }
+ } else {
+ $node->data[$key] = $children;
+ }
+ } else {
+ // Same as above, find the children of this node
+ $children = $this->_gatherChildren($node->id);
+ $node->data = array();
+ $node->data[] = $children;
+ }
+ } else {
+ // The node is a single string. See if we need to unserialize it.
+ if (is_array($node->data)) {
+ $key = key($node->data);
+ $key = empty($key) ? 0 : $key;
+
+ if (!isset($node->data[$key]) || is_array($node->data[$key]) || is_object($node->data[$key])) {
+ return true;
+ }
+
+ self::_unserialize($node->data[$key]);
+ } elseif (is_string($node->data)) {
+ self::_unserialize($node->data);
+ }
+ }
+
+ // We edited $node by reference, so just return true
+ return true;
+ }
+
+ /**
+ * Traverses node-space and copies references to / from this object.
+ *
+ * @param Horde_Yaml_Node $z A node whose references we wish to make real
+ * @return bool
+ */
+ protected function _makeReferences(&$z)
+ {
+ // It is a reference
+ if (isset($z->ref)) {
+ $key = key($z->data);
+ // Copy the data to this object for easy retrieval later
+ $this->ref[$z->ref] =& $z->data[$key];
+ // It has a reference
+ } elseif (isset($z->refKey)) {
+ if (isset($this->ref[$z->refKey])) {
+ $key = key($z->data);
+ // Copy the data from this object to make the node a real reference
+ $z->data[$key] =& $this->ref[$z->refKey];
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Merges two arrays, maintaining numeric keys. If two numeric
+ * keys clash, the second one will be appended to the resulting
+ * array. If string keys clash, the last one wins.
+ *
+ * @param array $arr1
+ * @param array $arr2
+ * @return array
+ */
+ protected function _array_kmerge($arr1, $arr2)
+ {
+ while (list($key, $val) = each($arr2)) {
+ if (isset($arr1[$key]) && is_int($key)) {
+ $arr1[] = $val;
+ } else {
+ $arr1[$key] = $val;
+ }
+ }
+
+ return $arr1;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Horde YAML package
+ *
+ * This package is heavily inspired by the Spyc PHP YAML
+ * implementation (http://spyc.sourceforge.net/), and portions are
+ * copyright 2005-2006 Chris Wanstrath.
+ *
+ * @author Chris Wanstrath <chris@ozmm.org>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ */
+
+/**
+ * A node, used for parsing YAML.
+ *
+ * @category Horde
+ * @package Horde_Yaml
+ */
+class Horde_Yaml_Node
+{
+ /**
+ * @var string
+ */
+ public $parent;
+
+ /**
+ */
+ public $id;
+
+ /**
+ * @var mixed
+ */
+ public $data;
+
+ /**
+ * @var integer
+ */
+ public $indent;
+
+ /**
+ * @var bool
+ */
+ public $children = false;
+
+ /**
+ * The constructor assigns the node a unique ID.
+ * @return void
+ */
+ public function __construct($nodeId)
+ {
+ $this->id = $nodeId;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Yaml</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde YAML parsing and dumping routines</summary>
+ <description>This package provides classes for parsing YAML files
+ into PHP arrays, and dumping PHP arrays into YAML encoding.
+ </description>
+ <lead>
+ <name>Chuck Hagenbuch</name>
+ <user>chuck</user>
+ <email>chuck@horde.org</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Mike Naberezny</name>
+ <user>mnaberez</user>
+ <email>mike@maintainable.com</email>
+ <active>yes</active>
+ </lead>
+ <date>2008-01-06</date>
+ <version>
+ <release>1.0.1</release>
+ <api>1.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://opensource.org/licenses/bsd-license.php">BSD</license>
+ <notes>
+ * Fix extra spaces at the end of lines that have been unfolded.
+ * Support dumping and loading PHP classes that implement Serializable
+ * Support loading serialized ArrayObject and other !php constructs
+ supported by pecl/syck
+ </notes>
+ <contents>
+ <dir name="/">
+ <dir name="lib">
+ <dir name="Horde">
+ <dir name="Yaml">
+ <file name="Dumper.php" role="php" />
+ <file name="Exception.php" role="php" />
+ <file name="Loader.php" role="php" />
+ <file name="Node.php" role="php" />
+ </dir> <!-- /lib/Horde/Yaml -->
+ <file name="Yaml.php" role="php" />
+ </dir> <!-- /lib/Horde -->
+ </dir> <!-- /lib -->
+ </dir> <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.1.0</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0b1</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <phprelease>
+ <filelist>
+ <install name="lib/Horde/Yaml/Dumper.php" as="Horde/Yaml/Dumper.php" />
+ <install name="lib/Horde/Yaml/Exception.php" as="Horde/Yaml/Exception.php" />
+ <install name="lib/Horde/Yaml/Loader.php" as="Horde/Yaml/Loader.php" />
+ <install name="lib/Horde/Yaml/Node.php" as="Horde/Yaml/Node.php" />
+ <install name="lib/Horde/Yaml.php" as="Horde/Yaml.php" />
+ </filelist>
+ </phprelease>
+</package>
--- /dev/null
+D/Horde////
--- /dev/null
+framework/Yaml/test
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+D/Yaml////
--- /dev/null
+framework/Yaml/test/Horde
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+<?php
+/**
+ * Horde_Yaml test suite
+ *
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+ define('PHPUnit_MAIN_METHOD', 'Horde_Yaml_AllTests::main');
+}
+
+require_once 'PHPUnit/Framework/TestSuite.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+/**
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_AllTests {
+
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ // Catch strict standards
+ error_reporting(E_ALL | E_STRICT);
+
+ // Set up autoload
+ set_include_path(dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . 'lib' . PATH_SEPARATOR . get_include_path());
+ if (!spl_autoload_functions()) {
+ spl_autoload_register(create_function('$class', '$filename = str_replace(array(\'::\', \'_\'), \'/\', $class); @include_once "$filename.php";'));
+ }
+
+ // Test helpers
+ require_once dirname(__FILE__) . '/Helpers.php';
+
+ $suite = new PHPUnit_Framework_TestSuite('Horde Framework - Horde_Yaml');
+
+ $basedir = dirname(__FILE__);
+ $baseregexp = preg_quote($basedir . DIRECTORY_SEPARATOR, '/');
+
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basedir)) as $file) {
+ if ($file->isFile() && preg_match('/Test.php$/', $file->getFilename())) {
+ $pathname = $file->getPathname();
+ require $pathname;
+
+ $class = str_replace(DIRECTORY_SEPARATOR, '_',
+ preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname));
+ $suite->addTestSuite('Horde_Yaml_' . $class);
+ }
+ }
+
+ return $suite;
+ }
+
+}
+
+if (PHPUnit_MAIN_METHOD == 'Horde_Yaml_AllTests::main') {
+ Horde_Yaml_AllTests::main();
+}
--- /dev/null
+/AllTests.php/1.2/Wed Jun 18 19:05:26 2008//
+/DumperTest.php/1.2/Wed Jun 18 19:05:26 2008//
+/Helpers.php/1.2/Wed Jun 18 19:05:26 2008//
+/LoaderTest.php/1.2/Wed Jun 18 19:05:26 2008//
+/NodeTest.php/1.2/Wed Jun 18 19:05:26 2008//
+D/fixtures////
--- /dev/null
+framework/Yaml/test/Horde/Yaml
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+<?php
+/**
+ * Horde_Yaml_Node test
+ *
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+
+/**
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_DumperTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->dumper = new Horde_Yaml_Dumper();
+ }
+
+ // Pass-thru in Horde_Yaml
+
+ public function testPassThruConvenienceFunction()
+ {
+ $value = array();
+
+ // Disable any external dumper function
+ $oldDumpFunc = Horde_Yaml::$dumpfunc;
+ Horde_Yaml::$dumpfunc = false;
+
+ $expected = $this->dumper->dump($value);
+ $actual = Horde_Yaml::dump($value);
+
+ // Restore the dumper function
+ Horde_Yaml::$dumpfunc = $oldDumpFunc;
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Argument checking
+
+ public function testThrowsWhenOptionsIsNotArray()
+ {
+ $options = 42;
+ try {
+ $this->dumper->dump(array(), $options);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/options.*array/i', $e->getMessage());
+ }
+ }
+
+ public function testThrowsWhenOptionIndentIsNotAnInteger()
+ {
+ $options = array('indent' => 'foo');
+ try {
+ $this->dumper->dump(array(), $options);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/indent.*integer/i', $e->getMessage());
+ }
+ }
+
+ public function testThrowsWhenOptionWordwrapIsNotAnInteger()
+ {
+ $options = array('wordwrap' => 'foo');
+ try {
+ $this->dumper->dump(array(), $options);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/wordwrap.*integer/i', $e->getMessage());
+ }
+ }
+
+ // Dumping
+
+ public function testDumpAlwaysStartsNewYamlDocument()
+ {
+ $dump = $this->dumper->dump(array());
+ $this->assertRegExp("/^---\n/", $dump);
+ }
+
+ public function testNumericStrings()
+ {
+ $value = array('foo' => '73,123');
+ $this->assertSame($value, Horde_Yaml::load(Horde_Yaml::dump($value)));
+ }
+
+ public function testDumpsArrayAsMap()
+ {
+ $value = array('foo' => 'bar');
+
+ $expected = "---\nfoo: bar\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDumpsTraversableAsMap()
+ {
+ $value = new ArrayObject(array('foo' => 'bar'));
+
+ $expected = "---\nfoo: bar\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testMovedArray()
+ {
+ return $this->markTestSkipped();
+
+ $arr = array_flip(range(1, 1000));
+ $string = $this->dumper->dump($arr);
+ $arr2 = Horde_Yaml::load($string);
+
+ $this->assertEquals($arr, $arr2);
+ }
+
+ public function testMixedArray()
+ {
+ $arr = array('test', 'a' => 'test2', 'test3');
+
+ $string = $this->dumper->dump($arr);
+ $arr2 = Horde_Yaml::load($string);
+
+ $this->assertEquals($arr2, $arr);
+ }
+
+ public function testNegativeKeysArray()
+ {
+ $this->markTestSkipped();
+
+ $arr = array(-1 => 'test', -2 => 'test2', 0 => 'test3');
+
+ $string = $this->dumper->dump($arr);
+ $arr2 = Horde_Yaml::load($string);
+
+ $this->assertEquals($arr, $arr2);
+ }
+
+ public function testInfinity()
+ {
+ $value = array('foo' => INF);
+
+ $expected = "---\nfoo: .INF\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testNegativeInfinity()
+ {
+ $value = array('foo' => -INF);
+
+ $expected = "---\nfoo: -.INF\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testNan()
+ {
+ $value = array('foo' => NAN);
+
+ $expected = "---\nfoo: .NAN\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testSerializable()
+ {
+ $value = array('obj' => new Horde_Yaml_Test_Serializable('s'));
+
+ $expected = "---\nobj: >\n !php/object::Horde_Yaml_Test_Serializable\n s\n";
+ $actual = $this->dumper->dump($value);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDumpSequence()
+ {
+ $value = array('foo', 'bar');
+
+ $expected = "---\n"
+ . "- foo\n"
+ . "- bar\n";
+ $actual = $this->dumper->dump($value);
+
+ $this->assertEquals($expected, $actual);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Horde_Yaml test helpers
+ *
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+
+/**
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_Test_Serializable implements Serializable
+{
+ private $string = null;
+
+ public function __construct($string = null)
+ {
+ if (null === $string)
+ throw new Exception('This is not supposed to be called implicitly');
+
+ $this->string = $string;
+ }
+
+ public function serialize()
+ {
+ return $this->string;
+ }
+
+ public function unserialize($serialized)
+ {
+ $this->string = $serialized;
+ }
+
+ public function test()
+ {
+ return $this->string;
+ }
+
+}
+
+class Horde_Yaml_Test_NotSerializable
+{}
--- /dev/null
+<?php
+/**
+ * Horde_Yaml_Loader test
+ *
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+
+/**
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_LoaderTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ Horde_Yaml::$loadfunc = 'nonexistant_callback';
+ }
+
+ // Loading: load()
+
+ public function testLoad()
+ {
+ $expected = array('foo' => 'bar');
+ $actual = Horde_Yaml::load('foo: bar');
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testLoadUsesCallbackForParsingIfAvailable()
+ {
+ Horde_Yaml::$loadfunc = 'Horde_Yaml_LoaderTest_MockLoader::returnArray';
+
+ $yaml = 'foo';
+ $expected = Horde_Yaml_LoaderTest_MockLoader::returnArray($yaml);
+ $actual = Horde_Yaml::load($yaml);
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testLoadThrowsWhenInputStringIsNotString()
+ {
+ $notString = 42;
+ try {
+ Horde_Yaml::load($notString);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/must be a string/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadThrowsWhenInputStringIsEmpty()
+ {
+ $emptyString = '';
+ try {
+ Horde_Yaml::load($emptyString);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/cannot be empty/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadReturnsEmptyArrayWhenStringCannotBeParsedAsYaml()
+ {
+ $notYaml = 'notyaml';
+ $this->assertEquals(array(), Horde_Yaml::load($notYaml));
+ }
+
+ // Loading: loadFile()
+
+ public function testLoadFile()
+ {
+ $parsed = Horde_Yaml::loadFile($this->fixture('basic'));
+ $this->assertEquals('bar', $parsed['foo']);
+ }
+
+ public function testLoadFileThrowsWhenFilenameIsNotString()
+ {
+ $notString = 42;
+ try {
+ Horde_Yaml::loadFile($notString);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/must be a string/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadFileThrowsWhenFilenameIsEmptyString()
+ {
+ $emptyString = '';
+ try {
+ Horde_Yaml::loadFile($emptyString);
+ $this->fail();
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/cannot be empty/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadFileThrowsWhenFilenameCannotBeOpened()
+ {
+ $nonexistant = '/path/to/a/nonexistant/filename';
+ try {
+ Horde_Yaml::loadFile($nonexistant);
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertRegExp('/failed to open/i', $e->getMessage());
+ }
+ }
+
+ // Loading: loadStream()
+
+ public function testLoadStream()
+ {
+ $fp = fopen($this->fixture('basic'), 'rb');
+ $parsed = Horde_Yaml::loadStream($fp);
+ $this->assertEquals('bar', $parsed['foo']);
+ }
+
+ public function testLoadStreamThrowsWhenStreamIsNotResource()
+ {
+ $notResource = 42;
+ try {
+ Horde_Yaml::loadStream($notResource);
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/stream resource/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadStreamThrowsWhenStreamIsResourceButNotStream()
+ {
+ $resourceButNotStream = xml_parser_create();
+ $this->assertType('resource', $resourceButNotStream);
+
+ try {
+ Horde_Yaml::loadStream($resourceButNotStream);
+ } catch (InvalidArgumentException $e) {
+ $this->assertRegExp('/stream resource/i', $e->getMessage());
+ }
+ }
+
+ public function testLoadStreamUsesCallbackForParsingIfAvailable()
+ {
+ Horde_Yaml::$loadfunc = 'Horde_Yaml_LoaderTest_MockLoader::returnArray';
+
+ $stream = fopen('php://memory', 'r');
+ $expected = Horde_Yaml_LoaderTest_MockLoader::returnArray($stream);
+ $actual = Horde_Yaml::loadStream($stream);
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Parsing: Mappings
+
+ public function testMappingStringValue()
+ {
+ $yaml = "String: Anyone's name, really.";
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertEquals("Anyone's name, really.", $parsed['String']);
+ }
+
+ public function testMappingIntegerValue()
+ {
+ $yaml = 'Int: 13';
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertEquals(13, $parsed['Int']);
+ }
+
+ public function testMappingIntegerZeroValue()
+ {
+ $yaml = 'Zero: 0';
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertSame(0, $parsed['Zero']);
+ }
+
+ public function testMappingFloatValue()
+ {
+ $yaml = 'Float: 5.34';
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertEquals(5.34, $parsed['Float']);
+ }
+
+ public function testMappingBooleanTrue()
+ {
+ $trues = array('TRUE', 'True', 'true', 'On', 'on', '+', 'YES', 'Yes', 'yes');
+ foreach ($trues as $true) {
+ $yaml = "True: $true";
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertTrue($parsed['True'], $true);
+ }
+ }
+
+ public function testMappingBooleanFalse()
+ {
+ $falses = array('FALSE', 'False', 'false', 'Off', 'off', '-', 'NO', 'No', 'no');
+ foreach ($falses as $false) {
+ $yaml = "False: $false";
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertFalse($parsed['False'], $false);
+ }
+ }
+
+ public function testMappingNullValue()
+ {
+ $nulls = array('NULL', 'Null', 'null', '', '~');
+ foreach ($nulls as $null) {
+ $yaml = "Null: $null";
+ $parsed = Horde_Yaml::load($yaml);
+ $this->assertNull($parsed['Null'], $null);
+ }
+ }
+
+ public function testMappedValueWithFoldedBlock()
+ {
+ $parsed = Horde_Yaml::loadFile($this->fixture('basic'));
+
+ $expected = "There isn't any time for your tricks!\nDo you understand?\n";
+ $actual = $parsed['no time'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testMappedValueWithMapping()
+ {
+ $yaml = "foo:\n"
+ . " bar: baz";
+ $expected = array('foo' => array('bar' => 'baz'));
+ $actual = Horde_Yaml::load($yaml);
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Parsing: Types
+
+ public function testFloatExponential()
+ {
+ $this->assertSame(array('e' => 10.0), Horde_Yaml::load('e: 1.0e+1'));
+ $this->assertSame(array('e' => 0.1), Horde_Yaml::load('e: 1.0e-1'));
+ }
+
+ public function testInfinity()
+ {
+ $this->assertSame(array('i' => INF), Horde_Yaml::load('i: .inf'));
+ $this->assertSame(array('i' => INF), Horde_Yaml::load('i: .Inf'));
+ $this->assertSame(array('i' => INF), Horde_Yaml::load('i: .INF'));
+ }
+
+ public function testNegativeInfinity()
+ {
+ $this->assertSame(array('i' => -INF), Horde_Yaml::load('i: -.inf'));
+ $this->assertSame(array('i' => -INF), Horde_Yaml::load('i: -.Inf'));
+ $this->assertSame(array('i' => -INF), Horde_Yaml::load('i: -.INF'));
+ }
+
+ public function testNan()
+ {
+ // NAN !== NAN, but NAN == NAN
+ $this->assertEquals(array('n' => NAN), Horde_Yaml::load('n: .nan'));
+ $this->assertEquals(array('n' => NAN), Horde_Yaml::load('n: .NaN'));
+ $this->assertEquals(array('n' => NAN), Horde_Yaml::load('n: .NAN'));
+ }
+
+ public function testArray()
+ {
+ $this->assertEquals(array('a' => array()), Horde_Yaml::load('a: []'));
+ $this->assertEquals(array('a' => array('a', 'b', 'c')), Horde_Yaml::load('a: [a, b, c]'));
+ $this->assertEquals(array('a' => array()), Horde_Yaml::load('a: !php/array []'));
+
+ // ArrayObject implements ArrayAccess: OK
+ $this->assertEquals(array('ao' => new ArrayObject()), Horde_Yaml::load('ao: !php/array::ArrayObject []'));
+ $this->assertEquals(array('ao' => new ArrayObject(array(1, 2, 3))), Horde_Yaml::load('ao: !php/array::ArrayObject [1, 2, 3]'));
+
+ // Horde_Yaml_Test_NotSerializable doesn't implement ArrayAccess: FAILURE
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_NotSerializable';
+ try {
+ Horde_Yaml::load('array: !php/array::Horde_Yaml_Test_NotSerializable []');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_NotSerializable does not implement ArrayAccess', $e->getMessage());
+ }
+
+ // Horde_Yaml_Test_OtherClass doesn't exist: FAILURE
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_OtherClass';
+ try {
+ Horde_Yaml::load('array: !php/array::Horde_Yaml_Test_OtherClass []');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_OtherClass is not defined', $e->getMessage());
+ }
+
+ // Horde_Yaml_Test_Disallowed is not whitelisted
+ try {
+ Horde_Yaml::load('array: !php/array::Horde_Yaml_Test_Disallowed []');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_Disallowed is not in the list of allowed classes', $e->getMessage());
+ }
+ }
+
+ public function testHash()
+ {
+ $this->assertEquals(array('a' => array()), Horde_Yaml::load('a: {}'));
+ $this->assertEquals(array('a' => array('a', 'b', 'c')), Horde_Yaml::load('a: {0: a, 1: b, 2: c}'));
+
+ // ArrayObject implements ArrayAccess: OK
+ $this->assertEquals(array('ao' => new ArrayObject()), Horde_Yaml::load('ao: !php/hash::ArrayObject {}'));
+ $this->assertEquals(
+ array('ao' => new ArrayObject(array('a' => 1, 'b' => 2, 3 => 3, 4 => 'd', 'e' => 5))),
+ Horde_Yaml::load('ao: !php/hash::ArrayObject {a: 1, b: 2, 3: 3, 4: d, e: 5}')
+ );
+
+ // Horde_Yaml_Test_NotSerializable doesn't implement ArrayAccess: FAILURE
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_NotSerializable';
+ try {
+ Horde_Yaml::load('hash: !php/hash::Horde_Yaml_Test_NotSerializable {}');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_NotSerializable does not implement ArrayAccess', $e->getMessage());
+ }
+
+ // Horde_Yaml_Test_OtherClass doesn't exist: FAILURE
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_OtherClass';
+ try {
+ Horde_Yaml::load('hash: !php/hash::Horde_Yaml_Test_OtherClass {}');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_OtherClass is not defined', $e->getMessage());
+ }
+
+ // Horde_Yaml_Test_Disallowed is not whitelisted
+ try {
+ Horde_Yaml::load('hash: !php/hash::Horde_Yaml_Test_Disallowed []');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_Disallowed is not in the list of allowed classes', $e->getMessage());
+ }
+ }
+
+ public function testSerializable()
+ {
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_Serializable';
+ $result = Horde_Yaml::load('obj: >
+ !php/object::Horde_Yaml_Test_Serializable
+ string');
+
+ $this->assertType('Horde_Yaml_Test_Serializable', $result['obj']);
+ $this->assertSame('string', $result['obj']->test());
+
+ // Horde_Yaml_Test_NotSerializable doesn't implement Serializable: FAILURE
+ Horde_Yaml::$allowedClasses[] = 'Horde_Yaml_Test_NotSerializable';
+ try {
+ Horde_Yaml::load('o: !php/object::Horde_Yaml_Test_NotSerializable string');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_NotSerializable does not implement Serializable', $e->getMessage());
+ }
+
+ // Horde_Yaml_Test_Disallowed is not whitelisted
+ try {
+ Horde_Yaml::load('o: !php/object::Horde_Yaml_Test_Disallowed string');
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertEquals('Horde_Yaml_Test_Disallowed is not in the list of allowed classes', $e->getMessage());
+ }
+ }
+
+ // Parsing: Sequences
+
+ public function testSequenceBasic()
+ {
+ $yaml = "- PHP Class\n"
+ . "- Basic YAML Loader\n"
+ . "- Very Basic YAML Dumper";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertEquals("PHP Class", $parsed[0]);
+ $this->assertEquals("Basic YAML Loader", $parsed[1]);
+ $this->assertEquals("Very Basic YAML Dumper", $parsed[2]);
+ }
+
+ public function testSequenceOfSequence()
+ {
+ $yaml = "-\n"
+ . " - YAML is so easy to learn.\n"
+ . " - Your config files will never be the same.";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("YAML is so easy to learn.",
+ "Your config files will never be the same.");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testSequenceofMappings()
+ {
+ $yaml = "-\n"
+ . " cpu: 1.5ghz\n"
+ . " ram: 1 gig\n"
+ . " os : os x 10.4.1";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("cpu" => "1.5ghz", "ram" => "1 gig", "os" => "os x 10.4.1");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual, 'Sequence of mappings');
+ }
+
+ public function testMappedSequence()
+ {
+ $yaml = "domains:\n"
+ . " - yaml.org\n"
+ . " - php.net\n";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("yaml.org", "php.net");
+ $actual = $parsed['domains'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testSequenceWithMappedValuesStartingWithCaps()
+ {
+ $yaml = "- program: Adium\n"
+ . " platform: OS X\n"
+ . " type: Chat Client\n";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("program" => "Adium", "platform" => "OS X", "type" => "Chat Client");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Parsing: References
+
+ public function testReferencesAssignment1()
+ {
+ $parsed = Horde_Yaml::loadFile($this->fixture('references'));
+
+ $expected = array('Perl', 'Python', 'PHP', 'Ruby');
+ $actual = $parsed['dynamic languages'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testReferencesAssignment2()
+ {
+ $parsed = Horde_Yaml::loadFile($this->fixture('references'));
+
+ $expected = array('C/C++', 'Java');
+ $actual = $parsed['compiled languages'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testReferenceUsage()
+ {
+ $parsed = Horde_Yaml::loadFile($this->fixture('references'));
+
+ $assignment1 = array('Perl', 'Python', 'PHP', 'Ruby');
+ $assignment2 = array('C/C++', 'Java');
+
+ $expected = array($assignment1, $assignment2);
+ $actual = $parsed['all languages'];
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Parsing: Inlines
+
+ public function testInlinedSequence()
+ {
+ $yaml = '- [One, Two, Three, Four]';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("One", "Two", "Three", "Four");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineSequenceWithQuotes()
+ {
+ $yaml = "- ['complex: string', 'another [string]']";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array('complex: string', 'another [string]');
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineSequenceOneDeep()
+ {
+ $yaml = '- [One, [Two, And, Three], Four, Five]';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("One", array("Two", "And", "Three"), "Four", "Five");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineSequenceOneDeepWithQuotes()
+ {
+ $yaml = '- [a, [\'1\', "2"], b]';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array('a', array('1', '2'), 'b');
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineSequenceTwoDeep()
+ {
+ $yaml = '- [This, [Is, Getting, [Ridiculous, Guys]], Seriously, [Show, Mercy]]';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("This", array("Is", "Getting", array("Ridiculous", "Guys")),
+ "Seriously", array("Show", "Mercy"));
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineSequenceWhenEmpty()
+ {
+ $yaml = '- []';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array();
+ $actual = $parsed[0];
+ $this->assertEquals($actual, $expected);
+ }
+
+ public function testInlineSequenceWhenEmptyWithWhitespace()
+ {
+ $yaml = "- [ \t]";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array();
+ $actual = $parsed[0];
+ $this->assertEquals($actual, $expected);
+ }
+
+ public function testInlineMapping()
+ {
+ $yaml = '- {name: chris, age: young, brand: lucky strike}';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("name" => "chris", "age" => "young", "brand" => "lucky strike");
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineMappingWhenEmpty()
+ {
+ $yaml = '- {}';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array();
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineMappingWhenEmptyWithWhitespace()
+ {
+ $yaml = "- { \t}";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array();
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineMappingWithQuotesInlinedInSequence()
+ {
+ $yaml = '- {name: "Foo, Bar\'s", age: 20}';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array('name' => "Foo, Bar's", 'age' => 20);
+ $actual = $parsed[0];
+
+ $this->assertEquals($expected, $actual);
+ }
+
+
+ public function testInlineMappingWithQuotesInlinedInMapping()
+ {
+ $yaml = 'outer: { inner1: "foo bar", inner2: \'baz qux\' }';
+
+ $expected = array('outer' => array('inner1' => "foo bar", 'inner2' => "baz qux"));
+ $actual = Horde_Yaml::load($yaml);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testInlineMappingOneDeep()
+ {
+ $yaml = "- {name: mark, age: older than chris, brand: [marlboro, lucky strike]}";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = array("name" => "mark", "age" => "older than chris",
+ "brand" => array("marlboro", "lucky strike"));
+ $actual = $parsed[0];
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Parsing: Quotes
+
+ public function testQuotesCanBeEscaped()
+ {
+ $yaml = "- one'apostrophe on line\n"
+ . "- two'apostrophes' on line\n"
+ . "- one\"quote on line\n"
+ . "- two\"quotes\" on line\n";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertEquals("one'apostrophe on line",
+ $parsed[0]);
+
+ $this->assertEquals("two'apostrophes' on line",
+ $parsed[1]);
+
+ $this->assertEquals('one"quote on line',
+ $parsed[2]);
+
+ $this->assertEquals('two"quotes" on line',
+ $parsed[3]);
+ }
+
+ public function testQuotesCanBeUsedForComplexKeys()
+ {
+ $yaml = '"if: you\'d": like';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertEquals("like", $parsed["if: you'd"]);
+ }
+
+ public function testQuotesCanBeEmptyWhenQuotes()
+ {
+ $yaml = 'empty: ""';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertSame('', $parsed['empty']);
+ }
+
+ public function testQuotesCanBeEmptyWhenApostrophes()
+ {
+ $yaml = "empty: ''";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertSame('', $parsed['empty']);
+ }
+
+ public function testWhitespaceBetweenQuotesIsPreserved()
+ {
+ $yaml = 'empty: " "';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertSame(' ', $parsed['empty']);
+ }
+
+ public function testWhitespaceBetweenApostrophesIsPreserved()
+ {
+ $yaml = "empty: ' '";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertSame(' ', $parsed['empty']);
+ }
+
+ // Parsing: Keys
+
+ public function testKeyAsNumeric()
+ {
+ // Added in Spyc .2
+ $yaml = '1040: Ooo, a numeric key! # And working comments? Wow!';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $this->assertEquals("Ooo, a numeric key!", $parsed[1040]);
+ }
+
+ // Tab Detection
+
+ public function testThrowsAnExceptionWhenFirstCharacterOfLineIsTab()
+ {
+ try {
+ Horde_Yaml::load("\tfoo: bar");
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertRegExp('/indent contains a tab/i', $e->getMessage());
+ }
+ }
+
+ public function testThrowsExceptionWhenLineIndentContainsTab()
+ {
+ try {
+ Horde_Yaml::load(" \tfoo: bar");
+ $this->fail();
+ } catch (Horde_Yaml_Exception $e) {
+ $this->assertRegExp('/indent contains a tab/i', $e->getMessage());
+ }
+ }
+
+ public function testDoesNotThrowOnAnEmptyLineWithTabsOrSpaces()
+ {
+ Horde_Yaml::load(" ");
+ Horde_Yaml::load("\t");
+ Horde_Yaml::load(" \t");
+ Horde_Yaml::load("\t ");
+ }
+
+ // Comments
+
+ public function testCommentOnEmptyLine()
+ {
+ $yaml = "# foo\nbar: baz";
+ $expected = array('bar' => 'baz');
+ $actual = Horde_Yaml::load($yaml);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testCommentAtEndOfLine()
+ {
+ $yaml = 'foo: bar # baz';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = 'bar';
+ $actual = $parsed['foo'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDecoyCommentEmbeddedInQuotes()
+ {
+ $yaml = 'foo: "bar # baz"';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = 'bar # baz';
+ $actual = $parsed['foo'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDecoyCommentEmbeddedInQuotesAndEndOfLineComment()
+ {
+ $yaml = 'foo: "bar # baz" # qux';
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = 'bar # baz';
+ $actual = $parsed['foo'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDecoyCommentEmbeddedInApostrophes()
+ {
+ $yaml = "foo: 'bar # baz'";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = 'bar # baz';
+ $actual = $parsed['foo'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testDecoyCommentEmbeddedInApostrophesAndEndOfLineVersion()
+ {
+ $yaml = "foo: 'bar # baz' # qux";
+ $parsed = Horde_Yaml::load($yaml);
+
+ $expected = 'bar # baz';
+ $actual = $parsed['foo'];
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Misc
+
+ public function testComplexParse()
+ {
+ $yaml = "databases:\n"
+ . " - name: spartan\n"
+ . " notes:\n"
+ . " - Needs to be backed up\n"
+ . " - Needs to be normalized\n"
+ . " type: mysql\n";
+
+ $expected = array('databases' => array(array('name' => 'spartan',
+ 'notes' => array('Needs to be backed up',
+ 'Needs to be normalized'),
+ 'type' => 'mysql')));
+ $actual = Horde_Yaml::load($yaml);
+ $this->assertEquals($expected, $actual);
+ }
+
+ // Test Helpers
+
+ public function fixture($name)
+ {
+ return dirname(__FILE__) . "/fixtures/{$name}.yml";
+ }
+
+}
+
+
+/**
+ * Used to test Horde_Yaml::$loadfunc callback.
+ *
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_LoaderTest_MockLoader
+{
+ public static function returnArray($yaml)
+ {
+ return array('loaded');
+ }
+
+ public static function returnFalse($yaml)
+ {
+ return false;
+ }
+}
--- /dev/null
+<?php
+/**
+ * Horde_Yaml_Node test
+ *
+ * @author Mike Naberezny <mike@maintainable.com>
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+
+/**
+ * @category Horde
+ * @package Horde_Yaml
+ * @subpackage UnitTests
+ */
+class Horde_Yaml_NodeTest extends PHPUnit_Framework_TestCase
+{
+ public function testConstructorAssignsId()
+ {
+ $id = 'foo';
+ $node = new Horde_Yaml_Node($id);
+ $this->assertEquals($id, $node->id);
+ }
+
+}
--- /dev/null
+/basic.yml/1.1/Wed Mar 5 20:37:57 2008//
+/references.yml/1.1/Wed Mar 5 20:37:57 2008//
+D
--- /dev/null
+framework/Yaml/test/Horde/Yaml/fixtures
--- /dev/null
+chuck@cvs.horde.org:/repository
--- /dev/null
+
+Bug:
+Submitted by:
+Merge after:
+CVS: ----------------------------------------------------------------------
+CVS: Bug: Fill this in if a listed bug is affected by the change.
+CVS: Submitted by: Fill this in if someone else sent in the change.
+CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default)
--- /dev/null
+foo: bar
+
+# A folded block as a mapped value
+no time: >
+ There isn't any time
+ for your tricks!
+
+ Do you understand?
+
+# A literal block as a mapped value
+some time: |
+ There is nothing but time
+ for your tricks.
+
--- /dev/null
+# References -- they're shaky, but functional
+dynamic languages: &DLANGS
+ - Perl
+ - Python
+ - PHP
+ - Ruby
+compiled languages: &CLANGS
+ - C/C++
+ - Java
+all languages:
+ - *DLANGS
+ - *CLANGS