xref: /plugin/combo/action/routermessage.php (revision 45a874f4355f8bee7459e5d3b79e86e68468b316)
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