はじまりの大地
This commit is contained in:
@@ -0,0 +1,625 @@
|
||||
<?php
|
||||
/**
|
||||
* Bureaucracy Plugin: Allows flexible creation of forms
|
||||
*
|
||||
* This plugin allows definition of forms in wiki pages. The forms can be
|
||||
* submitted via email or used to create new pages from templates.
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @author Adrian Lang <dokuwiki@cosmocode.de>
|
||||
*/
|
||||
// must be run within Dokuwiki
|
||||
use dokuwiki\Utf8\PhpString;
|
||||
|
||||
if(!defined('DOKU_INC')) die();
|
||||
|
||||
/**
|
||||
* All DokuWiki plugins to extend the parser/rendering mechanism
|
||||
* need to inherit from this class
|
||||
*/
|
||||
class syntax_plugin_bureaucracy extends DokuWiki_Syntax_Plugin {
|
||||
|
||||
private $form_id = 0;
|
||||
var $patterns = array();
|
||||
var $values = array();
|
||||
var $noreplace = null;
|
||||
var $functions = array();
|
||||
|
||||
/**
|
||||
* Prepare some replacements
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->prepareDateTimereplacements();
|
||||
$this->prepareNamespacetemplateReplacements();
|
||||
$this->prepareFunctions();
|
||||
}
|
||||
|
||||
/**
|
||||
* What kind of syntax are we?
|
||||
*/
|
||||
public function getType() {
|
||||
return 'substition';
|
||||
}
|
||||
|
||||
/**
|
||||
* What about paragraphs?
|
||||
*/
|
||||
public function getPType() {
|
||||
return 'block';
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to sort in?
|
||||
*/
|
||||
public function getSort() {
|
||||
return 155;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect pattern to lexer
|
||||
*
|
||||
* @param string $mode
|
||||
*/
|
||||
public function connectTo($mode) {
|
||||
$this->Lexer->addSpecialPattern('<form>.*?</form>', $mode, 'plugin_bureaucracy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler to prepare matched data for the rendering process
|
||||
*
|
||||
* @param string $match The text matched by the patterns
|
||||
* @param int $state The lexer state for the match
|
||||
* @param int $pos The character position of the matched text
|
||||
* @param Doku_Handler $handler The Doku_Handler object
|
||||
* @return bool|array Return an array with all data you want to use in render, false don't add an instruction
|
||||
*/
|
||||
public function handle($match, $state, $pos, Doku_Handler $handler) {
|
||||
$match = substr($match, 6, -7); // remove form wrap
|
||||
$lines = explode("\n", $match);
|
||||
$actions = $rawactions = array();
|
||||
$thanks = '';
|
||||
$labels = '';
|
||||
|
||||
// parse the lines into an command/argument array
|
||||
$cmds = array();
|
||||
while(count($lines) > 0) {
|
||||
$line = trim(array_shift($lines));
|
||||
if(!$line) continue;
|
||||
$args = $this->_parse_line($line, $lines);
|
||||
$args[0] = $this->_sanitizeClassName($args[0]);
|
||||
|
||||
if(in_array($args[0], array('action', 'thanks', 'labels'))) {
|
||||
if(count($args) < 2) {
|
||||
msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]), hsc($args[1])), -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// is action element?
|
||||
if($args[0] == 'action') {
|
||||
array_shift($args);
|
||||
$rawactions[] = array('type' => array_shift($args), 'argv' => $args);
|
||||
continue;
|
||||
}
|
||||
|
||||
// is thank you text?
|
||||
if($args[0] == 'thanks') {
|
||||
$thanks = $args[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
// is labels?
|
||||
if($args[0] == 'labels') {
|
||||
$labels = $args[1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($args[0], '_') === false) {
|
||||
$name = 'bureaucracy_field' . $args[0];
|
||||
} else {
|
||||
//name convention: plugin_componentname
|
||||
$name = $args[0];
|
||||
}
|
||||
|
||||
/** @var helper_plugin_bureaucracy_field $field */
|
||||
$field = $this->loadHelper($name, false);
|
||||
if($field && is_a($field, 'helper_plugin_bureaucracy_field')) {
|
||||
$field->initialize($args);
|
||||
$cmds[] = $field;
|
||||
} else {
|
||||
$evdata = array('fields' => &$cmds, 'args' => $args);
|
||||
$event = new Doku_Event('PLUGIN_BUREAUCRACY_FIELD_UNKNOWN', $evdata);
|
||||
if($event->advise_before()) {
|
||||
msg(sprintf($this->getLang('e_unknowntype'), hsc($name)), -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check if action is available
|
||||
foreach($rawactions as $action) {
|
||||
$action['type'] = $this->_sanitizeClassName($action['type']);
|
||||
|
||||
if(strpos($action['type'], '_') === false) {
|
||||
$action['actionname'] = 'bureaucracy_action' . $action['type'];
|
||||
} else {
|
||||
//name convention for other plugins: plugin_componentname
|
||||
$action['actionname'] = $action['type'];
|
||||
}
|
||||
|
||||
list($plugin, $component) = explode('_', $action['actionname']);
|
||||
$alternativename = $action['type'] . '_'. $action['type'];
|
||||
|
||||
// bureaucracy_action<name> or <plugin>_<componentname>
|
||||
if(!plugin_isdisabled($action['actionname']) || @file_exists(DOKU_PLUGIN . $plugin . '/helper/' . $component . '.php')) {
|
||||
$actions[] = $action;
|
||||
|
||||
// shortcut for other plugins with component name <name>_<name>
|
||||
} elseif(plugin_isdisabled($alternativename) || !@file_exists(DOKU_PLUGIN . $action['type'] . '/helper/' . $action['type'] . '.php')) {
|
||||
$action['actionname'] = $alternativename;
|
||||
$actions[] = $action;
|
||||
|
||||
// not found
|
||||
} else {
|
||||
$evdata = array('actions' => &$actions, 'action' => $action);
|
||||
$event = new Doku_Event('PLUGIN_BUREAUCRACY_ACTION_UNKNOWN', $evdata);
|
||||
if($event->advise_before()) {
|
||||
msg(sprintf($this->getLang('e_unknownaction'), hsc($action['actionname'])), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// action(s) found?
|
||||
if(count($actions) < 1) {
|
||||
msg($this->getLang('e_noaction'), -1);
|
||||
}
|
||||
|
||||
// set thank you message
|
||||
if(!$thanks) {
|
||||
$thanks = "";
|
||||
foreach($actions as $action) {
|
||||
$thanks .= $this->getLang($action['type'] . '_thanks');
|
||||
}
|
||||
} else {
|
||||
$thanks = hsc($thanks);
|
||||
}
|
||||
return array(
|
||||
'fields' => $cmds,
|
||||
'actions' => $actions,
|
||||
'thanks' => $thanks,
|
||||
'labels' => $labels
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the actual output creation.
|
||||
*
|
||||
* @param string $format output format being rendered
|
||||
* @param Doku_Renderer $R the current renderer object
|
||||
* @param array $data data created by handler()
|
||||
* @return boolean rendered correctly? (however, returned value is not used at the moment)
|
||||
*/
|
||||
public function render($format, Doku_Renderer $R, $data) {
|
||||
if($format != 'xhtml') return false;
|
||||
$R->info['cache'] = false; // don't cache
|
||||
|
||||
/**
|
||||
* replace some time and name placeholders in the default values
|
||||
* @var $field helper_plugin_bureaucracy_field
|
||||
*/
|
||||
foreach($data['fields'] as &$field) {
|
||||
if(isset($field->opt['value'])) {
|
||||
$field->opt['value'] = $this->replace($field->opt['value']);
|
||||
}
|
||||
}
|
||||
|
||||
if($data['labels']) $this->loadlabels($data);
|
||||
|
||||
$this->form_id++;
|
||||
if(isset($_POST['bureaucracy']) && checkSecurityToken() && $_POST['bureaucracy']['$$id'] == $this->form_id) {
|
||||
$success = $this->_handlepost($data);
|
||||
if($success !== false) {
|
||||
$R->doc .= '<div class="bureaucracy__plugin" id="scroll__here">' . $success . '</div>';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$R->doc .= $this->_htmlform($data['fields']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the labels, loaded from a defined labelpage
|
||||
*
|
||||
* @param array $data all data passed to render()
|
||||
*/
|
||||
protected function loadlabels(&$data) {
|
||||
global $INFO;
|
||||
$labelpage = $data['labels'];
|
||||
$exists = false;
|
||||
resolve_pageid($INFO['namespace'], $labelpage, $exists);
|
||||
if(!$exists) {
|
||||
msg(sprintf($this->getLang('e_labelpage'), html_wikilink($labelpage)), -1);
|
||||
return;
|
||||
}
|
||||
|
||||
// parse simple list (first level cdata only)
|
||||
$labels = array();
|
||||
$instructions = p_cached_instructions(wikiFN($labelpage));
|
||||
$inli = 0;
|
||||
$item = '';
|
||||
foreach($instructions as $instruction) {
|
||||
if($instruction[0] == 'listitem_open') {
|
||||
$inli++;
|
||||
continue;
|
||||
}
|
||||
if($inli === 1 && $instruction[0] == 'cdata') {
|
||||
$item .= $instruction[1][0];
|
||||
}
|
||||
if($instruction[0] == 'listitem_close') {
|
||||
$inli--;
|
||||
if($inli === 0) {
|
||||
list($k, $v) = explode('=', $item, 2);
|
||||
$k = trim($k);
|
||||
$v = trim($v);
|
||||
if($k && $v) $labels[$k] = $v;
|
||||
$item = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply labels to all fields
|
||||
$len = count($data['fields']);
|
||||
for($i = 0; $i < $len; $i++) {
|
||||
if(isset($data['fields'][$i]->depends_on)) {
|
||||
// translate dependency on fieldsets
|
||||
$label = $data['fields'][$i]->depends_on[0];
|
||||
if(isset($labels[$label])) {
|
||||
$data['fields'][$i]->depends_on[0] = $labels[$label];
|
||||
}
|
||||
|
||||
} else if(isset($data['fields'][$i]->opt['label'])) {
|
||||
// translate field labels
|
||||
$label = $data['fields'][$i]->opt['label'];
|
||||
if(isset($labels[$label])) {
|
||||
$data['fields'][$i]->opt['display'] = $labels[$label];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($data['thanks'])) {
|
||||
if(isset($labels[$data['thanks']])) {
|
||||
$data['thanks'] = $labels[$data['thanks']];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate posted data, perform action(s)
|
||||
*
|
||||
* @param array $data all data passed to render()
|
||||
* @return bool|string
|
||||
* returns thanks message when fields validated and performed the action(s) succesfully;
|
||||
* otherwise returns false.
|
||||
*/
|
||||
private function _handlepost($data) {
|
||||
$success = true;
|
||||
foreach($data['fields'] as $index => $field) {
|
||||
/** @var $field helper_plugin_bureaucracy_field */
|
||||
|
||||
$isValid = true;
|
||||
if($field->getFieldType() === 'file') {
|
||||
$file = array();
|
||||
foreach($_FILES['bureaucracy'] as $key => $value) {
|
||||
$file[$key] = $value[$index];
|
||||
}
|
||||
$isValid = $field->handle_post($file, $data['fields'], $index, $this->form_id);
|
||||
|
||||
} elseif($field->getFieldType() === 'fieldset' || !$field->hidden) {
|
||||
$isValid = $field->handle_post($_POST['bureaucracy'][$index] ?? null, $data['fields'], $index, $this->form_id);
|
||||
}
|
||||
|
||||
if(!$isValid) {
|
||||
// Do not return instantly to allow validation of all fields.
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
if(!$success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$thanks_array = array();
|
||||
|
||||
foreach($data['actions'] as $actionData) {
|
||||
/** @var helper_plugin_bureaucracy_action $action */
|
||||
$action = $this->loadHelper($actionData['actionname'], false);
|
||||
|
||||
// action helper found?
|
||||
if(!$action) {
|
||||
msg(sprintf($this->getLang('e_unknownaction'), hsc($actionData['actionname'])), -1);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$thanks_array[] = $action->run(
|
||||
$data['fields'],
|
||||
$data['thanks'],
|
||||
$actionData['argv']
|
||||
);
|
||||
} catch(Exception $e) {
|
||||
msg($e->getMessage(), -1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform after_action hooks
|
||||
foreach($data['fields'] as $field) {
|
||||
$field->after_action();
|
||||
}
|
||||
|
||||
// create thanks string
|
||||
$thanks = implode('', array_unique($thanks_array));
|
||||
|
||||
return $thanks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the form
|
||||
*
|
||||
* @param helper_plugin_bureaucracy_field[] $fields array with form fields
|
||||
* @return string html of the form
|
||||
*/
|
||||
private function _htmlform($fields) {
|
||||
global $INFO;
|
||||
|
||||
$form = new Doku_Form(array('class' => 'bureaucracy__plugin',
|
||||
'id' => 'bureaucracy__plugin' . $this->form_id,
|
||||
'enctype' => 'multipart/form-data'));
|
||||
$form->addHidden('id', $INFO['id']);
|
||||
$form->addHidden('bureaucracy[$$id]', $this->form_id);
|
||||
|
||||
foreach($fields as $id => $field) {
|
||||
$field->renderfield(array('name' => 'bureaucracy[' . $id . ']'), $form, $this->form_id);
|
||||
}
|
||||
|
||||
return $form->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a line into (quoted) arguments
|
||||
* Splits line at spaces, except when quoted
|
||||
*
|
||||
* @author William Fletcher <wfletcher@applestone.co.za>
|
||||
*
|
||||
* @param string $line line to parse
|
||||
* @param array $lines all remaining lines
|
||||
* @return array with all the arguments
|
||||
*/
|
||||
private function _parse_line($line, &$lines) {
|
||||
$args = array();
|
||||
$inQuote = false;
|
||||
$escapedQuote = false;
|
||||
$arg = '';
|
||||
do {
|
||||
$len = strlen($line);
|
||||
for($i = 0; $i < $len; $i++) {
|
||||
if($line[$i] == '"') {
|
||||
if($inQuote) {
|
||||
if($escapedQuote) {
|
||||
$arg .= '"';
|
||||
$escapedQuote = false;
|
||||
continue;
|
||||
}
|
||||
if($i + 1 < $len && $line[$i + 1] == '"') {
|
||||
$escapedQuote = true;
|
||||
continue;
|
||||
}
|
||||
array_push($args, $arg);
|
||||
$inQuote = false;
|
||||
$arg = '';
|
||||
continue;
|
||||
} else {
|
||||
$inQuote = true;
|
||||
continue;
|
||||
}
|
||||
} else if($line[$i] == ' ') {
|
||||
if($inQuote) {
|
||||
$arg .= ' ';
|
||||
continue;
|
||||
} else {
|
||||
if(strlen($arg) < 1) continue;
|
||||
array_push($args, $arg);
|
||||
$arg = '';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$arg .= $line[$i];
|
||||
}
|
||||
if(!$inQuote || count($lines) === 0) break;
|
||||
$line = array_shift($lines);
|
||||
$arg .= "\n";
|
||||
} while(true);
|
||||
if(strlen($arg) > 0) array_push($args, $arg);
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean class name
|
||||
*
|
||||
* @param string $classname
|
||||
* @return string cleaned name
|
||||
*/
|
||||
private function _sanitizeClassName($classname) {
|
||||
return preg_replace('/[^\w\x7f-\xff]/', '', strtolower($classname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save content in <noreplace> tags into $this->noreplace
|
||||
*
|
||||
* @param string $input The text to work on
|
||||
*/
|
||||
protected function noreplace_save($input) {
|
||||
$pattern = '/<noreplace>(.*?)<\/noreplace>/is';
|
||||
//save content of <noreplace> tags
|
||||
preg_match_all($pattern, $input, $matches);
|
||||
$this->noreplace = $matches[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply replacement patterns and values as prepared earlier
|
||||
* (disable $strftime to prevent double replacements with default strftime() replacements in nstemplate)
|
||||
*
|
||||
* @param string $input The text to work on
|
||||
* @param bool $strftime Apply strftime() replacements
|
||||
* @return string processed text
|
||||
*/
|
||||
function replace($input, $strftime = true) {
|
||||
//in helper_plugin_struct_field::setVal $input can be an array
|
||||
//just return $input in that case
|
||||
if (!is_string($input)) return $input;
|
||||
if (is_null($this->noreplace)) $this->noreplace_save($input);
|
||||
|
||||
foreach ($this->values as $label => $value) {
|
||||
$pattern = $this->patterns[$label];
|
||||
if (is_callable($value)) {
|
||||
$input = preg_replace_callback(
|
||||
$pattern,
|
||||
$value,
|
||||
$input
|
||||
);
|
||||
} else {
|
||||
$input = preg_replace($pattern, $value, $input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($strftime) {
|
||||
$input = preg_replace_callback(
|
||||
'/%./',
|
||||
function($m){return strftime($m[0]);},
|
||||
$input
|
||||
);
|
||||
}
|
||||
// user syntax: %%.(.*?)
|
||||
// strftime() is already applied once, so syntax is at this point: %.(.*?)
|
||||
$input = preg_replace_callback(
|
||||
'/@DATE\((.*?)(?:,\s*(.*?))?\)@/',
|
||||
array($this, 'replacedate'),
|
||||
$input
|
||||
);
|
||||
|
||||
//run functions
|
||||
foreach ($this->functions as $name => $callback) {
|
||||
$pattern = '/@' . preg_quote($name) . '\((.*?)\)@/';
|
||||
if (is_callable($callback)) {
|
||||
$input = preg_replace_callback($pattern, function ($matches) use ($callback) {
|
||||
return call_user_func($callback, $matches[1]);
|
||||
}, $input);
|
||||
}
|
||||
}
|
||||
|
||||
//replace <noreplace> tags with their original content
|
||||
$pattern = '/<noreplace>.*?<\/noreplace>/is';
|
||||
if (is_array($this->noreplace)) foreach ($this->noreplace as $nr) {
|
||||
$input = preg_replace($pattern, $nr, $input, 1);
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* (callback) Replace date by request datestring
|
||||
* e.g. '%m(30-11-1975)' is replaced by '11'
|
||||
*
|
||||
* @param array $match with [0]=>whole match, [1]=> first subpattern, [2] => second subpattern
|
||||
* @return string
|
||||
*/
|
||||
function replacedate($match) {
|
||||
global $conf;
|
||||
|
||||
//no 2nd argument for default date format
|
||||
$match[2] = $match[2] ?? $conf['dformat'];
|
||||
|
||||
return strftime($match[2], strtotime($match[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same replacements as applied at template namespaces
|
||||
*
|
||||
* @see parsePageTemplate()
|
||||
*/
|
||||
function prepareNamespacetemplateReplacements() {
|
||||
/* @var Input $INPUT */
|
||||
global $INPUT;
|
||||
global $INFO;
|
||||
global $USERINFO;
|
||||
global $conf;
|
||||
global $ID;
|
||||
|
||||
$this->patterns['__formpage_id__'] = '/@FORMPAGE_ID@/';
|
||||
$this->patterns['__formpage_ns__'] = '/@FORMPAGE_NS@/';
|
||||
$this->patterns['__formpage_curns__'] = '/@FORMPAGE_CURNS@/';
|
||||
$this->patterns['__formpage_file__'] = '/@FORMPAGE_FILE@/';
|
||||
$this->patterns['__formpage_!file__'] = '/@FORMPAGE_!FILE@/';
|
||||
$this->patterns['__formpage_!file!__'] = '/@FORMPAGE_!FILE!@/';
|
||||
$this->patterns['__formpage_page__'] = '/@FORMPAGE_PAGE@/';
|
||||
$this->patterns['__formpage_!page__'] = '/@FORMPAGE_!PAGE@/';
|
||||
$this->patterns['__formpage_!!page__'] = '/@FORMPAGE_!!PAGE@/';
|
||||
$this->patterns['__formpage_!page!__'] = '/@FORMPAGE_!PAGE!@/';
|
||||
$this->patterns['__user__'] = '/@USER@/';
|
||||
$this->patterns['__name__'] = '/@NAME@/';
|
||||
$this->patterns['__mail__'] = '/@MAIL@/';
|
||||
$this->patterns['__date__'] = '/@DATE@/';
|
||||
|
||||
// replace placeholders
|
||||
$localid = isset($INFO['id']) ? $INFO['id'] : $ID;
|
||||
$file = noNS($localid);
|
||||
$page = strtr($file, $conf['sepchar'], ' ');
|
||||
$this->values['__formpage_id__'] = $localid;
|
||||
$this->values['__formpage_ns__'] = getNS($localid);
|
||||
$this->values['__formpage_curns__'] = curNS($localid);
|
||||
$this->values['__formpage_file__'] = $file;
|
||||
$this->values['__formpage_!file__'] = PhpString::ucfirst($file);
|
||||
$this->values['__formpage_!file!__'] = PhpString::strtoupper($file);
|
||||
$this->values['__formpage_page__'] = $page;
|
||||
$this->values['__formpage_!page__'] = PhpString::ucfirst($page);
|
||||
$this->values['__formpage_!!page__'] = PhpString::ucwords($page);
|
||||
$this->values['__formpage_!page!__'] = PhpString::strtoupper($page);
|
||||
$this->values['__user__'] = $INPUT->server->str('REMOTE_USER');
|
||||
$this->values['__name__'] = $USERINFO['name'] ?? '';
|
||||
$this->values['__mail__'] = $USERINFO['mail'] ?? '';
|
||||
$this->values['__date__'] = strftime($conf['dformat']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Date time replacements
|
||||
*/
|
||||
function prepareDateTimereplacements() {
|
||||
$this->patterns['__year__'] = '/@YEAR@/';
|
||||
$this->patterns['__month__'] = '/@MONTH@/';
|
||||
$this->patterns['__monthname__'] = '/@MONTHNAME@/';
|
||||
$this->patterns['__day__'] = '/@DAY@/';
|
||||
$this->patterns['__time__'] = '/@TIME@/';
|
||||
$this->patterns['__timesec__'] = '/@TIMESEC@/';
|
||||
$this->values['__year__'] = date('Y');
|
||||
$this->values['__month__'] = date('m');
|
||||
$this->values['__monthname__'] = date('B');
|
||||
$this->values['__day__'] = date('d');
|
||||
$this->values['__time__'] = date('H:i');
|
||||
$this->values['__timesec__'] = date('H:i:s');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions that can be used after replacements
|
||||
*/
|
||||
function prepareFunctions() {
|
||||
$this->functions['curNS'] = 'curNS';
|
||||
$this->functions['getNS'] = 'getNS';
|
||||
$this->functions['noNS'] = 'noNS';
|
||||
$this->functions['p_get_first_heading'] = 'p_get_first_heading';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user