register_hook('PARSER_WIKITEXT_PREPROCESS', 'BEFORE', $this, '_doreplace'); $controller->register_hook('PARSER_HANDLER_DONE', 'BEFORE', $this, '_fixsecedit'); $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, '_cache_control'); } function _replacecallback($hits) { return ($this->autoindexer++); } //trigger function _doreplace(&$event, $param) { global $ID; require_once(dirname(__FILE__) . "/class.evalmath.php"); $math = new evalmath(); $this->autoindexer = 0; $invalidate = false; $original = $event->data; $wikified = $original; //catch anonymous access $username=isset($_SERVER['REMOTE_USER'])?$_SERVER['REMOTE_USER']:"anonymous"; //get const definitions $data = array(); if (preg_match('/]*>([^<]*)<\/const>/', $event->data, $data) > 0) { //split entries //var_dump($data);exit; $data = array_pop($data); $data = preg_split('/[\r\n]+/', $data, -1, PREG_SPLIT_NO_EMPTY); //process wiki-data $autoindex = 0; foreach ($data as $entry) { //normal const $item = explode("=", trim($entry), 2); if (count($item) === 2) { //special string-replace switch ($item[1]) { case "%USER%": $item[1] = $username; $invalidate = true; break; //pagename case "%ID%": $item[1] = noNS(cleanID(getID())); break; //pagename case "%NAMESPACE%": $item[1] = getNS(cleanID(getID())); break; //namespace case "%RANDOM%": $item[1] = strval(rand()); $invalidate = true; break; //random number case "%YEAR%": $item[1] = date("Y"); break; //current year case "%MONTH%": $item[1] = date("m"); break; //current month case "%MONTHNAME%": $item[1] = date("F"); break; //current month case "%WEEK%": $item[1] = date("W"); $invalidate = true; break; //current week (iso) case "%DAY%": $item[1] = date("d"); $invalidate = true; break; //current day case "%DAYNAME%": $item[1] = date("l"); $invalidate = true; break; //current day case "%HOUR%": $item[1] = date("H"); $invalidate = true; break; //current hour case "%MINUTE%": $item[1] = date("i"); $invalidate = true; break; //current minute case "%SECOND%": $item[1] = date("s"); $invalidate = true; break; //current second case "%UNIXEPOCH%": $item[1] = date("U"); $invalidate = true; break; //current unix timestamp case "%AUTOINDEX%": $item[1] = "%%INDEX#" . (++$autoindex) . "%%"; //special automatic indexer break; case "%REVISION%": $tmp_info = pageinfo(); $item[1] = $tmp_info['lastmod']; break; //current revision number (unix timestamp) case "%LASTMOD%": $tmp_info = pageinfo(); $item[1] = strftime("%Y%m%d_%H%M%S", $tmp_info['lastmod']); break; //last modification date default: $item[1] = trim($item[1]); break; } //replace in wiki $wikified = str_replace("%%" . trim($item[0]) . "%%", $item[1], $wikified); $wikified = str_replace("§§" . trim($item[0]) . "§§", $item[1], $wikified); //load evaluator @$math->assign_and_evaluate($item[0]."=".$item[1]); } else { //evaluate expression $item = explode(":", $entry); if (count($item) === 2) { $wikified = str_replace("%%" . trim($item[0]) . "%%", @$math->assign_and_evaluate($item[1]), $wikified); $wikified = str_replace("§§" . trim($item[0]) . "§§", @$math->assign_and_evaluate($item[1]), $wikified); } } } //autoindex? while ($autoindex > 0) { $this->autoindexer = 1; //replace all $wikified = preg_replace_callback("|%%INDEX#" . $autoindex . "%%|", array( $this, "_replacecallback" ), $wikified); $autoindex--; } $event->data = $wikified; $original = explode("\n", $original); $wikified = explode("\n", $wikified); $this->offsets[$ID] = array(); // fill offset array to deal with section editing issues for ($l = 0; $l < count($wikified); $l++) { // record offsets at the start of this line $this->offsets[$ID][] = array( 'pos' => $char_pos, 'offset' => $text_offset ); // calculate position / offset for next line $char_pos += strlen($wikified[$l]) + 1; $text_offset += strlen($wikified[$l]) - strlen($original[$l]); //echo '(' . $char_pos . '/' . $text_offset . ')' . ' '; } } //save invalidation info to metadata p_set_metadata($ID, array( 'plugin_const' => array( 'invalidate' => $invalidate ) ), false, true); } /** * force cache invalidation for certain constants */ function _cache_control(&$event, $param) { global $conf; $cache =& $event->data; if ((isset($cache->page) === true) && ($cache->mode === "i")) { //cache purge requested? $const = p_get_metadata($cache->page, 'plugin_const'); //force initial purge if (!isset($const['invalidate'])) { $const['invalidate'] = true; } $cache->depends["purge"] = $const["invalidate"]; } } /** * modifying the raw data has as side effect that the sectioning is based on the * modified data, not the original. This means that after processing, we need to * adjust the section start/end markers so that they point to start/end positions * in the original data, not the modified data. */ function _fixsecedit(&$event, $param) { $calls =& $event->data->calls; $count = count($calls); // iterate through the instruction list and set the file offset values // back to the values they would be if no const syntax has been added by this plugin for ($i = 0; $i < $count; $i++) { if (in_array($calls[$i][0],array( 'section_open', 'section_close', 'header', 'p_open', //'table_close', //'table_open', ))) { $calls[$i][2] = $this->_convert($calls[$i][2]); } if (in_array($calls[$i][0],array('header','table_open'))) { $calls[$i][1][2] = $this->_convert($calls[$i][1][2]); } if(in_array($calls[$i][0],array('table_close'))) { $calls[$i][1][0] = $this->_convert($calls[$i][1][0]); } // be aware of headernofloat plugin if ($calls[$i][0] === 'plugin' && $calls[$i][1][0] === 'headernofloat') { $calls[$i][1][1]['pos'] = $this->_convert($calls[$i][1][1]['pos']); $calls[$i][2] = $this->_convert($calls[$i][2]); } //if($calls[$i][0] == 'table_close') } } /** * Convert modified raw wiki offset value pos back to the unmodified value */ function _convert($pos) { global $ID; if(!array_key_exists($ID,$this->offsets)) return $pos; // find the offset that applies to this character position $offset = 0; foreach ($this->offsets[$ID] as $tuple) { if ($pos >= $tuple['pos']) { $offset = $tuple['offset']; } else { break; } } // return corrected position return $pos - $offset; } }