1c3437056SNickeau<?php 2c3437056SNickeau 3c3437056SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 4c3437056SNickeau 504fd306cSNickeauuse ComboStrap\ExceptionBadSyntax; 686ec4045Sgerardnicouse ComboStrap\Identity; 7c3437056SNickeauuse ComboStrap\Index; 8c3437056SNickeauuse ComboStrap\LogUtility; 904fd306cSNickeauuse ComboStrap\LinkMarkup; 10c3437056SNickeauuse ComboStrap\Message; 1104fd306cSNickeauuse ComboStrap\MarkupPath; 12c3437056SNickeauuse dokuwiki\Extension\ActionPlugin; 13c3437056SNickeau 14c3437056SNickeau 15c3437056SNickeau/** 16c3437056SNickeau * 17c3437056SNickeau * To show a message after redirection or rewriting 18c3437056SNickeau * 19c3437056SNickeau * 20c3437056SNickeau * 21c3437056SNickeau */ 22c3437056SNickeauclass action_plugin_combo_routermessage extends ActionPlugin 23c3437056SNickeau{ 24c3437056SNickeau 25c3437056SNickeau // a class can not start with a number then webcomponent is not a valid class name 26c3437056SNickeau const REDIRECT_MANAGER_BOX_CLASS = "redirect-manager"; 27c3437056SNickeau 28c3437056SNickeau // Property key 29c3437056SNickeau const ORIGIN_PAGE = 'redirectId'; 30c3437056SNickeau const ORIGIN_TYPE = 'redirectOrigin'; 31c3437056SNickeau const CONF_SHOW_PAGE_NAME_IS_NOT_UNIQUE = 'ShowPageNameIsNotUnique'; 3286ec4045Sgerardnico const CONF_SHOW_MESSAGE_CLASSIC = 'ShowMessageClassic'; 3386ec4045Sgerardnico const CONF_SHOW_MESSAGE_CLASSIC_DEFAULT = 1; 34c3437056SNickeau 35c3437056SNickeau function __construct() 36c3437056SNickeau { 37c3437056SNickeau // enable direct access to language strings 38c3437056SNickeau // ie $this->lang 39c3437056SNickeau $this->setupLocale(); 40c3437056SNickeau } 41c3437056SNickeau 42c3437056SNickeau /** 43c3437056SNickeau * 44c3437056SNickeau * Return the message properties from a query string 45c3437056SNickeau * 46c3437056SNickeau * An internal HTTP redirect pass them via query string 47c3437056SNickeau */ 48c3437056SNickeau private static function getMessageQueryStringProperties(): array 49c3437056SNickeau { 50c3437056SNickeau 51c3437056SNickeau $returnValues = array(); 52c3437056SNickeau 53c3437056SNickeau global $INPUT; 54c3437056SNickeau $origin = $INPUT->str(self::ORIGIN_PAGE, null); 55c3437056SNickeau if ($origin != null) { 56c3437056SNickeau $returnValues = array( 57c3437056SNickeau $origin, 58c3437056SNickeau $INPUT->str(self::ORIGIN_TYPE, null) 59c3437056SNickeau ); 60c3437056SNickeau } 61c3437056SNickeau return $returnValues; 62c3437056SNickeau 63c3437056SNickeau } 64c3437056SNickeau 65c3437056SNickeau 66c3437056SNickeau function register(Doku_Event_Handler $controller) 67c3437056SNickeau { 68c3437056SNickeau 69c3437056SNickeau /* This will call the function _displayRedirectMessage */ 70c3437056SNickeau $controller->register_hook( 71c3437056SNickeau 'TPL_ACT_RENDER', 72c3437056SNickeau 'BEFORE', 73c3437056SNickeau $this, 74c3437056SNickeau '_displayRedirectMessage', 75c3437056SNickeau array() 76c3437056SNickeau ); 77c3437056SNickeau 78c3437056SNickeau 79c3437056SNickeau } 80c3437056SNickeau 81c3437056SNickeau 82c3437056SNickeau /** 83c3437056SNickeau * Main function; dispatches the visual comment actions 84c3437056SNickeau * @param $event Doku_Event 85c3437056SNickeau */ 86c3437056SNickeau function _displayRedirectMessage(&$event, $param) 87c3437056SNickeau { 88c3437056SNickeau 89c3437056SNickeau $pageIdOrigin = null; 90c3437056SNickeau $redirectSource = null; 91c3437056SNickeau 92c3437056SNickeau $messageQueryStringProperties = self::getMessageQueryStringProperties(); 93c3437056SNickeau if (!empty($messageQueryStringProperties)) { 94c3437056SNickeau list($pageIdOrigin, $redirectSource) = $messageQueryStringProperties; 95c3437056SNickeau } 96c3437056SNickeau 97c3437056SNickeau if ($pageIdOrigin) { 98c3437056SNickeau 99c3437056SNickeau switch ($redirectSource) { 100c3437056SNickeau 101c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_PAGE_RULES: 10286ec4045Sgerardnico if (!$this->showMessageIfPublicAndPlanned()) { 10386ec4045Sgerardnico return; 10486ec4045Sgerardnico } 105c3437056SNickeau $message = Message::createInfoMessage() 106c3437056SNickeau ->addHtmlContent("<p>" . sprintf($this->getLang('message_redirected_by_redirect'), hsc($pageIdOrigin)) . "</p>"); 107c3437056SNickeau break; 108c3437056SNickeau 109c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_START_PAGE: 110c3437056SNickeau $message = Message::createWarningMessage() 111c3437056SNickeau ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_startpage'], hsc($pageIdOrigin)) . "</p>"); 112c3437056SNickeau break; 113c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_BEST_PAGE_NAME: 114c3437056SNickeau $message = Message::createWarningMessage() 115c3437056SNickeau ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_bestpagename'], hsc($pageIdOrigin)) . "</p>"); 116c3437056SNickeau break; 117*b6b20725Sgerardnico case action_plugin_combo_router::TARGET_ORIGIN_BEST_END_PAGE_NAME: 118*b6b20725Sgerardnico $message = Message::createWarningMessage() 119*b6b20725Sgerardnico ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_bestendpagename'], hsc($pageIdOrigin)) . "</p>"); 120*b6b20725Sgerardnico break; 121c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_BEST_NAMESPACE: 122c3437056SNickeau $message = Message::createWarningMessage() 123c3437056SNickeau ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_bestnamespace'], hsc($pageIdOrigin)) . "</p>"); 124c3437056SNickeau break; 125c3437056SNickeau 126c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_SEARCH_ENGINE: 127c3437056SNickeau $message = Message::createWarningMessage() 128c3437056SNickeau ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_searchengine'], hsc($pageIdOrigin)) . "</p>"); 129c3437056SNickeau break; 130c3437056SNickeau 131c3437056SNickeau case action_plugin_combo_router::GO_TO_EDIT_MODE: 132c3437056SNickeau $message = Message::createInfoMessage() 133c3437056SNickeau ->addHtmlContent("<p>" . $this->lang['message_redirected_to_edit_mode'] . "</p>"); 134c3437056SNickeau break; 135c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_PERMALINK_EXTENDED: 136c3437056SNickeau case action_plugin_combo_router::TARGET_ORIGIN_PERMALINK: 137c3437056SNickeau $message = Message::createInfoMessage() 138c3437056SNickeau ->addHtmlContent("<p>" . $this->lang['message_redirected_from_permalink'] . "</p>"); 139c3437056SNickeau break; 140561faa65Sgerardnico case action_plugin_combo_router::TARGET_ORIGIN_CANONICAL: 14186ec4045Sgerardnico if (!$this->showMessageIfPublicAndPlanned()) { 14286ec4045Sgerardnico return; 14386ec4045Sgerardnico } 144561faa65Sgerardnico $message = Message::createInfoMessage() 145561faa65Sgerardnico ->addHtmlContent("<p>" . $this->lang['message_redirected_from_canonical'] . "</p>"); 146561faa65Sgerardnico break; 147c3437056SNickeau default: 148c3437056SNickeau LogUtility::msg("The redirection source ($redirectSource) is unknown. It was not expected", LogUtility::LVL_MSG_ERROR, action_plugin_combo_router::CANONICAL); 149c3437056SNickeau return; 150c3437056SNickeau 151c3437056SNickeau } 152c3437056SNickeau 153c3437056SNickeau 154c3437056SNickeau // Add a list of page with the same name to the message 155c3437056SNickeau // if the redirections is not planned 15604fd306cSNickeau if ($redirectSource != action_plugin_combo_router::TARGET_ORIGIN_PAGE_RULES) { 15704fd306cSNickeau $pageOrigin = MarkupPath::createMarkupFromId($pageIdOrigin); 15804fd306cSNickeau $this->addToMessagePagesWithSameName($message, $pageOrigin); 159c3437056SNickeau } 160c3437056SNickeau 161c3437056SNickeau if ($event->data === 'show' || $event->data === 'edit' || $event->data === 'search') { 162c3437056SNickeau $html = $message 163c3437056SNickeau ->setPlugin($this) 164c3437056SNickeau ->setClass(action_plugin_combo_routermessage::REDIRECT_MANAGER_BOX_CLASS) 165c3437056SNickeau ->setCanonical(action_plugin_combo_router::CANONICAL) 166c3437056SNickeau ->setSignatureName(action_plugin_combo_router::URL_MANAGER_NAME) 167c3437056SNickeau ->toHtmlBox(); 16804fd306cSNickeau LogUtility::infoToPublic($html, action_plugin_combo_router::CANONICAL); 169c3437056SNickeau } 170c3437056SNickeau 171c3437056SNickeau 172c3437056SNickeau } 173c3437056SNickeau 174c3437056SNickeau 175c3437056SNickeau } 176c3437056SNickeau 177c3437056SNickeau 178c3437056SNickeau /** 179c3437056SNickeau * Add the page with the same page name but in an other location 180c3437056SNickeau * @param Message $message 18104fd306cSNickeau * @param MarkupPath $pageOrigin 182c3437056SNickeau */ 18304fd306cSNickeau function addToMessagePagesWithSameName(Message $message, MarkupPath $pageOrigin) 184c3437056SNickeau { 185c3437056SNickeau 18686ec4045Sgerardnico if (!$this->getConf(self::CONF_SHOW_PAGE_NAME_IS_NOT_UNIQUE) == 1) { 18786ec4045Sgerardnico return; 18886ec4045Sgerardnico } 189c3437056SNickeau 190c3437056SNickeau global $ID; 191c3437056SNickeau // The page name 19204fd306cSNickeau $pageName = $pageOrigin->getNameOrDefault(); 19304fd306cSNickeau $pagesWithSameName = Index::getOrCreate()->getPagesWithSameLastName($pageOrigin); 19404fd306cSNickeau 19504fd306cSNickeau if (count($pagesWithSameName) === 1) { 19604fd306cSNickeau $page = $pagesWithSameName[0]; 19704fd306cSNickeau if ($page->getWikiId() === $ID) { 19804fd306cSNickeau // the page itself 19904fd306cSNickeau return; 20004fd306cSNickeau } 20104fd306cSNickeau } 202c3437056SNickeau 203c3437056SNickeau if (count($pagesWithSameName) > 0) { 204c3437056SNickeau 205c3437056SNickeau $message->setType(Message::TYPE_WARNING); 206c3437056SNickeau 207c3437056SNickeau // Assign the value to a variable to be able to use the construct .= 208c3437056SNickeau if ($message->getPlainTextContent() <> '') { 209c3437056SNickeau $message->addHtmlContent('<br/><br/>'); 210c3437056SNickeau } 211c3437056SNickeau $message->addHtmlContent($this->lang['message_pagename_exist_one']); 212c3437056SNickeau $message->addHtmlContent('<ul>'); 213c3437056SNickeau 214c3437056SNickeau $i = 0; 21504fd306cSNickeau $listPagesHtml = ""; 21604fd306cSNickeau foreach ($pagesWithSameName as $page) { 21704fd306cSNickeau 21804fd306cSNickeau if ($page->getWikiId() === $ID) { 219c3437056SNickeau continue; 220c3437056SNickeau } 221c3437056SNickeau $i++; 222c3437056SNickeau if ($i > 10) { 22304fd306cSNickeau $listPagesHtml .= '<li>' . 224c3437056SNickeau tpl_link( 22504fd306cSNickeau "?do=search&q=" . rawurldecode($pageName), 226c3437056SNickeau "More ...", 227c3437056SNickeau 'class="" rel="nofollow" title="More..."', 228c3437056SNickeau $return = true 22904fd306cSNickeau ) . '</li>'; 230c3437056SNickeau break; 231c3437056SNickeau } 23204fd306cSNickeau 23304fd306cSNickeau try { 23404fd306cSNickeau $markupRef = LinkMarkup::createFromPageIdOrPath($page->getWikiId()); 23504fd306cSNickeau $tagAttributes = $markupRef 23604fd306cSNickeau ->toAttributes() 23704fd306cSNickeau ->addOutputAttributeValue("rel", "nofollow"); 23804fd306cSNickeau $listPagesHtml .= "<li>{$tagAttributes->toHtmlEnterTag("a")}{$markupRef->getDefaultLabel()}</a></li>"; 23904fd306cSNickeau } catch (ExceptionBadSyntax $e) { 24004fd306cSNickeau LogUtility::internalError("Internal Error: Unable to get a markup ref for the page ($page). Error: {$e->getMessage()}"); 241c3437056SNickeau } 24286ec4045Sgerardnico 243c3437056SNickeau } 24404fd306cSNickeau $message->addHtmlContent($listPagesHtml); 24504fd306cSNickeau $message->addHtmlContent('</ul>'); 24604fd306cSNickeau 24704fd306cSNickeau } 24804fd306cSNickeau } 249c3437056SNickeau 250c3437056SNickeau 251c3437056SNickeau /** 252c3437056SNickeau * Set the redirect in a session that will be be read after the redirect 253c3437056SNickeau * in order to show a message to the user 254c3437056SNickeau * @param string $id 255c3437056SNickeau * @param string $redirectSource 256c3437056SNickeau */ 257c3437056SNickeau static function notify($id, $redirectSource) 258c3437056SNickeau { 259c3437056SNickeau // Msg via session 260c3437056SNickeau if (!defined('NOSESSION')) { 261c3437056SNickeau //reopen session, store data and close session again 262c3437056SNickeau self::sessionStart(); 263c3437056SNickeau $_SESSION[DOKU_COOKIE][self::ORIGIN_PAGE] = $id; 264c3437056SNickeau $_SESSION[DOKU_COOKIE][self::ORIGIN_TYPE] = $redirectSource; 265c3437056SNickeau self::sessionClose(); 266c3437056SNickeau 267c3437056SNickeau } 268c3437056SNickeau } 269c3437056SNickeau 270c3437056SNickeau 271c3437056SNickeau private static function sessionStart() 272c3437056SNickeau { 273c3437056SNickeau $sessionStatus = session_status(); 274c3437056SNickeau switch ($sessionStatus) { 275c3437056SNickeau case PHP_SESSION_DISABLED: 276c3437056SNickeau throw new RuntimeException("Sessions are disabled"); 277c3437056SNickeau 278c3437056SNickeau case PHP_SESSION_NONE: 279c3437056SNickeau $result = @session_start(); 280c3437056SNickeau if (!$result) { 281c3437056SNickeau throw new RuntimeException("The session was not successfully started"); 282c3437056SNickeau } 283c3437056SNickeau break; 284c3437056SNickeau case PHP_SESSION_ACTIVE: 285c3437056SNickeau break; 286c3437056SNickeau } 287c3437056SNickeau } 288c3437056SNickeau 289c3437056SNickeau private static function sessionClose() 290c3437056SNickeau { 291c3437056SNickeau // Close the session 292c3437056SNickeau $phpVersion = phpversion(); 293c3437056SNickeau if ($phpVersion > "7.2.0") { 294c3437056SNickeau $result = session_write_close(); 295c3437056SNickeau if (!$result) { 296c3437056SNickeau // Session is really not a well known mechanism 297c3437056SNickeau // Set this error in a info level to not fail the test 298c3437056SNickeau LogUtility::msg("Failure to write the session", LogUtility::LVL_MSG_INFO); 299c3437056SNickeau } 300c3437056SNickeau } else { 301c3437056SNickeau session_write_close(); 302c3437056SNickeau } 303c3437056SNickeau 304c3437056SNickeau } 305c3437056SNickeau 30686ec4045Sgerardnico /** 30786ec4045Sgerardnico * We don't saw the message if it was planned and 30886ec4045Sgerardnico * it's a reader 30986ec4045Sgerardnico * @return bool 31086ec4045Sgerardnico */ 31186ec4045Sgerardnico private function showMessageIfPublicAndPlanned(): bool 31286ec4045Sgerardnico { 31386ec4045Sgerardnico if (Identity::isWriter()) { 31486ec4045Sgerardnico return true; 31586ec4045Sgerardnico } 31686ec4045Sgerardnico return $this->getConf(self::CONF_SHOW_MESSAGE_CLASSIC, self::CONF_SHOW_MESSAGE_CLASSIC_DEFAULT) == 1; 31786ec4045Sgerardnico } 31886ec4045Sgerardnico 319c3437056SNickeau} 320