3 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
\r
4 * Copyright (C) 2002-2005 The Nucleus Group
\r
6 * This program is free software; you can redistribute it and/or
\r
7 * modify it under the terms of the GNU General Public License
\r
8 * as published by the Free Software Foundation; either version 2
\r
9 * of the License, or (at your option) any later version.
\r
10 * (see nucleus/documentation/index.html#license for more info)
\r
13 * @license http://nucleuscms.org/license.txt GNU General Public License
\r
14 * @copyright Copyright (C) 2002-2005 The Nucleus Group
\r
15 * @version $Id: PARSER.php,v 1.4 2005-08-13 07:33:02 kimitake Exp $
\r
16 * $NucleusJP: PARSER.php,v 1.3 2005/03/12 06:19:05 kimitake Exp $
\r
20 * This is the parser class of Nucleus. It is used for various things (skin parsing,
\r
21 * form generation, ...)
\r
25 // array with the names of all allowed actions
\r
28 // reference to actions handler
\r
31 // delimiters that can be used for skin/templatevars
\r
34 // parameter delimiter (to separate skinvar params)
\r
37 // usually set to 0. When set to 1, all skinvars are allowed regardless of $actions
\r
38 var $norestrictions;
\r
41 * Creates a new parser object with the given allowed actions
\r
42 * and the given handler
\r
44 * @param $allowedActions array
\r
45 * @param $handler class object with functions for each action (reference)
\r
46 * @param $delim optional delimiter
\r
47 * @param $paramdelim optional parameterdelimiter
\r
49 function PARSER($allowedActions, &$handler, $delim = '(<%|%>)', $pdelim = ',') {
\r
50 $this->actions = $allowedActions;
\r
51 $this->handler =& $handler;
\r
52 $this->delim = $delim;
\r
53 $this->pdelim = $pdelim;
\r
54 $this->norestrictions = 0; // set this to 1 to disable checking for allowedActions
\r
58 * Parses the given contents and outputs it
\r
60 function parse(&$contents) {
\r
62 $pieces = preg_split('/'.$this->delim.'/',$contents);
\r
64 $maxidx = sizeof($pieces);
\r
65 for ($idx = 0;$idx<$maxidx;$idx++) {
\r
66 echo $pieces[$idx];
\r
68 $this->doAction($pieces[$idx]);
\r
76 function doAction($action) {
\r
79 if (!$action) return;
\r
81 // split into action name + arguments
\r
82 if (strstr($action,'(')) {
\r
83 $paramStartPos = strpos($action, '(');
\r
84 $params = substr($action, $paramStartPos + 1, strlen($action) - $paramStartPos - 2);
\r
85 $action = substr($action, 0, $paramStartPos);
\r
86 $params = explode ($this->pdelim, $params);
\r
89 // for PHP versions lower than 4.0.6:
\r
90 // - add // before '$params = ...'
\r
91 // - remove // before 'foreach'
\r
92 $params = array_map('trim',$params);
\r
93 // foreach ($params as $key => $value) { $params[$key] = trim($value); }
\r
99 $actionlc = strtolower($action);
\r
101 // skip execution of skinvars while inside an if condition which hides this part of the page
\r
102 if (!$this->handler->if_currentlevel && ($actionlc != 'else') && ($actionlc != 'endif') && (substr($actionlc,0,2) != 'if'))
\r
105 if (in_array($actionlc, $this->actions) || $this->norestrictions ) {
\r
106 // when using PHP versions lower than 4.0.5, uncomment the line before
\r
107 // and comment the call_user_func_array call
\r
108 //$this->call_using_array($action, $this->handler, $params);
\r
109 call_user_func_array(array(&$this->handler,'parse_' . $actionlc), $params);
\r
111 // redirect to plugin action if possible
\r
112 if (in_array('plugin', $this->actions) && $manager->pluginInstalled('NP_'.$action))
\r
113 $this->doAction('plugin('.$action.$this->pdelim.implode($this->pdelim,$params).')');
\r
115 echo '<b>DISALLOWED (' , $action , ')</b>';
\r
121 * Calls a method using an array of parameters (for use with PHP versions lower than 4.0.5)
\r
122 * ( = call_user_func_array() function )
\r
124 function call_using_array($methodname, &$handler, $paramarray) {
\r
126 $methodname = 'parse_' . $methodname;
\r
128 if (!method_exists($handler, $methodname)) {
\r
132 $command = 'call_user_func(array(&$handler,$methodname)';
\r
133 for ($i = 0; $i<count($paramarray); $i++)
\r
134 $command .= ',$paramarray[' . $i . ']';
\r
136 eval($command); // execute the correct method
\r
139 function setProperty($property, $value) {
\r
141 $manager->setParserProperty($property, $value);
\r
144 function getProperty($name) {
\r
146 return $manager->getParserProperty($name);
\r
153 * This class contains parse actions that are available in all ACTION classes
\r
154 * e.g. include, phpinclude, parsedinclude, skinfile, ...
\r
156 * It should never be used on it's own
\r
158 class BaseActions {
\r
160 // depth level for includes (max. level is 3)
\r
163 // array of evaluated conditions (true/false). The element at the end is the one for the most nested
\r
165 var $if_conditions;
\r
167 // at all times, can be evaluated to either true if the current block needs to be displayed. This
\r
168 // variable is used to decide to skip skinvars in parts that will never be outputted.
\r
169 var $if_currentlevel;
\r
171 // contains a search string with keywords that need to be highlighted. These get parsed into $aHighlight
\r
174 // array of keywords that need to be highlighted in search results (see the highlight()
\r
175 // and parseHighlight() methods)
\r
179 // reference to the parser object that is using this object as actions-handler
\r
184 function BaseActions() {
\r
187 // if nesting level
\r
188 $this->if_conditions = array(); // array on which condition values are pushed/popped
\r
189 $this->if_currentlevel = 1; // 1 = current level is displayed; 0 = current level not displayed
\r
192 $this->strHighlight = ''; // full highlight
\r
193 $this->aHighlight = array(); // parsed highlight
\r
197 // include file (no parsing of php)
\r
198 function parse_include($filename) {
\r
199 @readfile($this->getIncludeFileName($filename));
\r
202 // php-include file
\r
203 function parse_phpinclude($filename) {
\r
204 includephp($this->getIncludeFileName($filename));
\r
207 function parse_parsedinclude($filename) {
\r
208 // check current level
\r
209 if ($this->level > 3) return; // max. depth reached (avoid endless loop)
\r
210 $filename = $this->getIncludeFileName($filename);
\r
211 if (!file_exists($filename)) return '';
\r
213 $fsize = filesize($filename);
\r
215 // nothing to include
\r
219 $this->level = $this->level + 1;
\r
222 $fd = fopen ($filename, 'r');
\r
223 $contents = fread ($fd, $fsize);
\r
226 // parse file contents
\r
227 $this->parser->parse($contents);
\r
229 $this->level = $this->level - 1;
\r
233 * Returns the correct location of the file to be included, according to
\r
234 * parser properties
\r
236 * IF IncludeMode = 'skindir' => use skindir
\r
238 function getIncludeFileName($filename) {
\r
239 // leave absolute filenames and http urls as they are
\r
241 (substr($filename,0,1) == '/')
\r
242 || (substr($filename,0,7) == 'http://')
\r
243 || (substr($filename,0,6) == 'ftp://')
\r
247 $filename = PARSER::getProperty('IncludePrefix') . $filename;
\r
248 if (PARSER::getProperty('IncludeMode') == 'skindir') {
\r
250 return $DIR_SKINS . $filename;
\r
257 * Inserts an url relative to the skindir (useful when doing import/export)
\r
259 * e.g. <skinfile(default/myfile.sth)>
\r
261 function parse_skinfile($filename) {
\r
264 echo $CONF['SkinsURL'] . PARSER::getProperty('IncludePrefix') . $filename;
\r
268 * Sets a property for the parser
\r
270 function parse_set($property, $value) {
\r
271 PARSER::setProperty($property, $value);
\r
275 * Helper function: add if condition
\r
277 function _addIfCondition($condition) {
\r
279 array_push($this->if_conditions,$condition);
\r
281 $this->_updateTopIfCondition();
\r
286 function _updateTopIfCondition() {
\r
287 if (sizeof($this->if_conditions) == 0)
\r
288 $this->if_currentlevel = 1;
\r
290 $this->if_currentlevel = $this->if_conditions[sizeof($this->if_conditions) - 1];
\r
294 * returns the currently top if condition
\r
296 function _getTopIfCondition() {
\r
297 return $this->if_currentlevel;
\r
303 function parse_else() {
\r
304 if (sizeof($this->if_conditions) == 0) return;
\r
305 $old = $this->if_currentlevel;
\r
306 if (array_pop($this->if_conditions)) {
\r
308 $this->_addIfCondition(0);
\r
311 $this->_addIfCondition(1);
\r
316 * Ends a conditional if-block
\r
317 * see e.g. ifcat (BLOG), ifblogsetting (PAGEFACTORY)
\r
319 function parse_endif() {
\r
320 // we can only close what has been opened
\r
321 if (sizeof($this->if_conditions) == 0) return;
\r
323 if (array_pop($this->if_conditions)) {
\r
329 $this->_updateTopIfCondition();
\r
334 * Sets the search terms to be highlighted
\r
336 * @param $highlight
\r
337 * A series of search terms
\r
339 function setHighlight($highlight) {
\r
340 $this->strHighlight = $highlight;
\r
342 $this->aHighlight = parseHighlight($highlight);
\r
347 * Applies the highlight to the given piece of text
\r
350 * Data that needs to be highlighted
\r
351 * @see setHighlight
\r
353 function highlight(&$data) {
\r
354 if ($this->aHighlight)
\r
355 return highlight($data,$this->aHighlight,$this->template['SEARCH_HIGHLIGHT']);
\r