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