Overview

Packages

  • Yaml

Classes

  • Horde_Yaml
  • Horde_Yaml_Dumper
  • Horde_Yaml_Exception
  • Horde_Yaml_Loader
  • Horde_Yaml_Node
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Horde YAML package
  4:  *
  5:  * This package is heavily inspired by the Spyc PHP YAML
  6:  * implementation (http://spyc.sourceforge.net/), and portions are
  7:  * copyright 2005-2006 Chris Wanstrath.
  8:  *
  9:  * @author   Chris Wanstrath <chris@ozmm.org>
 10:  * @author   Chuck Hagenbuch <chuck@horde.org>
 11:  * @author   Mike Naberezny <mike@maintainable.com>
 12:  * @license  http://www.horde.org/licenses/bsd BSD
 13:  * @category Horde
 14:  * @package  Yaml
 15:  */
 16: 
 17: /**
 18:  * Dump PHP data structures to YAML.
 19:  *
 20:  * @category Horde
 21:  * @package  Yaml
 22:  */
 23: class Horde_Yaml_Dumper
 24: {
 25:     protected $_options = array();
 26: 
 27:     /**
 28:      * Dump PHP array to YAML
 29:      *
 30:      * The dump method, when supplied with an array, will do its best
 31:      * to convert the array into valid YAML.
 32:      *
 33:      * Options:
 34:      *    `indent`:
 35:      *       number of spaces to indent children (default 2)
 36:      *    `wordwrap`:
 37:      *       wordwrap column number (default 40)
 38:      *
 39:      * @param  array|Traversable  $array     PHP array or traversable object
 40:      * @param  integer            $options   Options for dumping
 41:      * @return string                        YAML representation of $value
 42:      */
 43:     public function dump($value, $options = array())
 44:     {
 45:         // validate & merge default options
 46:         if (!is_array($options)) {
 47:             throw new InvalidArgumentException('Options must be an array');
 48:         }
 49: 
 50:         $defaults = array('indent'   => 2,
 51:                           'wordwrap' => 40);
 52:         $this->_options = array_merge($defaults, $options);
 53: 
 54:         if (! is_int($this->_options['indent'])) {
 55:             throw new InvalidArgumentException('Indent must be an integer');
 56:         }
 57: 
 58:         if (! is_int($this->_options['wordwrap'])) {
 59:             throw new InvalidArgumentException('Wordwrap column must be an integer');
 60:         }
 61: 
 62:         // new YAML document
 63:         $dump = "---\n";
 64: 
 65:         // iterate through array and yamlize it
 66:         foreach ($value as $key => $value) {
 67:             $dump .= $this->_yamlize($key, $value, 0);
 68:         }
 69:         return $dump;
 70:     }
 71: 
 72:     /**
 73:      * Attempts to convert a key / value array item to YAML
 74:      *
 75:      * @param  string        $key     The name of the key
 76:      * @param  string|array  $value   The value of the item
 77:      * @param  integer       $indent  The indent of the current node
 78:      * @return string
 79:      */
 80:     protected function _yamlize($key, $value, $indent)
 81:     {
 82:         if ($value instanceof Serializable) {
 83:             // Dump serializable objects as !php/object::classname serialize_data
 84:             $data = '!php/object::' . get_class($value) . ' ' . $value->serialize();
 85:             $string = $this->_dumpNode($key, $data, $indent);
 86:         } elseif (is_array($value) || $value instanceof Traversable) {
 87:             // It has children.  Make it the right kind of item.
 88:             $string = $this->_dumpNode($key, null, $indent);
 89: 
 90:             // Add the indent.
 91:             $indent += $this->_options['indent'];
 92: 
 93:             // Yamlize the array.
 94:             $string .= $this->_yamlizeArray($value, $indent);
 95:         } elseif (!is_array($value)) {
 96:             // No children.
 97:             $string = $this->_dumpNode($key, $value, $indent);
 98:         }
 99: 
100:         return $string;
101:     }
102: 
103:     /**
104:      * Attempts to convert an array to YAML
105:      *
106:      * @param  array    $array The array you want to convert
107:      * @param  integer  $indent The indent of the current level
108:      * @return string
109:      */
110:     protected function _yamlizeArray($array, $indent)
111:     {
112:         if (!is_array($array)) {
113:             return false;
114:         }
115: 
116:         $string = '';
117:         foreach ($array as $key => $value) {
118:             $string .= $this->_yamlize($key, $value, $indent);
119:         }
120:         return $string;
121:     }
122: 
123:     /**
124:      * Returns YAML from a key and a value
125:      *
126:      * @param  string   $key     The name of the key
127:      * @param  string   $value   The value of the item
128:      * @param  integer  $indent  The indent of the current node
129:      * @return string
130:      */
131:     protected function _dumpNode($key, $value, $indent)
132:     {
133:         $literal = false;
134:         // Do some folding here, for blocks.
135:         if (strpos($value, "\n") !== false
136:             || strpos($value, ': ') !== false
137:             || strpos($value, '- ') !== false) {
138:             $value = $this->_doLiteralBlock($value, $indent);
139:             $literal = true;
140:         } else {
141:             $value = $this->_fold($value, $indent);
142:         }
143: 
144:         if (is_bool($value)) {
145:             $value = ($value) ? 'true' : 'false';
146:         } elseif (is_float($value)) {
147:             if (is_nan($value)) {
148:                 $value = '.NAN';
149:             } elseif ($value === INF) {
150:                 $value = '.INF';
151:             } elseif ($value === -INF) {
152:                 $value = '-.INF';
153:             }
154:         }
155: 
156:         $spaces = str_repeat(' ', $indent);
157: 
158:         // Quote strings if necessary, and not folded
159:         if (!$literal && strpos($value, "\n") === false && strchr($value, '#')) {
160:             $value = "'{$value}'";
161:         }
162: 
163:         if (is_int($key)) {
164:             // It's a sequence.
165:             $string = $spaces . '- ' . $value . "\n";
166:         } else {
167:             // It's mapped.
168:             $string = $spaces . $key . ': ' . $value . "\n";
169:         }
170: 
171:         return $string;
172:     }
173: 
174:     /**
175:      * Creates a literal block for dumping
176:      *
177:      * @param  string   $value
178:      * @param  integer  $indent  The value of the indent.
179:      * @return string
180:      */
181:     protected function _doLiteralBlock($value, $indent)
182:     {
183:         $exploded = explode("\n", $value);
184:         $newValue = '|';
185:         $indent += $this->_options['indent'];
186:         $spaces = str_repeat(' ', $indent);
187:         foreach ($exploded as $line) {
188:             $newValue .= "\n" . $spaces . trim($line);
189:         }
190:         return $newValue;
191:     }
192: 
193:     /**
194:      * Folds a string of text, if necessary
195:      *
196:      * @param   $value   The string you wish to fold
197:      * @return  string
198:      */
199:     protected function _fold($value, $indent)
200:     {
201:         // Don't do anything if wordwrap is set to 0
202:         if (! $this->_options['wordwrap']) {
203:             return $value;
204:         }
205: 
206:         if (strlen($value) > $this->_options['wordwrap']) {
207:             $indent += $this->_options['indent'];
208:             $indent = str_repeat(' ', $indent);
209:             $wrapped = wordwrap($value, $this->_options['wordwrap'], "\n$indent");
210:             $value = ">\n" . $indent . $wrapped;
211:         }
212: 
213:         return $value;
214:     }
215: 
216: }
217: 
API documentation generated by ApiGen