]> git.llucax.com Git - software/bife/bife-all.git/blob - src/BIFE/Parser.php
cf0b851cfdca4dfc8151a2b21a52196496253784
[software/bife/bife-all.git] / src / BIFE / Parser.php
1 <?php
2 // vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
3 // +--------------------------------------------------------------------+
4 // |                       BIFE - Buil It FastEr                        |
5 // +--------------------------------------------------------------------+
6 // | This file is part of BIFE.                                         |
7 // |                                                                    |
8 // | BIFE is free software; you can redistribute it and/or modify it    |
9 // | under the terms of the GNU General Public License as published by  |
10 // | the Free Software Foundation; either version 2 of the License, or  |
11 // | (at your option) any later version.                                |
12 // |                                                                    |
13 // | BIFE is distributed in the hope that it will be useful, but        |
14 // | WITHOUT ANY WARRANTY; without even the implied warranty of         |
15 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   |
16 // | General Public License for more details.                           |
17 // |                                                                    |
18 // | You should have received a copy of the GNU General Public License  |
19 // | along with Hooks; if not, write to the Free Software Foundation,   |
20 // | Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA      |
21 // +--------------------------------------------------------------------+
22 // | Created: Wed May 17 18:16:54 ART 2003                              |
23 // | Authors: Leandro Lucarella <luca@lugmen.org.ar>                    |
24 // +--------------------------------------------------------------------+
25 //
26 // $Id$
27 //
28
29 // +X2C Class 25 :Parser
30 /**
31  * This is the XML Parser.
32  *
33  * @access public
34  */
35 class BIFE_Parser {
36     /**
37      * Top level widget.
38      *
39      * @var    BIFE_Root $root
40      * @access public
41      */
42     var $root;
43
44     /**
45      * XML parser resource.
46      *
47      * @var    resource $parser
48      * @access public
49      */
50     var $parser;
51
52     /**
53      * BIFE widgets stack.
54      *
55      * @var    array $stack
56      * @access public
57      */
58     var $stack;
59
60     /**
61      * Fallback class to use in case that a widget class is not found.
62      *
63      * @var    string $fallback
64      * @access public
65      */
66     var $fallback = '';
67
68     /**
69      * XML cache directory. Empty if no cahching must be done (for current dir use '.').
70      *
71      * @var    string $cache
72      * @access protected
73      */
74     var $cache = '/tmp';
75
76     // ~X2C
77
78     // +X2C Operation 30
79     /**
80      * Constructor.
81      *
82      * @param  string $fallback Fallback class name (none if empty).
83      * @param  string $cache XML cache directory. Empty is no caching will be done.
84      *
85      * @return void
86      * @access public
87      */
88     function BIFE_Parser($fallback = '', $cache = '/tmp') // ~X2C
89     {
90         $this->__construct($fallback, $cache);
91     }
92     // -X2C
93
94     // +X2C Operation 31
95     /**
96      * Constructor.
97      *
98      * @param  string $fallback Fallback class name (none if empty).
99      * @param  string $cache XML cache directory. Empty is no caching will be done.
100      *
101      * @return void
102      * @access public
103      */
104     function __construct($fallback = '', $cache = '/tmp') // ~X2C
105     {
106         $this->stack    = array();
107         $this->root     = null;
108         $this->parser   = xml_parser_create();
109         $this->fallback = $fallback;
110         $this->cache    = $cache;
111         xml_set_object($this->parser, $this);
112         xml_set_element_handler($this->parser, 'startElement', 'endElement');
113         xml_set_character_data_handler($this->parser, 'characterData');
114     }
115     // -X2C
116
117     // +X2C Operation 32
118     /**
119      * Destructor.
120      *
121      * @return void
122      * @access public
123      */
124     function __destruct() // ~X2C
125     {
126         xml_parser_free($this->parser);
127     }
128     // -X2C
129
130     // +X2C Operation 33
131     /**
132      * XML parser start of element handler.
133      *
134      * @param  resource $parser XML parser resource.
135      * @param  string $name XML tag name.
136      * @param  array $attrs XML tag attributes.
137      *
138      * @return void
139      * @access public
140      */
141     function startElement($parser, $name, $attrs) // ~X2C
142     {
143         $class = "BIFE_$name";
144         if (!class_exists($class)) {
145             @include_once 'BIFE/' . ucfirst(strtolower($name)) . '.php';
146         }
147         if (class_exists($class)) {
148             $obj =& new $class($attrs);
149             if (!is_a($obj, 'bife_widget')) {
150                 trigger_error("Class '$class' is not a BIFE_Widget.", E_USER_WARNING);
151             }
152             $this->stack[] =& $obj;
153         } else {
154             if ($this->fallback) {
155                 $class = $this->fallback;
156                 $obj =& new $class($name, $attrs);
157                 if (!is_a($obj, 'bife_fallback')) {
158                     trigger_error("Class '$class' is not a BIFE_Fallback.", E_USER_WARNING);
159                 }
160                 $this->stack[] =& $obj;
161             } else {
162                 trigger_error("Class not found '$class'.", E_USER_ERROR);
163             }
164         }
165     }
166     // -X2C
167
168     // +X2C Operation 34
169     /**
170      * XML parser end of element handler.
171      *
172      * @param  resource $parser XML parser resource.
173      * @param  string $name XML tag name.
174      *
175      * @return void
176      * @access public
177      */
178     function endElement($parser, $name) // ~X2C
179     {
180         end($this->stack);
181         $current =& $this->stack[key($this->stack)];
182         array_pop($this->stack);
183         end($this->stack);
184         $parent =& $this->stack[key($this->stack)];
185         if ($parent) {
186             $parent->addContents($current);
187         } else {
188             $this->root =& $current;
189         }
190     }
191     // -X2C
192
193     // +X2C Operation 35
194     /**
195      * XML parser character data handler.
196      *
197      * @param  resource $parser XML parser resource.
198      * @param  string $data XML character data.
199      *
200      * @return void
201      * @access public
202      */
203     function characterData($parser, $data) // ~X2C
204     {
205         end($this->stack);
206         $current =& $this->stack[key($this->stack)];
207         $current->addContents($data);
208     }
209     // -X2C
210
211     // +X2C Operation 36
212     /**
213      * Parse a string with XML data.
214      *
215      * @param  string $data XML string to parse.
216      * @param  bool $final Indicates if is the last string to parse.
217      *
218      * @return void
219      * @access public
220      */
221     function parse($data, $final = true) // ~X2C
222     {
223         if (!xml_parse($this->parser, $data, $final)) {
224             trigger_error(
225                 sprintf('XML error: %s at line %d.',
226                     xml_error_string(xml_get_error_code($this->parser)),
227                     xml_get_current_line_number($this->parser)
228                 ),
229                 E_USER_WARNING
230             );
231         }
232     }
233     // -X2C
234
235     // +X2C Operation 37
236     /**
237      * Parse a XML file with a complete and valid XML document.
238      *
239      * @param  string $filename Filename to parse.
240      *
241      * @return &BIFE_Root
242      * @access public
243      */
244     function &parseFile($filename) // ~X2C
245     {
246         if ($this->cache) {
247             $cache = $this->cache . '/' . 'bife_parser_cache' . strtr(realpath($filename), '/', '_');
248             if (@filemtime($cache) > @filemtime($filename)) {
249                 // FIXME - replace with file_get_contents()
250                 $file = file($cache);
251                 foreach(unserialize(trim(array_shift($file))) as $required) {
252                     require_once $required;
253                 }
254                 return unserialize(join('', $file));
255             }
256         }
257         if ($fp = @fopen($filename, 'r')) {
258             while ($data = fread($fp, 4096)) {
259                 $this->parse($data, feof($fp));
260             }
261         } else {
262             trigger_error("Could not open BIFE XML input file '$filename'.",
263                 E_USER_WARNING);
264         }
265         fclose($fp);
266         if ($this->cache) {
267             $fp = fopen($cache, 'w');
268             fputs($fp, serialize($this->root->getRequiredFiles()) . "\n");
269             fputs($fp, serialize($this->root));
270             fclose($fp);
271         }
272         return $this->root;
273     }
274     // -X2C
275
276
277     // +X2C Operation 74
278     /**
279      * Parse a XML string with a complete and valid XML document.
280      *
281      * @param  string $data XML data to parse.
282      *
283      * @return &BIFE_Root
284      * @access public
285      */
286     function &parseString($data) // ~X2C
287     {
288         $this->parse($data, true);
289         return $this->root;
290     }
291     // -X2C
292
293 } // -X2C Class :Parser
294
295 ?>