2 // vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
3 // +--------------------------------------------------------------------+
4 // | BIFE - Buil It FastEr |
5 // +--------------------------------------------------------------------+
6 // | This file is part of BIFE. |
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. |
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. |
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 // +--------------------------------------------------------------------+
29 // +X2C Class 25 :Parser
31 * This is the XML Parser.
40 * @var BIFE_Widget $root
46 * XML parser resource.
48 * @var resource $parser
62 * Fallback class to use in case that a widget class is not found.
64 * @var string $fallback
70 * XML cache directory. Empty if no cahching must be done (for current dir use '.').
78 * Files required by the parsed XML file.
80 * @var array $requires
83 var $requires = array();
91 * @param string $fallback Fallback class name (none if empty).
92 * @param string $cache XML cache directory. Empty is no caching will be done.
97 function BIFE_Parser($fallback = '', $cache = '/tmp') // ~X2C
99 $this->__construct($fallback, $cache);
107 * @param string $fallback Fallback class name (none if empty).
108 * @param string $cache XML cache directory. Empty is no caching will be done.
113 function __construct($fallback = '', $cache = '/tmp') // ~X2C
115 $this->parser = xml_parser_create();
116 $this->fallback = $fallback;
117 $this->cache = $cache;
118 xml_set_object($this->parser, $this);
119 xml_set_element_handler($this->parser, 'startElement', 'endElement');
120 xml_set_character_data_handler($this->parser, 'characterData');
131 function __destruct() // ~X2C
133 xml_parser_free($this->parser);
139 * XML parser start of element handler.
141 * @param resource $parser XML parser resource.
142 * @param string $name XML tag name.
143 * @param array $attrs XML tag attributes.
148 function startElement($parser, $name, $attrs) // ~X2C
150 $class = 'bife_' . strtolower(strtr($name, ':', '_'));
151 if (!class_exists($class)) {
153 strtr(ucwords(strtr(strtolower($name), ':', ' ')), ' ', '/') .
155 if (@include_once $inc) {
156 $this->includes[] = $inc;
159 if (class_exists($class)) {
160 $obj =& new $class($attrs);
161 // XXX - Does this check make sense?
162 if (!is_a($obj, 'bife_widget')) {
163 trigger_error("Class '$class' is not a BIFE_Widget.", E_USER_WARNING);
165 $this->stack[] =& $obj;
167 if ($this->fallback) {
168 $class = $this->fallback;
169 $obj =& new $class($name, $attrs);
170 if (!is_a($obj, 'bife_fallback')) {
171 trigger_error("Class '$class' is not a BIFE_Fallback.", E_USER_WARNING);
173 $this->stack[] =& $obj;
175 trigger_error("Class not found '$class'.", E_USER_ERROR);
183 * XML parser end of element handler.
185 * @param resource $parser XML parser resource.
186 * @param string $name XML tag name.
191 function endElement($parser, $name) // ~X2C
194 $current =& $this->stack[key($this->stack)];
195 array_pop($this->stack);
197 $parent =& $this->stack[key($this->stack)];
199 $parent->addContents($current);
201 $this->root =& $current;
208 * XML parser character data handler.
210 * @param resource $parser XML parser resource.
211 * @param string $data XML character data.
216 function characterData($parser, $data) // ~X2C
219 $current =& $this->stack[key($this->stack)];
220 $current->addContents($data);
226 * Parse a string with XML data.
228 * @param string $data XML string to parse.
229 * @param bool $final Indicates if is the last string to parse.
234 function parse($data, $final = true) // ~X2C
236 if (!xml_parse($this->parser, $data, $final)) {
238 sprintf('XML error: %s at line %d.',
239 xml_error_string(xml_get_error_code($this->parser)),
240 xml_get_current_line_number($this->parser)
250 * Parse a XML file with a complete and valid XML document.
252 * @param string $filename Filename to parse.
254 * @return &BIFE_Widget
257 function &parseFile($filename) // ~X2C
260 $cache = $this->cache . '/' . 'bife_parser_cache' . strtr(realpath($filename), '/', '_');
261 if (@filemtime($cache) > @filemtime($filename)) {
262 $file = file($cache);
263 foreach(unserialize(trim(array_shift($file))) as $required) {
264 include_once $required;
266 return unserialize(join('', $file));
269 if ($fp = @fopen($filename, 'r')) {
270 while ($data = fread($fp, 4096)) {
271 $this->parse($data, feof($fp));
274 trigger_error("Could not open BIFE XML input file '$filename'.",
279 $fp = fopen($cache, 'w');
280 fputs($fp, serialize($this->includes) . "\n");
281 fputs($fp, serialize($this->root));
290 * Parse a XML string with a complete and valid XML document.
292 * @param string $data XML data to parse.
294 * @return &BIFE_Widget
297 function &parseString($data) // ~X2C
299 $this->parse($data, true);
304 } // -X2C Class :Parser