markers used during translation process * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_greenstonedocs extends DokuWiki_Syntax_Plugin { /** The plugin should only effect pages within this namespace. */ private $target_namespace_prefix; /** @function __construct() */ public function __construct() { global $conf; $this->target_namespace_prefix = $this->getConf('currentnamespace'); // Prerequisite testing. Ensure the following list of plugins are also // installed and complain otherwise. if ($this->getConf('checkprereq')) { $prereqs = array_flip(explode(' ', $this->getConf('prerequisiteplugins'))); if ($dh = opendir(DOKU_PLUGIN)) { while (($file = readdir($dh)) !== false) { $path = DOKU_PLUGIN . $file; if (substr($file, 0, 1) != '.' && is_dir($path)) { if (isset($prereqs[$file])) { unset($prereqs[$file]); } } } closedir($dh); } if (count($prereqs) > 0) { ksort($prereqs); foreach ($prereqs as $plugin_name => $value) { msg("The Greenstone Wiki requires the plugin: " . $plugin_name, -1); } } else { $this->_resetConf('checkprereq'); } } // Check the plugin configuration and, if checked, proceed to auto- // matically update the internal links within the Greenstone wiki pages // to have a different base namespace if ($this->getConf('updatenamespace')) { // Determine the starting point for the update $base_dir = DOKU_INC . 'data/pages/' . $this->getConf('currentnamespace') . '/'; // - ensure trailing : for consistency in namespaces $current_namespace = $this->getConf('currentnamespace'); if (strlen($current_namespace) > 0 && substr($current_namespace, -1) != ':') { $current_namespace .= ':'; } $old_namespace = $this->getConf('oldnamespace'); if (strlen($old_namespace) > 0 && substr($old_namespace, -1) != ':') { $old_namespace .= ':'; } // - recursive call to do the actual search and replace $raw_child_namespaces = explode(' ', $this->getConf('childnamespaces')); $child_namespaces = array(); foreach ($raw_child_namespaces as $raw_child_namespace) { if (strlen($raw_child_namespace) > 0 && substr($raw_child_namespace, -1) != ':') { $raw_child_namespace .= ':'; } $child_namespaces[] = $raw_child_namespace; } // Begin search $this->_replaceInternalLinkNamespace($base_dir, $old_namespace, $current_namespace, $child_namespaces); // Finally, we reset the configuration option back to off. $this->_resetConf('updatenamespace'); // Let users know what has happened msg("Sucessfully performed one-time update of namespace in Greenstone Documentation.", 1); } } /** __construct() **/ /** */ function _resetConf($key) { // Reset the configuration option back to off. // - file on disk $config_file_path = DOKU_CONF . 'local.php'; $content = file_get_contents($config_file_path); $option_prefix = '$conf[\'plugin\'][\'greenstonedocs\'][\'' . $key . '\']'; if (strpos($content, $option_prefix) !== false) { $content = str_replace($option_prefix . ' = 1;', $option_prefix . ' = 0;', $content); } else { $content .= "\n" . $option_prefix . " = 0;"; } file_put_contents($config_file_path, $content); // - in memory cache $conf[$key] = 0; } /** _resetConf($key) **/ /** @function _replaceInternalLinkNamespace() */ function _replaceInternalLinkNamespace($dir, $old_namespace, $new_namespace, $child_namespaces) { $files = array(); if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if (substr($file, 0, 1) != '.') { $files[] = $file; } } closedir($dh); } foreach ($files as $file) { $path = $dir . $file; // - continue the recursive search through child directories if (is_dir($path)) { $this->_replaceInternalLinkNamespace($path . '/', $old_namespace, $new_namespace, $child_namespaces); } else if (substr($file, -4) == '.txt') { // - none of these files are *that* large, so read them // into memory for processing $page_content = file_get_contents($path); // - we are looking for internal links that contain the // old namespace (or '') followed by an expected child // namespace - and then replace the old namespace $pattern = '/(\[\[)' . $old_namespace . '(' . implode('|', $child_namespaces) . ')(.+?\]\])/'; $replace = '${1}'. $new_namespace . '${2}${3}'; $replace_count = 0; $page_content = preg_replace($pattern, $replace, $page_content, -1, $replace_count); // - special case: also fix up the mismatched imgcaption tags $pattern = '/()(<\/imgcaption>)\s*(\{\{.+?\}\})/s'; $replace = '${1}${3}${2}'; $page_content = preg_replace($pattern, $replace, $page_content, -1, $replace_count); if ($replace_count > 0) { file_put_contents($path, $page_content); } } } } /** @function _replaceInternalLinkNamespace() **/ /** * Should return the type of syntax this plugin defines. * - notice that the typo (substition == substitution) is necessary */ function getType() { return 'substition'; } /** * Returns a number used to determine in which order modes are added. */ function getSort() { return 0; } /** * Connect lookup pattern to lexer. */ function connectTo($mode) { $current_full_namespace = getNS(getID('id',true)); // Note that the result is FALSE if no match, and should be 0 if name- // space starts with prefix. if (strpos($current_full_namespace, $this->target_namespace_prefix) === 0) { // Hiding the section/translation ID tags in headers $this->Lexer->addSpecialPattern( '^[ \t]*={2,6}\s?[^\n]+={2,6}[ \t]*(?=\n)', $mode, 'plugin_greenstonedocs'); // Hiding the translation ID tags in paragraph text $this->Lexer->addSpecialPattern('', $mode, 'plugin_greenstonedocs'); // Hiding the translation ID tags in image captions $this->Lexer->addSpecialPattern('\%!-- id:[^\s]+ --\%', $mode, 'plugin_greenstonedocs'); } } /** * Handler to prepare matched data for the rendering process. * *

* The $aState parameter gives the type of pattern * which triggered the call to this method: *

*
*
DOKU_LEXER_ENTER
*
a pattern set by addEntryPattern()
*
DOKU_LEXER_MATCHED
*
a pattern set by addPattern()
*
DOKU_LEXER_EXIT
*
a pattern set by addExitPattern()
*
DOKU_LEXER_SPECIAL
*
a pattern set by addSpecialPattern()
*
DOKU_LEXER_UNMATCHED
*
ordinary text encountered within the plugin's syntax mode * which doesn't match any pattern.
*
* @param $aMatch String The text matched by the patterns. * @param $aState Integer The lexer state for the match. * @param $aPos Integer The character position of the matched text. * @param $aHandler Object Reference to the Doku_Handler object. * @return Integer The current lexer state for the match. * @public * @see render() * @static */ function handle($match, $state, $pos, &$handler) { if (preg_match('/wiki/i', $match)) { return array($state, $match, array('action'=>'debug', 'pos'=>$pos)); } // Special case for IDs (section and language) in header strings if (preg_match('/={2,6}\s?[^\n]+={2,6}/', $match)) { //msg("[DEBUG] Title: " . htmlspecialchars($match), 2, '', '', MSG_ADMINS_ONLY); $match = preg_replace('//', '', $match); $match = preg_replace('//', '', $match); $handler->header($match, $state, $pos); return true; } // any other match gets replaced with empty string return array($state, $match, array('action'=>'erase', 'pos'=>$pos)); } /** * Handle the actual output creation. * *

* The method checks for the given $aFormat and returns * FALSE when a format isn't supported. $aRenderer * contains a reference to the renderer object which is currently * handling the rendering. The contents of $aData is the * return value of the handle() method. *

* @see handle() */ function render($mode, &$renderer, $data) { if($mode == 'xhtml') { list($state, $match, $params) = $data; switch ($params['action']) { case 'debug': $renderer->doc .= 'SQUIG-squig-squig'; break; // By default we do an erase replace default: $renderer->doc .= ''; } return true; } return false; } } //Setup VIM: ex: et ts=4 enc=utf-8 : ?>