* @author David Lorentsen */ use dokuwiki\File\PageResolver; // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); class syntax_plugin_pageredirect extends DokuWiki_Syntax_Plugin { /** * @return string Syntax mode type */ public function getType() { return 'substition'; } /** * @return string Paragraph type */ public function getPType() { return 'block'; } /** * @return int Sort order - Low numbers go before high numbers */ public function getSort() { return 1; } /** * Connect lookup pattern to lexer. * * @param string $mode Parser mode */ public function connectTo($mode) { // NOTE: each document is surrounted with \n by dokuwiki parser // so it's safe to use \n in the pattern // this fixes creole greedyness: // https://github.com/glensc/dokuwiki-plugin-pageredirect/issues/18#issuecomment-249386268 $this->Lexer->addSpecialPattern('(?:~~REDIRECT>.+?~~|\n#(?i:redirect) [^\r\n]+)', $mode, 'plugin_pageredirect'); } /** * Handler to prepare matched data for the rendering process * * This function can only pass data to render() via its return value * render() may be not be run during the object's current life. * * Usually you should only need the $match param. * * @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 Reference to the Doku_Handler object * @return array Return an array with all data you want to use in render */ public function handle($match, $state, $pos, Doku_Handler $handler) { // strip leading "\n" from creole-compatible pattern $match = trim($match); // extract target page from match pattern if($match[0] == '#') { # #REDIRECT PAGE $id = substr($match, 10); } else { # ~~REDIRECT>PAGE~~ $id = substr($match, 11, -2); } $id = trim($id); $is_external = preg_match('#^https?://#i', $id); // resolve and clean the $id if it is not external if(!$is_external) { global $ID; if (class_exists('dokuwiki\File\PageResolver')) { $resolver = new PageResolver($ID); $id = $resolver->resolveId($id); } else { $exists = null; resolve_pageid(getNS($ID), $id, $exists); } } return array($id, $is_external); } /** * Handles the actual output creation. * * The function must not assume any other of the classes methods have been run * during the object's current life. The only reliable data it receives are its * parameters. * * The function should always check for the given output format and return false * when a format isn't supported. * * $renderer contains a reference to the renderer object which is * currently handling the rendering. You need to use it for writing * the output. How this is done depends on the renderer used (specified * by $format * * The contents of the $data array depends on what the handler() function above * created * * @param string $format output format being rendered * @param Doku_Renderer $renderer reference to the current renderer object * @param array $data data created by handler() * @return boolean return true if rendered correctly */ public function render($format, Doku_Renderer $renderer, $data) { if($format == 'xhtml') { // add prepared note about redirection $renderer->doc .= $this->redirect_message($data); // hook into the post render event to allow the page to be redirected global $EVENT_HANDLER; /** @var action_plugin_pageredirect $action */ $action = plugin_load('action', 'pageredirect'); $EVENT_HANDLER->register_hook('TPL_ACT_RENDER', 'AFTER', $action, 'handle_dokuwiki_started'); return true; } if($format == 'metadata') { // add redirection to metadata $renderer->meta['relation']['isreplacedby'] = $data; if (!$data[1]) { $page = preg_split("/\?|#/", $data[0])[0]; $renderer->meta['relation']['references'][$page] = page_exists($page); } return true; } return false; } /** * Create redirection message html * * @param string $page * @return string */ private function redirect_message($metadata) { list($page, $is_external) = $metadata; if(!$is_external) { $link = html_wikilink($page); } else { $link = '' . hsc($page) . ''; } // prepare message here instead of in render $message = '
' . sprintf($this->getLang('redirect_to'), $link) . '
'; return $message; } }