OSDN Git Service

This commit was generated by cvs2svn to compensate for changes in r4,
[nucleus-jp/nucleus-jp-ancient.git] / euc / nucleus / libs / PARSER.php
1 <?php
2 /**
3   * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/) 
4   * Copyright (C) 2002-2004 The Nucleus Group
5   *
6   * This program is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU General Public License
8   * as published by the Free Software Foundation; either version 2
9   * of the License, or (at your option) any later version.
10   * (see nucleus/documentation/index.html#license for more info)
11   *
12   * $Id: PARSER.php,v 1.1.1.1 2005-02-28 07:14:13 kimitake Exp $
13   */
14  
15 /**
16  * This is the parser class of Nucleus. It is used for various things (skin parsing,
17  * form generation, ...)
18  */
19 class PARSER {
20
21         // array with the names of all allowed actions
22         var $actions;
23         
24         // reference to actions handler
25         var $handler;
26         
27         // delimiters that can be used for skin/templatevars
28         var $delim;
29         
30         // parameter delimiter (to separate skinvar params)
31         var $pdelim;
32         
33         // usually set to 0. When set to 1, all skinvars are allowed regardless of $actions
34         var $norestrictions;
35         
36         /**
37          * Creates a new parser object with the given allowed actions 
38          * and the given handler
39          *
40          * @param $allowedActions array
41          * @param $handler class object with functions for each action (reference)
42          * @param $delim optional delimiter
43          * @param $paramdelim optional parameterdelimiter        
44          */
45         function PARSER($allowedActions, &$handler, $delim = '(<%|%>)', $pdelim = ',') {
46                 $this->actions = $allowedActions;
47                 $this->handler =& $handler;
48                 $this->delim = $delim;
49                 $this->pdelim = $pdelim;
50                 $this->norestrictions = 0;      // set this to 1 to disable checking for allowedActions
51         }
52         
53         /**
54          * Parses the given contents and outputs it
55          */
56         function parse(&$contents) {
57         
58                 $pieces = preg_split('/'.$this->delim.'/',$contents);
59                 
60                 $maxidx = sizeof($pieces);
61                 for ($idx = 0;$idx<$maxidx;$idx++) {
62                         echo $pieces[$idx];             
63                         $idx++;
64                         $this->doAction($pieces[$idx]);
65                 }
66         }
67         
68
69         /**
70           * handle an action 
71           */
72         function doAction($action) {
73                 global $manager;
74
75                 if (!$action) return;
76                 
77                 // split into action name + arguments
78                 if (strstr($action,'(')) {
79                         $paramStartPos = strpos($action, '(');
80                         $params = substr($action, $paramStartPos + 1, strlen($action) - $paramStartPos - 2);
81                         $action = substr($action, 0, $paramStartPos);
82                         $params = explode ($this->pdelim, $params);
83                         
84                         // trim parameters 
85                         // for PHP versions lower than 4.0.6:
86                         //   - add // before '$params = ...' 
87                         //   - remove // before 'foreach'
88                         $params = array_map('trim',$params);
89                         // foreach ($params as $key => $value) { $params[$key] = trim($value); }                        
90                 } else {
91                         // no parameters
92                         $params = array();
93                 }
94         
95                 $actionlc = strtolower($action);
96                 
97                 // skip execution of skinvars while inside an if condition which hides this part of the page
98                 if (!$this->handler->if_currentlevel && ($actionlc != 'else') && ($actionlc != 'endif') && (substr($actionlc,0,2) != 'if'))
99                         return;
100         
101                 if (in_array($actionlc, $this->actions) || $this->norestrictions ) {
102                         // when using PHP versions lower than 4.0.5, uncomment the line before
103                         // and comment the call_user_func_array call
104                         //$this->call_using_array($action, $this->handler, $params);
105                         call_user_func_array(array(&$this->handler,'parse_' . $actionlc), $params);
106                 } else {
107                         // redirect to plugin action if possible
108                         if (in_array('plugin', $this->actions) && $manager->pluginInstalled('NP_'.$action))
109                                 $this->doAction('plugin('.$action.$this->pdelim.implode($this->pdelim,$params).')');
110                         else
111                                 echo '<b>DISALLOWED (' , $action , ')</b>';
112                 }
113                 
114         }
115         
116         /**
117           * Calls a method using an array of parameters (for use with PHP versions lower than 4.0.5)
118           * ( = call_user_func_array() function )
119           */
120         function call_using_array($methodname, &$handler, $paramarray) {
121
122                 $methodname = 'parse_' . $methodname;
123                 
124                 if (!method_exists($handler, $methodname)) {
125                         return;
126                 }
127
128                 $command = 'call_user_func(array(&$handler,$methodname)';
129                 for ($i = 0; $i<count($paramarray); $i++)
130                         $command .= ',$paramarray[' . $i . ']';
131                 $command .= ');';
132                 eval($command); // execute the correct method
133         }
134         
135         function setProperty($property, $value) {
136                 global $manager;
137                 $manager->setParserProperty($property, $value);
138         }
139         
140         function getProperty($name) {
141                 global $manager;
142                 return $manager->getParserProperty($name);
143         }
144         
145         
146 }
147
148 /**
149  * This class contains parse actions that are available in all ACTION classes
150  * e.g. include, phpinclude, parsedinclude, skinfile, ...
151  *
152  * It should never be used on it's own
153  */
154 class BaseActions {
155         
156         // depth level for includes (max. level is 3)
157         var $level;
158         
159         // array of evaluated conditions (true/false). The element at the end is the one for the most nested
160         // if block.
161         var $if_conditions;
162         
163         // at all times, can be evaluated to either true if the current block needs to be displayed. This 
164         // variable is used to decide to skip skinvars in parts that will never be outputted.
165         var $if_currentlevel;
166         
167         // contains a search string with keywords that need to be highlighted. These get parsed into $aHighlight
168         var $strHighlight;
169         
170         // array of keywords that need to be highlighted in search results (see the highlight() 
171         // and parseHighlight() methods)
172         var $aHighlight;
173         
174
175         // reference to the parser object that is using this object as actions-handler
176
177         var $parser;
178         
179
180         function BaseActions() {
181                 $this->level = 0; 
182                 
183                 // if nesting level
184                 $this->if_conditions = array(); // array on which condition values are pushed/popped
185                 $this->if_currentlevel = 1;             // 1 = current level is displayed; 0 = current level not displayed
186
187                 // highlights           
188                 $this->strHighlight = '';                       // full highlight
189                 $this->aHighlight = array();            // parsed highlight
190                 
191         }
192
193         // include file (no parsing of php)
194         function parse_include($filename) {
195                 @readfile($this->getIncludeFileName($filename));
196         }
197         
198         // php-include file 
199         function parse_phpinclude($filename) {
200                 includephp($this->getIncludeFileName($filename));
201         }       
202         // parsed include
203         function parse_parsedinclude($filename) {
204                 // check current level
205                 if ($this->level > 3) return;   // max. depth reached (avoid endless loop)
206                 $filename = $this->getIncludeFileName($filename);
207                 if (!file_exists($filename)) return '';
208                 
209                 $fsize = filesize($filename);
210                 
211                 // nothing to include
212                 if ($fsize <= 0)
213                         return;
214                 
215                 $this->level = $this->level + 1;
216                 
217                 // read file 
218                 $fd = fopen ($filename, 'r');
219                 $contents = fread ($fd, $fsize);
220                 fclose ($fd);           
221                 
222                 // parse file contents
223                 $this->parser->parse($contents);
224                 
225                 $this->level = $this->level - 1;                
226         }
227         
228         /**
229          * Returns the correct location of the file to be included, according to
230          * parser properties
231          *
232          * IF IncludeMode = 'skindir' => use skindir
233          */
234         function getIncludeFileName($filename) {
235                 // leave absolute filenames and http urls as they are
236                 if (
237                                 (substr($filename,0,1) == '/')
238                         ||      (substr($filename,0,7) == 'http://')
239                         ||      (substr($filename,0,6) == 'ftp://')                     
240                         )
241                         return $filename;
242         
243                 $filename = PARSER::getProperty('IncludePrefix') . $filename;
244                 if (PARSER::getProperty('IncludeMode') == 'skindir') {
245                         global $DIR_SKINS;
246                         return $DIR_SKINS . $filename;
247                 } else {
248                         return $filename;
249                 }
250         }
251         
252         /**
253          * Inserts an url relative to the skindir (useful when doing import/export)
254          *
255          * e.g. <skinfile(default/myfile.sth)>
256          */
257         function parse_skinfile($filename) {
258                 global $CONF;
259                 
260                 echo $CONF['SkinsURL'] . PARSER::getProperty('IncludePrefix') . $filename;
261         }
262         
263         /**
264          * Sets a property for the parser
265          */
266         function parse_set($property, $value) {
267                 PARSER::setProperty($property, $value);
268         }
269         
270         /**
271          * Helper function: add if condition
272          */
273         function _addIfCondition($condition) {
274         
275                 array_push($this->if_conditions,$condition);
276         
277                 $this->_updateTopIfCondition();
278                         
279                 ob_start();             
280         }
281         
282         function _updateTopIfCondition() {
283                 if (sizeof($this->if_conditions) == 0) 
284                         $this->if_currentlevel = 1;
285                 else
286                         $this->if_currentlevel = $this->if_conditions[sizeof($this->if_conditions) - 1];
287         }
288         
289         /**
290          * returns the currently top if condition
291          */
292         function _getTopIfCondition() {
293                 return $this->if_currentlevel;
294         }
295         
296         /**
297          * else
298          */
299         function parse_else() {
300                 if (sizeof($this->if_conditions) == 0) return;
301                 $old = $this->if_currentlevel;
302                 if (array_pop($this->if_conditions)) {
303                         ob_end_flush();
304                         $this->_addIfCondition(0);
305                 } else {
306                         ob_end_clean();
307                         $this->_addIfCondition(1);
308                 }
309         }
310         
311         /**
312          * Ends a conditional if-block 
313          * see e.g. ifcat (BLOG), ifblogsetting (PAGEFACTORY)
314          */
315         function parse_endif() {
316                 // we can only close what has been opened
317                 if (sizeof($this->if_conditions) == 0) return;
318                 
319                 if (array_pop($this->if_conditions)) {
320                         ob_end_flush();
321                 } else {
322                         ob_end_clean();
323                 }
324                 
325                 $this->_updateTopIfCondition();
326         }
327         
328         
329         /** 
330          * Sets the search terms to be highlighted
331          *
332          * @param $highlight
333          *              A series of search terms
334          */
335         function setHighlight($highlight) {     
336                 $this->strHighlight = $highlight;
337                 if ($highlight) {
338                         $this->aHighlight = parseHighlight($highlight); 
339                 }
340         }
341         
342         /**
343          * Applies the highlight to the given piece of text
344          *
345          * @param &$data
346          *              Data that needs to be highlighted
347          * @see setHighlight
348          */
349         function highlight(&$data) {
350                 if ($this->aHighlight)
351                         return highlight($data,$this->aHighlight,$this->template['SEARCH_HIGHLIGHT']);
352                 else
353                         return $data;
354         }
355         
356         
357
358 }
359  
360 ?>