3 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
4 * Copyright (C) 2002-2004 The Nucleus Group
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)
12 * $Id: PARSER.php,v 1.1.1.1 2005-02-28 07:14:13 kimitake Exp $
16 * This is the parser class of Nucleus. It is used for various things (skin parsing,
17 * form generation, ...)
21 // array with the names of all allowed actions
24 // reference to actions handler
27 // delimiters that can be used for skin/templatevars
30 // parameter delimiter (to separate skinvar params)
33 // usually set to 0. When set to 1, all skinvars are allowed regardless of $actions
37 * Creates a new parser object with the given allowed actions
38 * and the given handler
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
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
54 * Parses the given contents and outputs it
56 function parse(&$contents) {
58 $pieces = preg_split('/'.$this->delim.'/',$contents);
60 $maxidx = sizeof($pieces);
61 for ($idx = 0;$idx<$maxidx;$idx++) {
64 $this->doAction($pieces[$idx]);
72 function doAction($action) {
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);
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); }
95 $actionlc = strtolower($action);
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'))
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);
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).')');
111 echo '<b>DISALLOWED (' , $action , ')</b>';
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 )
120 function call_using_array($methodname, &$handler, $paramarray) {
122 $methodname = 'parse_' . $methodname;
124 if (!method_exists($handler, $methodname)) {
128 $command = 'call_user_func(array(&$handler,$methodname)';
129 for ($i = 0; $i<count($paramarray); $i++)
130 $command .= ',$paramarray[' . $i . ']';
132 eval($command); // execute the correct method
135 function setProperty($property, $value) {
137 $manager->setParserProperty($property, $value);
140 function getProperty($name) {
142 return $manager->getParserProperty($name);
149 * This class contains parse actions that are available in all ACTION classes
150 * e.g. include, phpinclude, parsedinclude, skinfile, ...
152 * It should never be used on it's own
156 // depth level for includes (max. level is 3)
159 // array of evaluated conditions (true/false). The element at the end is the one for the most nested
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;
167 // contains a search string with keywords that need to be highlighted. These get parsed into $aHighlight
170 // array of keywords that need to be highlighted in search results (see the highlight()
171 // and parseHighlight() methods)
175 // reference to the parser object that is using this object as actions-handler
180 function BaseActions() {
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
188 $this->strHighlight = ''; // full highlight
189 $this->aHighlight = array(); // parsed highlight
193 // include file (no parsing of php)
194 function parse_include($filename) {
195 @readfile($this->getIncludeFileName($filename));
199 function parse_phpinclude($filename) {
200 includephp($this->getIncludeFileName($filename));
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 '';
209 $fsize = filesize($filename);
211 // nothing to include
215 $this->level = $this->level + 1;
218 $fd = fopen ($filename, 'r');
219 $contents = fread ($fd, $fsize);
222 // parse file contents
223 $this->parser->parse($contents);
225 $this->level = $this->level - 1;
229 * Returns the correct location of the file to be included, according to
232 * IF IncludeMode = 'skindir' => use skindir
234 function getIncludeFileName($filename) {
235 // leave absolute filenames and http urls as they are
237 (substr($filename,0,1) == '/')
238 || (substr($filename,0,7) == 'http://')
239 || (substr($filename,0,6) == 'ftp://')
243 $filename = PARSER::getProperty('IncludePrefix') . $filename;
244 if (PARSER::getProperty('IncludeMode') == 'skindir') {
246 return $DIR_SKINS . $filename;
253 * Inserts an url relative to the skindir (useful when doing import/export)
255 * e.g. <skinfile(default/myfile.sth)>
257 function parse_skinfile($filename) {
260 echo $CONF['SkinsURL'] . PARSER::getProperty('IncludePrefix') . $filename;
264 * Sets a property for the parser
266 function parse_set($property, $value) {
267 PARSER::setProperty($property, $value);
271 * Helper function: add if condition
273 function _addIfCondition($condition) {
275 array_push($this->if_conditions,$condition);
277 $this->_updateTopIfCondition();
282 function _updateTopIfCondition() {
283 if (sizeof($this->if_conditions) == 0)
284 $this->if_currentlevel = 1;
286 $this->if_currentlevel = $this->if_conditions[sizeof($this->if_conditions) - 1];
290 * returns the currently top if condition
292 function _getTopIfCondition() {
293 return $this->if_currentlevel;
299 function parse_else() {
300 if (sizeof($this->if_conditions) == 0) return;
301 $old = $this->if_currentlevel;
302 if (array_pop($this->if_conditions)) {
304 $this->_addIfCondition(0);
307 $this->_addIfCondition(1);
312 * Ends a conditional if-block
313 * see e.g. ifcat (BLOG), ifblogsetting (PAGEFACTORY)
315 function parse_endif() {
316 // we can only close what has been opened
317 if (sizeof($this->if_conditions) == 0) return;
319 if (array_pop($this->if_conditions)) {
325 $this->_updateTopIfCondition();
330 * Sets the search terms to be highlighted
333 * A series of search terms
335 function setHighlight($highlight) {
336 $this->strHighlight = $highlight;
338 $this->aHighlight = parseHighlight($highlight);
343 * Applies the highlight to the given piece of text
346 * Data that needs to be highlighted
349 function highlight(&$data) {
350 if ($this->aHighlight)
351 return highlight($data,$this->aHighlight,$this->template['SEARCH_HIGHLIGHT']);