root/trunk/patXMLPretty.php

Revision 32, 13.2 kB (checked in by argh, 3 years ago)

Corrected docBlocks for compatibility with Zend Studio and phpDocumentor.

Line 
1 <?php
2 /**
3  * File containing the patXMLPretty class.
4  *
5  * @package        patXMLPretty
6  * @author        Sebastian 'The Argh' Mordziol <argh@php-tools.net>
7  * @see         patXMLPretty
8  */
9
10 /**
11  * Error: Invalid configuration reader object
12  */
13  define( 'PATXMLPRETTY_ERROR_INVALID_CONFIG_READER', 'patXMLPretty:01' );
14
15 /**
16  * Error: Missing a vital component
17  */
18  define( 'PATXMLPRETTY_ERROR_COMPONENT_MISSING', 'patXMLPretty:02' );
19
20 /**
21  * Error: Internal file not found
22  */
23  define( 'PATXMLPRETTY_ERROR_FILE_NOT_FOUND', 'patXMLPretty:03' );
24
25 /**
26  * Error: Internal file class not found
27  */
28  define( 'PATXMLPRETTY_ERROR_CLASS_NOT_FOUND', 'patXMLPretty:04' );
29
30 /**
31  * Error: File could not be included
32  */
33  define( 'PATXMLPRETTY_ERROR_COULD_NOT_INCLUDE_FILE', 'patXMLPretty:05' );
34
35 /**
36  * Error: XML parsing process failed
37  */
38  define( 'PATXMLPRETTY_ERROR_XML_PARSING_FAILED', 'patXMLPretty:06' );
39
40 /**
41  * Error: XML could not be read from target file
42  */
43  define( 'PATXMLPRETTY_ERROR_COULD_NOT_READ_XML_FROM_FILE', 'patXMLPretty:07' );
44
45 /**
46  * The base directory from which patXMLPretty operates
47  */
48  define( 'PATXMLPRETTY_BASE_DIR', dirname( __FILE__ ) );
49
50 /**
51  * Lightweight and fast XML syntax highlighting package with
52  * inline source documentation capabilities.
53  *
54  * @package        patXMLPretty
55  * @author        Sebastian 'The Argh' Mordziol <argh@php-tools.net>
56  * @author        Stephan Schmidt <schst@php.net>
57  * @version        0.1.0
58  * @license        LGPL
59  * @link        http://www.php-tools.net
60  */
61 class patXMLPretty
62 {
63    /**
64     * Stores the configuration reader object used to load
65     * and access tag syntax definitions.
66     *
67     * @access    private
68     * @var        patXMLReader_ConfigReader
69     * @see         setConfigReader()
70     * @see         createConfigReader()
71     */
72     var $configReader = null;
73
74    /**
75     * Stores the renderer object used to render the highlighted
76     * syntax.
77     *
78     * @access    private
79     * @var        patXMLPretty_Renderer
80     * @see         setRenderer()
81     * @see         createRenderer()
82     */
83     var $renderer = null;
84
85    /**
86     * Stores the parsing engine object used to parse the XML to highlight
87     *
88     * @access    private
89     * @var        patXMLPretty_Engine
90     * @see         setEngine()
91     * @see         createEngine()
92     */
93     var $engine = null;
94
95    /**
96     * Stores a list of folders in which patXMLPretty will look
97     * for modules like renderers and config readers to allow
98     * external repositories.
99     *
100     * @access    private
101     * @var        array
102     * @see         addClassRepository()
103     * @see         getClassRepositories()
104     */
105     var $classRepositories = array();
106
107    /**
108     * Sets the configuration reader to use to load and access the tag
109     * coloring and syntax definitions.
110     *
111     * @access    public
112     * @param    patXMLPretty_ConfigReader
113     * @return    bool true|patError
114     * @see         createConfigReader()
115     * @see         $configReader
116     */
117     function setConfigReader( &$configReader )
118     {
119         if( !is_a( $configReader, 'patXMLPretty_ConfigReader' ) ) {
120             $error = patErrorManager::raiseError(
121                 PATXMLPRETTY_ERROR_INVALID_CONFIG_READER,
122                 'Invalid configuration reader object',
123                 'The config reader you set is not a valid patXMLPretty configuration reader. '.
124                 'For reference, the argument given is a ['.gettype( $configReader ).'].'
125             );
126
127             return $error;
128         }
129
130         $this->configReader =& $configReader;
131         $result = true;
132         return $result;
133     }
134
135    /**
136     * Sets the renderer to use to render the highlighted content
137     *
138     * @access    public
139     * @param    patXMLPretty_Renderer
140     * @return    bool true|patError
141     * @see         createRenderer()
142     * @see         $renderer
143     */
144     function setRenderer( &$renderer )
145     {
146         if( !is_a( $renderer, 'patXMLPretty_Renderer' ) ) {
147             $error = patErrorManager::raiseError(
148                 PATXMLPRETTY_ERROR_INVALID_RENDERER,
149                 'Invalid renderer object',
150                 'The reader you set is not a valid patXMLPretty renderer. '.
151                 'For reference, the argument given is a ['.gettype( $renderer ).'].'
152             );
153
154             return $error;
155         }
156
157         $this->renderer =& $renderer;
158         $result = true;
159         return $result;
160     }
161
162    /**
163     * Sets the engine to use to parse the XML to highlight
164     *
165     * @access    public
166     * @param    patXMLPretty_Engine
167     * @return    bool true|patError
168     * @see         createEngine()
169     * @see         $engine
170     */
171     function setEngine( &$engine )
172     {
173         if( !is_a( $engine, 'patXMLPretty_Engine' ) ) {
174             $error = patErrorManager::raiseError(
175                 PATXMLPRETTY_ERROR_INVALID_ENGINE,
176                 'Invalid engine object',
177                 'The engine you set is not a valid patXMLPretty parsing engine. '.
178                 'For reference, the argument given is a ['.gettype( $engine ).'].'
179             );
180
181             return $error;
182         }
183
184         $this->engine =& $engine;
185         $result = true;
186         return $result;
187     }
188
189    /**
190     * Creates a configuration reader object. patXMLPretty uses configuration
191     * reader objects to access tag syntax information. With this factory method
192     * you can create the reader object that best fits your needs and set it via
193     * the {@link setConfigReader()} method.
194     *
195     * Note: this is not mandatory, as patXMLPretty will use the default config
196     * reader automatically if no reader has been specifically set.
197     *
198     * @access    public
199     * @param    string
200     * @param     array
201     * @return    patXMLPretty_ConfigReader|patError
202     */
203     function &createConfigReader( $type, $options = array() )
204     {
205         $configReader =& $this->_createModule( 'ConfigReader', $type, $options );
206         return $configReader;
207     }
208
209    /**
210     * Creates a renderer object. patXMLPretty uses renderer objects to create
211     * the highlighted content. With this factory method you can create a renderer
212     * object that best fits your needs and set it via the {@link setRenderer()} method.
213     *
214     * Note: this is not mandatory, as patXMLPretty will use a default renderer
215     * automatically if no renderer has been specifically set.
216     *
217     * @access    private
218     * @param    string
219     * @param     array
220     * @return    patXMLPretty_Renderer|patError
221     */
222     function &createRenderer( $type, $options = array() )
223     {
224         $renderer =& $this->_createModule( 'Renderer', $type, $options );
225         return $renderer;
226     }
227
228    /**
229     * Creates a parsing engine object. patXMLPretty uses parser objects to parse the
230     * XML data to highlight. With this factory method you can create a parsing engine
231     * object that best fits your needs and set it via the {@link setEngine()} method.
232     *
233     * Note: this is not mandatory, as patXMLPretty will use a default engine
234     * automatically if no engine has been specifically set.
235     *
236     * @access    private
237     * @param    string
238     * @param     array
239     * @return    patXMLPretty_Engine|patError
240     */
241     function &createEngine( $type, $options = array() )
242     {
243         $engine =& $this->_createModule( 'Engine', $type );
244         return $engine;
245     }
246
247    /**
248     * Generic method to create a patXMLPretty module object, like
249     * a renderer or config reader.
250     *
251     * @access    private
252     * @param    string
253     * @param     string
254     * @param     array
255     * @return    object
256     */
257     function &_createModule( $type, $name, $options = array() )
258     {
259         // include the base module file
260         $moduleBase = PATXMLPRETTY_BASE_DIR.'/patXMLPretty/Module.php';
261         if( !@include_once $moduleBase ) {
262             $error = patErrorManager::raiseError(
263                 PATXMLPRETTY_ERROR_COMPONENT_MISSING,
264                 'Missing vital component',
265                 'Could not find the base module component in path ['.$moduleBase.']. '.
266                 'Please check your patXMLPretty installation.'
267             );
268
269             return $error;
270         }
271
272         // include the base reader file
273         $baseFile = PATXMLPRETTY_BASE_DIR.'/patXMLPretty/'.$type.'.php';
274         if( !@include_once $baseFile ) {
275             $error = patErrorManager::raiseError(
276                 PATXMLPRETTY_ERROR_COMPONENT_MISSING,
277                 'Missing vital component',
278                 'Could not find the base config reader component in path ['.$baseFile.']. '.
279                 'Please check your patXMLPretty installation.'
280             );
281
282             return $error;
283         }
284
285         $class = 'patXMLPretty_'.str_replace( '/', '_', $type ).'_'.str_replace( '/', '_', $name );
286         $file = $type.'/'.$name.'.php';
287
288         $success = $this->_includeFile( $file, $class );
289         if( patErrorManager::isError( $success ) ) {
290             return $success;
291         }
292
293         $module =& new $class;
294         $module->setOptions( $options );
295         $module->setPretty( $this );
296
297         return $module;
298     }
299
300    /**
301     * Finds a file in the available class repositories
302     *
303     * @access    private
304     * @param    string
305     * @return    string|bool false
306     */
307     function _findFile( $file )
308     {
309         // now search for the requested file in all
310         // available class repositories.
311         $repositories = $this->getClassRepositories();
312         foreach( $repositories as $repository ) {
313             $file = $repository.'/patXMLPretty/'.$file;
314             if( file_exists( $file ) ) {
315                 return $file;
316             }
317         }
318
319         $result = false;
320         return $result;
321     }
322
323    /**
324     * Includes an internal patXMLPretty file, like a configuration
325     * reader or such, from any of the available class repositories.
326     *
327     * @access    private
328     * @param    string
329     * @param     string
330     * @return    bool true|patError
331     */
332     function _includeFile( $file, $class = null )
333     {
334         // find the file in the available repositories
335         $fullPath = $this->_findFile( $file );
336         if( !$fullPath ) {
337             $error = patErrorManager::raiseError(
338                 PATXMLPRETTY_ERROR_FILE_NOT_FOUND,
339                 'File not found',
340                 'Could not find the file ['.$file.'] in any of the available class '.
341                 'repository folders.'
342             );
343
344             return $error;
345         }
346
347         // try to include the file
348         if( !include_once $fullPath ) {
349             $error = patErrorManager::raiseError(
350                 PATXMLPRETTY_ERROR_COULD_NOT_INCLUDE_FILE,
351                 'Cannot include file',
352                 'The file ['.$file.'] exists, but cannot be included. Please make sure that '.
353                 'sufficient access rights are set so that I may include this file.'
354             );
355
356             return $error;
357         }
358
359         // if a class is required to be present in the file, check that too
360         if( !is_null( $class ) && !class_exists( $class ) ) {
361             $error = patErrorManager::raiseError(
362                 PATXMLPRETTY_ERROR_CLASS_NOT_FOUND,
363                 'Required class does not exist',
364                 'The file ['.$file.'] could be included, but the required class ['.$class.'] '.
365                 'could not be found. There is either a mismatch between the file name and the '.
366                 'containing class, or it is the wrong file.'
367             );
368
369             return $error;
370         }
371
372         $result = true;
373         return $result;
374     }
375
376    /**
377     * Adds a directory to the list of class repositories in which
378     * patXMLPretty will look for configuration readers and other
379     * assets. You can use this to use your own classes without
380     * copying them to the patXMLPretty directory tree.
381     *
382     * The folder structure has to follow that of the patXMLPretty
383     * package for the files to be found.
384     *
385     * @access    public
386     * @param    string
387     * @see         getClassRepositories()
388     * @see         $classRepositories
389     */
390     function addClassRepository( $dir )
391     {
392         $this->classRepositories[] = $dir;
393     }
394
395    /**
396     * Returns the current list of folders in which patXMLPretty
397     * searches for subclasses.
398     *
399     * @access    public
400     * @return    array
401     * @see         addClassRepository()
402     * @see         $classRepositories
403     */
404     function getClassRepositories()
405     {
406         $repositories = $this->classRepositories;
407         array_unshift( $repositories, PATXMLPRETTY_BASE_DIR );
408         return $repositories;
409     }
410
411    /**
412     * Retrieves a reference to the engine object
413     * that is currently used.
414     *
415     * @access    public
416     * @return    object|null
417     * @see        setEngine()
418     * @see         $engine
419     */
420     function &getEngine()
421     {
422         return $this->engine;
423     }
424
425    /**
426     * Initializes the parsing process by setting up all needed
427     * data and checking everything required is present.
428     *
429     * @access    private
430     * @return    bool true|patError
431     */
432     function _init()
433     {
434         // if no config reader is present, we create and use the default one.
435         if( is_null( $this->configReader ) ) {
436             $reader =& $this->createConfigReader( 'Default' );
437             if( patErrorManager::isError( $reader ) ) {
438                 return $reader;
439             }
440
441             $this->setConfigReader( $reader );
442         }
443
444         $success = $this->configReader->read();
445         if( patErrorManager::isError( $success ) ) {
446             return $success;
447         }
448
449         // if no renderer is present, we create and use the default one.
450         if( is_null( $this->renderer ) ) {
451             $renderer =& $this->createRenderer( 'HTML/Simple' );
452             if( patErrorManager::isError( $renderer ) ) {
453                 return $renderer;
454             }
455
456             $this->setRenderer( $renderer );
457         }
458
459         // if no engine has been set, create and use the default one.
460         if( is_null( $this->engine ) ) {
461             $engine =& $this->createEngine( 'Automatic' );
462             if( patErrorManager::isError( $engine ) ) {
463                 return $engine;
464             }
465
466             $this->setEngine( $engine );
467         }
468
469         $result = true;
470         return $result;
471     }
472
473    /**
474     * Parses an XML file, syntax-highlights it and returns
475     * the rendered content.
476     *
477     * @access    public
478     * @param    string
479     * @return    string|patError
480     * @see         parseString()
481     */
482     function parseFile( $file )
483     {
484         $xmlSource = @file_get_contents( $file );
485         if( !$xmlSource ) {
486             $error = patErrorManager::raiseError(
487                 PATXMLPRETTY_ERROR_COULD_NOT_READ_XML_FROM_FILE,
488                 'Could not open XML file',
489                 'Contents of target XML file ['.$file.'] could not be read.'
490             );
491
492             return $error;
493         }
494
495         $result = $this->parseString( $xmlSource );
496         return $result;
497     }
498
499    /**
500     * Parses and XML string, syntax-highlights it and returns
501     * the rendered content.
502     *
503     * @access    public
504     * @param    string
505     * @return    string|patError
506     * @see         parseFile()
507     */
508     function parseString( $xmlSource )
509     {
510         $success = $this->_init();
511         if( patErrorManager::isError( $success ) ) {
512             return $success;
513         }
514
515         // tell everyone who is whom :)
516         $this->renderer->setConfigReader( $this->configReader );
517         $this->engine->setRenderer( $this->renderer );
518         $this->engine->setConfigReader( $this->configReader );
519
520         $structure = $this->engine->parse( $xmlSource );
521         if( patErrorManager::isError( $structure ) ) {
522             return $structure;
523         }
524
525         $rendered = $this->renderer->render( $structure['document'], $structure['elements'], $structure['doctype'] );
526         return $rendered;
527     }
528 }
529 ?>
Note: See TracBrowser for help on using the browser.