root/modules/branches/2.5/core/XML_Unserializer.php

Revision 4538, 27.8 kB (checked in by p_lindheimer, 6 years ago)

#2070 fix bad use of <? with <?php

  • Property svn:mime-type set to text/html
  • Property svn:eol-style set to native
Line 
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4 /**
5  * XML_Unserializer
6  *
7  * Parses any XML document into PHP data structures.
8  *
9  * PHP versions 4 and 5
10  *
11  * LICENSE: This source file is subject to version 3.0 of the PHP license
12  * that is available through the world-wide-web at the following URI:
13  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
14  * the PHP License and are unable to obtain it through the web, please
15  * send a note to license@php.net so we can mail you a copy immediately.
16  *
17  * @category   XML
18  * @package    XML_Serializer
19  * @author     Stephan Schmidt <schst@php.net>
20  * @copyright  1997-2005 The PHP Group
21  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22  * @version    CVS: $Id: Unserializer.php,v 1.39 2005/09/28 11:19:56 schst Exp $
23  * @link       http://pear.php.net/package/XML_Serializer
24  * @see        XML_Unserializer
25  */
26
27 /**
28  * uses PEAR error managemt
29  */
30 //require_once 'PEAR.php';
31
32 /**
33  * uses XML_Parser to unserialize document
34  */
35 //require_once 'XML/Parser.php';
36
37 /**
38  * option: Convert nested tags to array or object
39  *
40  * Possible values:
41  * - array
42  * - object
43  * - associative array to define this option per tag name
44  */
45 define('XML_UNSERIALIZER_OPTION_COMPLEXTYPE', 'complexType');
46
47 /**
48  * option: Name of the attribute that stores the original key
49  *
50  * Possible values:
51  * - any string
52  */
53 define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY', 'keyAttribute');
54
55 /**
56  * option: Name of the attribute that stores the type
57  *
58  * Possible values:
59  * - any string
60  */
61 define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE', 'typeAttribute');
62
63 /**
64  * option: Name of the attribute that stores the class name
65  *
66  * Possible values:
67  * - any string
68  */
69 define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS', 'classAttribute');
70
71 /**
72  * option: Whether to use the tag name as a class name
73  *
74  * Possible values:
75  * - true or false
76  */
77 define('XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME', 'tagAsClass');
78
79 /**
80  * option: Name of the default class
81  *
82  * Possible values:
83  * - any string
84  */
85 define('XML_UNSERIALIZER_OPTION_DEFAULT_CLASS', 'defaultClass');
86
87 /**
88  * option: Whether to parse attributes
89  *
90  * Possible values:
91  * - true or false
92  */
93 define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE', 'parseAttributes');
94
95 /**
96  * option: Key of the array to store attributes (if any)
97  *
98  * Possible values:
99  * - any string
100  * - false (disabled)
101  */
102 define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY', 'attributesArray');
103
104 /**
105  * option: string to prepend attribute name (if any)
106  *
107  * Possible values:
108  * - any string
109  * - false (disabled)
110  */
111 define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND', 'prependAttributes');
112
113 /**
114  * option: key to store the content, if XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE is used
115  *
116  * Possible values:
117  * - any string
118  */
119 define('XML_UNSERIALIZER_OPTION_CONTENT_KEY', 'contentName');
120
121 /**
122  * option: map tag names
123  *
124  * Possible values:
125  * - associative array
126  */
127 define('XML_UNSERIALIZER_OPTION_TAG_MAP', 'tagMap');
128
129 /**
130  * option: list of tags that will always be enumerated
131  *
132  * Possible values:
133  * - indexed array
134  */
135 define('XML_UNSERIALIZER_OPTION_FORCE_ENUM', 'forceEnum');
136
137 /**
138  * option: Encoding of the XML document
139  *
140  * Possible values:
141  * - UTF-8
142  * - ISO-8859-1
143  */
144 define('XML_UNSERIALIZER_OPTION_ENCODING_SOURCE', 'encoding');
145
146 /**
147  * option: Desired target encoding of the data
148  *
149  * Possible values:
150  * - UTF-8
151  * - ISO-8859-1
152  */
153 define('XML_UNSERIALIZER_OPTION_ENCODING_TARGET', 'targetEncoding');
154
155 /**
156  * option: Callback that will be applied to textual data
157  *
158  * Possible values:
159  * - any valid PHP callback
160  */
161 define('XML_UNSERIALIZER_OPTION_DECODE_FUNC', 'decodeFunction');
162
163 /**
164  * option: whether to return the result of the unserialization from unserialize()
165  *
166  * Possible values:
167  * - true
168  * - false (default)
169  */
170 define('XML_UNSERIALIZER_OPTION_RETURN_RESULT', 'returnResult');
171
172 /**
173  * option: set the whitespace behaviour
174  *
175  * Possible values:
176  * - XML_UNSERIALIZER_WHITESPACE_KEEP
177  * - XML_UNSERIALIZER_WHITESPACE_TRIM
178  * - XML_UNSERIALIZER_WHITESPACE_NORMALIZE
179  */
180 define('XML_UNSERIALIZER_OPTION_WHITESPACE', 'whitespace');
181
182 /**
183  * Keep all whitespace
184  */
185 define('XML_UNSERIALIZER_WHITESPACE_KEEP', 'keep');
186
187 /**
188  * remove whitespace from start and end of the data
189  */
190 define('XML_UNSERIALIZER_WHITESPACE_TRIM', 'trim');
191
192 /**
193  * normalize whitespace
194  */
195 define('XML_UNSERIALIZER_WHITESPACE_NORMALIZE', 'normalize');
196
197 /**
198  * option: whether to ovverride all options that have been set before
199  *
200  * Possible values:
201  * - true
202  * - false (default)
203  */
204 define('XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS', 'overrideOptions');
205
206 /**
207  * option: list of tags, that will not be used as keys
208  */
209 define('XML_UNSERIALIZER_OPTION_IGNORE_KEYS', 'ignoreKeys');
210
211 /**
212  * option: whether to use type guessing for scalar values
213  */
214 define('XML_UNSERIALIZER_OPTION_GUESS_TYPES', 'guessTypes');
215
216 /**
217  * error code for no serialization done
218  */
219 define('XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION', 151);
220
221 /**
222  * XML_Unserializer
223  *
224  * class to unserialize XML documents that have been created with
225  * XML_Serializer. To unserialize an XML document you have to add
226  * type hints to the XML_Serializer options.
227  *
228  * If no type hints are available, XML_Unserializer will guess how
229  * the tags should be treated, that means complex structures will be
230  * arrays and tags with only CData in them will be strings.
231  *
232  * <code>
233  * require_once 'XML/Unserializer.php';
234  *
235  * //  be careful to always use the ampersand in front of the new operator
236  * $unserializer = &new XML_Unserializer();
237  *
238  * $unserializer->unserialize($xml);
239  *
240  * $data = $unserializer->getUnserializedData();
241  * <code>
242  *
243  *
244  * @category   XML
245  * @package    XML_Serializer
246  * @author     Stephan Schmidt <schst@php.net>
247  * @copyright  1997-2005 The PHP Group
248  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
249  * @version    Release: 0.18.0
250  * @link       http://pear.php.net/package/XML_Serializer
251  * @see        XML_Serializer
252  */
253 class XML_Unserializer extends PEAR
254 {
255    /**
256     * list of all available options
257     *
258     * @access private
259     * @var    array
260     */
261     var $_knownOptions = array(
262                                 XML_UNSERIALIZER_OPTION_COMPLEXTYPE,
263                                 XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY,
264                                 XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE,
265                                 XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS,
266                                 XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME,
267                                 XML_UNSERIALIZER_OPTION_DEFAULT_CLASS,
268                                 XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE,
269                                 XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY,
270                                 XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND,
271                                 XML_UNSERIALIZER_OPTION_CONTENT_KEY,
272                                 XML_UNSERIALIZER_OPTION_TAG_MAP,
273                                 XML_UNSERIALIZER_OPTION_FORCE_ENUM,
274                                 XML_UNSERIALIZER_OPTION_ENCODING_SOURCE,
275                                 XML_UNSERIALIZER_OPTION_ENCODING_TARGET,
276                                 XML_UNSERIALIZER_OPTION_DECODE_FUNC,
277                                 XML_UNSERIALIZER_OPTION_RETURN_RESULT,
278                                 XML_UNSERIALIZER_OPTION_WHITESPACE,
279                                 XML_UNSERIALIZER_OPTION_IGNORE_KEYS,
280                                 XML_UNSERIALIZER_OPTION_GUESS_TYPES
281                               );
282    /**
283     * default options for the serialization
284     *
285     * @access private
286     * @var    array
287     */
288     var $_defaultOptions = array(
289                          XML_UNSERIALIZER_OPTION_COMPLEXTYPE         => 'array',                // complex types will be converted to arrays, if no type hint is given
290                          XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY       => '_originalKey',         // get array key/property name from this attribute
291                          XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE      => '_type',                // get type from this attribute
292                          XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS     => '_class',               // get class from this attribute (if not given, use tag name)
293                          XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME    => true,                   // use the tagname as the classname
294                          XML_UNSERIALIZER_OPTION_DEFAULT_CLASS       => 'stdClass',             // name of the class that is used to create objects
295                          XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE    => false,                  // parse the attributes of the tag into an array
296                          XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY => false,                  // parse them into sperate array (specify name of array here)
297                          XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND  => '',                     // prepend attribute names with this string
298                          XML_UNSERIALIZER_OPTION_CONTENT_KEY         => '_content',             // put cdata found in a tag that has been converted to a complex type in this key
299                          XML_UNSERIALIZER_OPTION_TAG_MAP             => array(),                // use this to map tagnames
300                          XML_UNSERIALIZER_OPTION_FORCE_ENUM          => array(),                // these tags will always be an indexed array
301                          XML_UNSERIALIZER_OPTION_ENCODING_SOURCE     => null,                   // specify the encoding character of the document to parse
302                          XML_UNSERIALIZER_OPTION_ENCODING_TARGET     => null,                   // specify the target encoding
303                          XML_UNSERIALIZER_OPTION_DECODE_FUNC         => null,                   // function used to decode data
304                          XML_UNSERIALIZER_OPTION_RETURN_RESULT       => false,                  // unserialize() returns the result of the unserialization instead of true
305                          XML_UNSERIALIZER_OPTION_WHITESPACE          => XML_UNSERIALIZER_WHITESPACE_TRIM, // remove whitespace around data
306                          XML_UNSERIALIZER_OPTION_IGNORE_KEYS         => array(),                // List of tags that will automatically be added to the parent, instead of adding a new key
307                          XML_UNSERIALIZER_OPTION_GUESS_TYPES         => false                   // Whether to use type guessing
308                         );
309
310    /**
311     * current options for the serialization
312     *
313     * @access public
314     * @var    array
315     */
316     var $options = array();
317
318    /**
319     * unserialized data
320     *
321     * @access private
322     * @var    string
323     */
324     var $_unserializedData = null;
325
326    /**
327     * name of the root tag
328     *
329     * @access private
330     * @var    string
331     */
332     var $_root = null;
333
334    /**
335     * stack for all data that is found
336     *
337     * @access private
338     * @var    array
339     */
340     var $_dataStack  =   array();
341
342    /**
343     * stack for all values that are generated
344     *
345     * @access private
346     * @var    array
347     */
348     var $_valStack  =   array();
349
350    /**
351     * current tag depth
352     *
353     * @access private
354     * @var    int
355     */
356     var $_depth = 0;
357
358    /**
359     * XML_Parser instance
360     *
361     * @access   private
362     * @var      object XML_Parser
363     */
364     var $_parser = null;
365     
366    /**
367     * constructor
368     *
369     * @access   public
370     * @param    mixed   $options    array containing options for the unserialization
371     */
372     function XML_Unserializer($options = null)
373     {
374         if (is_array($options)) {
375             $this->options = array_merge($this->_defaultOptions, $options);
376         } else {
377             $this->options = $this->_defaultOptions;
378         }
379     }
380
381    /**
382     * return API version
383     *
384     * @access   public
385     * @static
386     * @return   string  $version API version
387     */
388     function apiVersion()
389     {
390         return '0.18.0';
391     }
392
393    /**
394     * reset all options to default options
395     *
396     * @access   public
397     * @see      setOption(), XML_Unserializer(), setOptions()
398     */
399     function resetOptions()
400     {
401         $this->options = $this->_defaultOptions;
402     }
403
404    /**
405     * set an option
406     *
407     * You can use this method if you do not want to set all options in the constructor
408     *
409     * @access   public
410     * @see      resetOption(), XML_Unserializer(), setOptions()
411     */
412     function setOption($name, $value)
413     {
414         $this->options[$name] = $value;
415     }
416
417    /**
418     * sets several options at once
419     *
420     * You can use this method if you do not want to set all options in the constructor
421     *
422     * @access   public
423     * @see      resetOption(), XML_Unserializer(), setOption()
424     */
425     function setOptions($options)
426     {
427         $this->options = array_merge($this->options, $options);
428     }
429
430    /**
431     * unserialize data
432     *
433     * @access   public
434     * @param    mixed    $data     data to unserialize (string, filename or resource)
435     * @param    boolean  $isFile   data should be treated as a file
436     * @param    array    $options  options that will override the global options for this call
437     * @return   boolean  $success
438     */
439     function unserialize($data, $isFile = false, $options = null)
440     {
441         $this->_unserializedData = null;
442         $this->_root = null;
443
444         // if options have been specified, use them instead
445         // of the previously defined ones
446         if (is_array($options)) {
447             $optionsBak = $this->options;
448             if (isset($options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS]) && $options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS] == true) {
449                 $this->options = array_merge($this->_defaultOptions, $options);
450             } else {
451                 $this->options = array_merge($this->options, $options);
452             }
453         } else {
454             $optionsBak = null;
455         }
456
457         $this->_valStack = array();
458         $this->_dataStack = array();
459         $this->_depth = 0;
460
461         $this->_createParser();
462         
463         if (is_string($data)) {
464             if ($isFile) {
465                 $result = $this->_parser->setInputFile($data);
466                 if (PEAR::isError($result)) {
467                     return $result;
468                 }
469                 $result = $this->_parser->parse();
470             } else {
471                 $result = $this->_parser->parseString($data,true);
472             }
473         } else {
474            $this->_parser->setInput($data);
475            $result = $this->_parser->parse();
476         }
477
478         if ($this->options[XML_UNSERIALIZER_OPTION_RETURN_RESULT] === true) {
479           $return = $this->_unserializedData;
480         } else {
481             $return = true;
482         }
483
484         if ($optionsBak !== null) {
485             $this->options = $optionsBak;
486         }
487
488         if (PEAR::isError($result)) {
489             return $result;
490         }
491
492         return $return;
493     }
494
495    /**
496     * get the result of the serialization
497     *
498     * @access public
499     * @return string  $serializedData
500     */
501     function getUnserializedData()
502     {
503         if ($this->_root === null) {
504             return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
505         }
506         return $this->_unserializedData;
507     }
508
509    /**
510     * get the name of the root tag
511     *
512     * @access public
513     * @return string  $rootName
514     */
515     function getRootName()
516     {
517         if ($this->_root === null) {
518             return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
519         }
520         return $this->_root;
521     }
522
523    /**
524     * Start element handler for XML parser
525     *
526     * @access private
527     * @param  object $parser  XML parser object
528     * @param  string $element XML element
529     * @param  array  $attribs attributes of XML tag
530     * @return void
531     */
532     function startHandler($parser, $element, $attribs)
533     {
534         if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]])) {
535             $type = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]];
536             $guessType = false;
537         } else {
538             $type = 'string';
539             if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) {
540                 $guessType = true;
541             } else {
542                 $guessType = false;
543             }
544         }
545
546         if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) {
547             $attribs = array_map($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $attribs);
548         }
549         
550         $this->_depth++;
551         $this->_dataStack[$this->_depth] = null;
552
553         if (is_array($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP]) && isset($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element])) {
554             $element = $this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element];
555         }
556
557         $val = array(
558                      'name'         => $element,
559                      'value'        => null,
560                      'type'         => $type,
561                      'guessType'    => $guessType,
562                      'childrenKeys' => array(),
563                      'aggregKeys'   => array()
564                     );
565
566         if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE] == true && (count($attribs) > 0)) {
567             $val['children'] = array();
568             $val['type']  = $this->_getComplexType($element);
569             $val['class'] = $element;
570
571             if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) {
572               $attribs = $this->_guessAndSetTypes($attribs);
573             }           
574             if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY] != false) {
575                 $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY]] = $attribs;
576             } else {
577                 foreach ($attribs as $attrib => $value) {
578                     $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND].$attrib] = $value;
579                 }
580             }
581         }
582
583         $keyAttr = false;
584         
585         if (is_string($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) {
586             $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY];
587         } elseif (is_array($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) {
588             if (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element])) {
589                 $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element];
590             } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default'])) {
591                 $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default'];
592             } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default'])) {
593                 // keep this for BC
594                 $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default'];
595             }
596         }
597         
598         if ($keyAttr !== false && isset($attribs[$keyAttr])) {
599             $val['name'] = $attribs[$keyAttr];
600         }
601
602         if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]])) {
603             $val['class'] = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]];
604         }
605
606         array_push($this->_valStack, $val);
607     }
608
609    /**
610     * Try to guess the type of several values and
611     * set them accordingly
612     *
613     * @access   private
614     * @param    array      array, containing the values
615     * @return   array      array, containing the values with their correct types
616     */
617     function _guessAndSetTypes($array)
618     {
619         foreach ($array as $key => $value) {
620           $array[$key] = $this->_guessAndSetType($value);
621         }
622         return $array;
623     }
624     
625    /**
626     * Try to guess the type of a value and
627     * set it accordingly
628     *
629     * @access   private
630     * @param    string      character data
631     * @return   mixed       value with the best matching type
632     */
633     function _guessAndSetType($value)
634     {
635         if ($value === 'true') {
636             return true;
637         }
638         if ($value === 'false') {
639             return false;
640         }
641         if ($value === 'NULL') {
642             return null;
643         }
644         if (preg_match('/^[-+]?[0-9]{1,}$/', $value)) {
645           return intval($value);
646         }
647         if (preg_match('/^[-+]?[0-9]{1,}\.[0-9]{1,}$/', $value)) {
648           return doubleval($value);
649         }
650         return (string)$value;
651     }
652     
653    /**
654     * End element handler for XML parser
655     *
656     * @access private
657     * @param  object XML parser object
658     * @param  string
659     * @return void
660     */
661     function endHandler($parser, $element)
662     {
663         $value = array_pop($this->_valStack);
664         switch ($this->options[XML_UNSERIALIZER_OPTION_WHITESPACE]) {
665             case XML_UNSERIALIZER_WHITESPACE_KEEP:
666                 $data = $this->_dataStack[$this->_depth];
667                 break;
668             case XML_UNSERIALIZER_WHITESPACE_NORMALIZE:
669                 $data = trim(preg_replace('/\s\s+/m', ' ', $this->_dataStack[$this->_depth]));
670                 break;
671             case XML_UNSERIALIZER_WHITESPACE_TRIM:
672             default:
673                 $data  = trim($this->_dataStack[$this->_depth]);
674                 break;
675         }
676
677         // adjust type of the value
678         switch(strtolower($value['type'])) {
679
680             // unserialize an object
681             case 'object':
682                 if (isset($value['class'])) {
683                     $classname  = $value['class'];
684                 } else {
685                     $classname = '';
686                 }
687                 // instantiate the class
688                 if ($this->options[XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME] === true && class_exists($classname)) {
689                     $value['value'] = &new $classname;
690                 } else {
691                     $value['value'] = &new $this->options[XML_UNSERIALIZER_OPTION_DEFAULT_CLASS];
692                 }
693                 if (trim($data) !== '') {
694                     if ($value['guessType'] === true) {
695                       $data = $this->_guessAndSetType($data);
696                     }
697                     $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data;
698                 }
699
700                 // set properties
701                 foreach ($value['children'] as $prop => $propVal) {
702                     // check whether there is a special method to set this property
703                     $setMethod = 'set'.$prop;
704                     if (method_exists($value['value'], $setMethod)) {
705                         call_user_func(array(&$value['value'], $setMethod), $propVal);
706                     } else {
707                         $value['value']->$prop = $propVal;
708                     }
709                 }
710                 //  check for magic function
711                 if (method_exists($value['value'], '__wakeup')) {
712                     $value['value']->__wakeup();
713                 }
714                 break;
715
716             // unserialize an array
717             case 'array':
718                 if (trim($data) !== '') {
719                     if ($value['guessType'] === true) {
720                       $data = $this->_guessAndSetType($data);
721                     }
722                     $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data;
723                 }
724                 if (isset($value['children'])) {
725                     $value['value'] = $value['children'];
726                 } else {
727                     $value['value'] = array();
728                 }
729                 break;
730
731             // unserialize a null value
732             case 'null':
733                 $data = null;
734                 break;
735
736             // unserialize a resource => this is not possible :-(
737             case 'resource':
738                 $value['value'] = $data;
739                 break;
740
741             // unserialize any scalar value
742             default:
743                 if ($value['guessType'] === true) {
744                     $data = $this->_guessAndSetType($data);
745                 } else {
746                     settype($data, $value['type']);
747                 }
748             
749                 $value['value'] = $data;
750                 break;
751         }
752         $parent = array_pop($this->_valStack);
753         if ($parent === null) {
754             $this->_unserializedData = &$value['value'];
755             $this->_root = &$value['name'];
756             return true;
757         } else {
758             // parent has to be an array
759             if (!isset($parent['children']) || !is_array($parent['children'])) {
760                 $parent['children'] = array();
761                 if (!in_array($parent['type'], array('array', 'object'))) {
762                     $parent['type'] = $this->_getComplexType($parent['name']);
763                     if ($parent['type'] == 'object') {
764                         $parent['class'] = $parent['name'];
765                     }
766                 }
767             }
768
769             if (in_array($element, $this->options[XML_UNSERIALIZER_OPTION_IGNORE_KEYS])) {
770                 $ignoreKey = true;
771             } else {
772               $ignoreKey = false;
773             }
774             
775             if (!empty($value['name']) && $ignoreKey === false) {
776                 // there already has been a tag with this name
777                 if (in_array($value['name'], $parent['childrenKeys']) || in_array($value['name'], $this->options[XML_UNSERIALIZER_OPTION_FORCE_ENUM])) {
778                     // no aggregate has been created for this tag
779                     if (!in_array($value['name'], $parent['aggregKeys'])) {
780                         if (isset($parent['children'][$value['name']])) {
781                             $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
782                         } else {
783                             $parent['children'][$value['name']] = array();
784                         }
785                         array_push($parent['aggregKeys'], $value['name']);
786                     }
787                     array_push($parent['children'][$value['name']], $value['value']);
788                 } else {
789                     $parent['children'][$value['name']] = &$value['value'];
790                     array_push($parent['childrenKeys'], $value['name']);
791                 }
792             } else {
793                 array_push($parent['children'], $value['value']);
794             }
795             array_push($this->_valStack, $parent);
796         }
797
798         $this->_depth--;
799     }
800
801    /**
802     * Handler for character data
803     *
804     * @access private
805     * @param  object XML parser object
806     * @param  string CDATA
807     * @return void
808     */
809     function cdataHandler($parser, $cdata)
810     {
811         if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) {
812             $cdata = call_user_func($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $cdata);
813         }
814         $this->_dataStack[$this->_depth] .= $cdata;
815     }
816
817    /**
818     * get the complex type, that should be used for a specified tag
819     *
820     * @access   private
821     * @param    string      name of the tag
822     * @return   string      complex type ('array' or 'object')
823     */
824     function _getComplexType($tagname)
825     {
826         if (is_string($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE])) {
827           return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE];
828         }
829         if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname])) {
830           return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname];
831         }
832         if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default'])) {
833           return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default'];
834         }
835         return 'array';
836     }
837     
838    /**
839     * create the XML_Parser instance
840     *
841     * @access    private
842     * @return    boolean
843     */
844     function _createParser()
845     {
846         if (is_object($this->_parser)) {
847             $this->_parser->free();
848             unset($this->_parser);
849         }
850         $this->_parser = &new XML_Parser($this->options[XML_UNSERIALIZER_OPTION_ENCODING_SOURCE], 'event', $this->options[XML_UNSERIALIZER_OPTION_ENCODING_TARGET]);
851         $this->_parser->folding = false;
852         $this->_parser->setHandlerObj($this);
853         return true;
854     }
855 }
856 ?>
Note: See TracBrowser for help on using the browser.