Fix #8052 - fixing pdf
[pear] / XML / Tree / Morph.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group                                |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license,      |
9 // | that is bundled with this package in the file LICENSE, and is        |
10 // | available at through the world-wide-web at                           |
11 // | http://www.php.net/license/2_02.txt.                                 |
12 // | If you did not receive a copy of the PHP license and are unable to   |
13 // | obtain it through the world-wide-web, please send a note to          |
14 // | license@php.net so we can mail you a copy immediately.               |
15 // +----------------------------------------------------------------------+
16 // | Authors:  Alan Knowles <alan@akbkhome.com>                           |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: php_pear_headers,v 1.1 2002/04/22 09:51:27 alan_k Exp $
20 //
21 // This is a wrapper class for XML_Tree to lets you add callbacks to xml tags
22 // to enable data morphing (so you can get associative arrays and the like from 
23 // Trees.
24 // 
25 //
26
27 require_once 'XML/Tree.php';
28
29 /**
30 * The Morpher..
31 *
32 * Usage:
33 *
34 *
35 *
36 *
37 * require_once 'XML/Tree/Morph.php';
38 *
39 *
40 * $x = new XML_Tree_Morph(
41 *    'somefile.glade',
42 *    array(
43 *       'debug' => 0,
44 *       'filter' => array(
45 *            //tag      // either toObject/toArray or your function/method etc.
46 *           'project' => 'toObject',
47 *           'widget'  => 'toObject',
48 *           'child'   => 'toObject',
49 *
50 *         )
51 *     )
52 * );
53 * $tree = $x->getTreeFromFile();
54 * print_r($tree->children[0]['project']);
55 * print_r($tree->children[1]['widget']);
56
57 * Results in...
58 *
59 *stdClass Object
60 *(
61 *    [name] => validatemanager
62 *    [program_name] => validatemanage 
63 *    [directory] =>
64 *    [source_directory] => src
65 *    [pixmaps_directory] => pixmaps
66 *    [language] => C
67 *    [gnome_support] => False
68 *    [gettext_support] => False
69 *)
70 *stdClass Object
71 *(
72 *    [class] => GtkWindow
73 *    [name] => window
74 *    [title] => Gtk_ValidateManager
75 *    [type] => GTK_WINDOW_TOPLEVEL
76 *    [position] => GTK_WIN_POS_CENTER
77 *    [modal] => False
78 *    [default_width] => 600
79 *    [default_height] => 400
80 *    [allow_shrink] => False
81 *    [allow_grow] => True
82 *    [auto_shrink] => False
83 *    [widget] => stdClass Object
84 *        ( ......
85 *
86 *
87 * @version    $Id: php_phpdoc_class,v 1.1 2002/04/22 10:20:29 alan_k Exp $
88 */
89 class XML_Tree_Morph extends XML_Tree {
90
91     var $cdata = '';
92     var $_morphOptions;
93     
94     var $i;
95     
96
97     /**
98     * Constructor
99     *
100     * 
101     * 
102     * 
103     * @param   string               Filename
104     * @param   array $options
105     *                   valid options:
106     *               debug = 0/1
107     *               filter => array(
108     *                   tagname => callback
109     *   
110     *           where callback can be
111     *               - toObject|toArary = built in converters
112     *               - 'function', array($object,'method') or
113     *                 array('class','staticMethod');
114     * 
115     *
116     * @access   public
117     */
118   
119     function __construct($filename,$options) {
120        
121         parent::__construct($filename,'1.0');
122         
123         $this->_morphOptions = $options;
124     }
125     
126
127     /**
128     * Overridden endHandler which relays into callbacks..
129     *
130     * @see      XML_Tree:endHandler();
131     */
132       
133   
134     
135     function endHandler($elem)  {
136         $this->i--;
137         if ($this->i > 1) {
138             $obj_id =   $this->i;
139             // recover the node created in StartHandler
140             $node   =  $this->obj[$obj_id];
141             // mixed contents
142             //var_dump($this->cdata, typeof($node->children);
143             if (is_array($node->children) && count($node->children) > 0) {
144                 if (!empty($this->cdata) && trim($this->cdata)) {
145                     $node->children[] =  new XML_Tree_Node(null, $this->cdata);
146                 }
147             } else if ($this->cdata !== null) {
148                 
149                 $node->setContent($this->cdata);
150                 //var_dump(array($node, $this->cdata));
151             } else {
152                 $node->setContent('');
153             }
154             $parent_id =  ($this->i - 1);
155             $parent    = $this->obj[$parent_id];
156             // attach the node to its parent node children array
157            // print_r($this);exit;
158             if (isset($this->_morphOptions['filter'][$node->name])) {
159                 $f = $this->_morphOptions['filter'][$node->name];
160                 if (is_string($f) && method_exists($this,'morph'.$f)) {
161                     $parent->children[] = $this->{'morph'.$this->_morphOptions['filter'][$node->name]}($node);
162                     $this->cdata = null;
163                     return null;
164                 }
165                 if (is_callable($f)) {
166                     $parent->children[] = call_user_func($f, $node);
167                     $this->cdata = null;
168                     return null;
169                 }
170                  
171                 
172                 
173             }
174             if (@$this->_morphOptions['debug']) {
175                 echo "SKIP: {$node->name}\n";\r
176             }
177             
178             $parent->children[] = $node;
179             
180         }
181         $this->cdata = null;
182         return null;
183         
184          
185     }
186     
187     /**
188     * morph to an array
189     *
190     * Converts standard <xxx>vvvv</xxxx> into
191     *   [xxxx] => vvvvv
192     * 
193     * 
194     * @param   object XML_Tree_Node
195     * 
196     *
197     * @return   array (name => array(keys=>values)
198     * @access   public
199     */
200     function morphToArray($node) {
201         $ret = array();
202         foreach($node->children as $cnode)  {
203             // is cnode a node?
204             if (is_a($cnode,'xml_tree_node')) {
205                 $ret[$cnode->name] = $cnode->content;
206                 continue;
207             }
208             // otherwise it's an array...
209              
210             
211             foreach($cnode as $k=>$o) {
212                 if (empty($ret[$k])) {
213                     $ret[$k]= array();
214                 }
215                 if (!is_array($ret[$k])) {
216                     echo "OPPS: $k already in array ";print_r($ret);
217                     echo "TRYING TO ADD "; print_r($cnode);
218                     exit;
219                 }
220                 $ret[$k][] = $o;
221             }
222             
223         }
224         foreach($ret as $k=>$v) {
225             if (is_array($v) && count($v) == 1 ) {
226                 $ret[$k] = $v[0];
227             }
228         }
229         
230         //print_r($ret);
231         return array($node->name => $ret);
232     }
233       /**
234     * morph to an object
235     *
236     * Converts standard <xxx>vvvv</xxxx> into
237     *   $obj->xxx = vvvvv
238     * 
239     * 
240     * @param   object XML_Tree_Node
241     * 
242     *
243     * @return   array   ($node->name => $object);
244     * @access   public
245     */
246     function morphToObject($node) {
247         $ret = new StdClass;
248         foreach($node->children as $cnode)  {
249             // is cnode a node?
250             if (is_a($cnode,'xml_tree_node')) {
251                 $ret->{$cnode->name} = $cnode->content;
252                 continue;
253             }
254             // otherwise it's an array...
255              
256             
257             foreach($cnode as $k=>$o) {
258                 if (empty($ret->{$k})) {
259                     $ret->{$k}= array();
260                 }
261                 if (!is_array($ret->{$k})) {
262                     echo "OPPS: $k already in array ";print_r($ret);
263                     echo "TRYING TO ADD "; print_r($cnode);
264                     exit;
265                 }
266                 $ret->{$k}[] = $o;
267             }
268             
269         }
270         foreach($ret as $k=>$v) {
271             if (is_array($v) && count($v) == 1 ) {
272                 $ret->{$k} = $v[0];
273             }
274         }
275         
276         //print_r($ret);
277         return array($node->name => $ret);
278     }
279 }
280