xref: /plugin/combo/action/routermessage.php (revision 564b1ae3619b65849aa27b721fa6229598967fe4)
1<?php
2
3require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
4
5use ComboStrap\Identity;
6use ComboStrap\Index;
7use ComboStrap\LogUtility;
8use ComboStrap\Message;
9use dokuwiki\Extension\ActionPlugin;
10
11
12/**
13 *
14 * To show a message after redirection or rewriting
15 *
16 *
17 *
18 */
19class action_plugin_combo_routermessage extends ActionPlugin
20{
21
22    // a class can not start with a number then webcomponent is not a valid class name
23    const REDIRECT_MANAGER_BOX_CLASS = "redirect-manager";
24
25    // Property key
26    const ORIGIN_PAGE = 'redirectId';
27    const ORIGIN_TYPE = 'redirectOrigin';
28    const CONF_SHOW_PAGE_NAME_IS_NOT_UNIQUE = 'ShowPageNameIsNotUnique';
29    const CONF_SHOW_MESSAGE_CLASSIC = 'ShowMessageClassic';
30    const CONF_SHOW_MESSAGE_CLASSIC_DEFAULT = 1;
31
32    function __construct()
33    {
34        // enable direct access to language strings
35        // ie $this->lang
36        $this->setupLocale();
37    }
38
39    /**
40     *
41     * Return the message properties from a query string
42     *
43     * An internal HTTP redirect pass them via query string
44     */
45    private static function getMessageQueryStringProperties(): array
46    {
47
48        $returnValues = array();
49
50        global $INPUT;
51        $origin = $INPUT->str(self::ORIGIN_PAGE, null);
52        if ($origin != null) {
53            $returnValues = array(
54                $origin,
55                $INPUT->str(self::ORIGIN_TYPE, null)
56            );
57        }
58        return $returnValues;
59
60    }
61
62
63    function register(Doku_Event_Handler $controller)
64    {
65
66        /* This will call the function _displayRedirectMessage */
67        $controller->register_hook(
68            'TPL_ACT_RENDER',
69            'BEFORE',
70            $this,
71            '_displayRedirectMessage',
72            array()
73        );
74
75
76    }
77
78
79    /**
80     * Main function; dispatches the visual comment actions
81     * @param   $event Doku_Event
82     */
83    function _displayRedirectMessage(&$event, $param)
84    {
85
86        $pageIdOrigin = null;
87        $redirectSource = null;
88
89        $messageQueryStringProperties = self::getMessageQueryStringProperties();
90        if (!empty($messageQueryStringProperties)) {
91            list($pageIdOrigin, $redirectSource) = $messageQueryStringProperties;
92        }
93
94        if ($pageIdOrigin) {
95
96            switch ($redirectSource) {
97
98                case action_plugin_combo_router::TARGET_ORIGIN_PAGE_RULES:
99                    if (!$this->showMessageIfPublicAndPlanned()) {
100                        return;
101                    }
102                    $message = Message::createInfoMessage()
103                        ->addHtmlContent("<p>" . sprintf($this->getLang('message_redirected_by_redirect'), hsc($pageIdOrigin)) . "</p>");
104                    break;
105
106                case action_plugin_combo_router::TARGET_ORIGIN_START_PAGE:
107                    $message = Message::createWarningMessage()
108                        ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_startpage'], hsc($pageIdOrigin)) . "</p>");
109                    break;
110                case  action_plugin_combo_router::TARGET_ORIGIN_BEST_PAGE_NAME:
111                    $message = Message::createWarningMessage()
112                        ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_bestpagename'], hsc($pageIdOrigin)) . "</p>");
113                    break;
114                case action_plugin_combo_router::TARGET_ORIGIN_BEST_NAMESPACE:
115                    $message = Message::createWarningMessage()
116                        ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_bestnamespace'], hsc($pageIdOrigin)) . "</p>");
117                    break;
118
119                case action_plugin_combo_router::TARGET_ORIGIN_SEARCH_ENGINE:
120                    $message = Message::createWarningMessage()
121                        ->addHtmlContent("<p>" . sprintf($this->lang['message_redirected_to_searchengine'], hsc($pageIdOrigin)) . "</p>");
122                    break;
123
124                case action_plugin_combo_router::GO_TO_EDIT_MODE:
125                    $message = Message::createInfoMessage()
126                        ->addHtmlContent("<p>" . $this->lang['message_redirected_to_edit_mode'] . "</p>");
127                    break;
128                case action_plugin_combo_router::TARGET_ORIGIN_PERMALINK_EXTENDED:
129                case action_plugin_combo_router::TARGET_ORIGIN_PERMALINK:
130                    $message = Message::createInfoMessage()
131                        ->addHtmlContent("<p>" . $this->lang['message_redirected_from_permalink'] . "</p>");
132                    break;
133                case action_plugin_combo_router::TARGET_ORIGIN_CANONICAL:
134                    if (!$this->showMessageIfPublicAndPlanned()) {
135                        return;
136                    }
137                    $message = Message::createInfoMessage()
138                        ->addHtmlContent("<p>" . $this->lang['message_redirected_from_canonical'] . "</p>");
139                    break;
140                default:
141                    LogUtility::msg("The redirection source ($redirectSource) is unknown. It was not expected", LogUtility::LVL_MSG_ERROR, action_plugin_combo_router::CANONICAL);
142                    return;
143
144            }
145
146
147            // Add a list of page with the same name to the message
148            // if the redirections is not planned
149            if ($redirectSource !== action_plugin_combo_router::TARGET_ORIGIN_PAGE_RULES) {
150                $this->addToMessagePagesWithSameName($message, $pageIdOrigin);
151            }
152
153            if ($event->data === 'show' || $event->data === 'edit' || $event->data === 'search') {
154                $html = $message
155                    ->setPlugin($this)
156                    ->setClass(action_plugin_combo_routermessage::REDIRECT_MANAGER_BOX_CLASS)
157                    ->setCanonical(action_plugin_combo_router::CANONICAL)
158                    ->setSignatureName(action_plugin_combo_router::URL_MANAGER_NAME)
159                    ->toHtmlBox();
160                ptln($html);
161            }
162
163
164        }
165
166
167    }
168
169
170    /**
171     * Add the page with the same page name but in an other location
172     * @param Message $message
173     * @param $pageIdOrigin
174     */
175    function addToMessagePagesWithSameName(Message $message, $pageIdOrigin)
176    {
177
178        if (!$this->getConf(self::CONF_SHOW_PAGE_NAME_IS_NOT_UNIQUE) == 1) {
179            return;
180        }
181
182        global $ID;
183        // The page name
184        $pageName = noNS($pageIdOrigin);
185        $pagesWithSameName = Index::getOrCreate()->getPagesWithSameLastName($pageIdOrigin);
186
187        if (count($pagesWithSameName) > 0) {
188
189            $message->setType(Message::TYPE_WARNING);
190
191            // Assign the value to a variable to be able to use the construct .=
192            if ($message->getPlainTextContent() <> '') {
193                $message->addHtmlContent('<br/><br/>');
194            }
195            $message->addHtmlContent($this->lang['message_pagename_exist_one']);
196            $message->addHtmlContent('<ul>');
197
198            $i = 0;
199            foreach ($pagesWithSameName as $pageId => $title) {
200                if ($pageId === $ID) {
201                    continue;
202                }
203                $i++;
204                if ($i > 10) {
205                    $message->addHtmlContent('<li>' .
206                        tpl_link(
207                            wl($pageIdOrigin) . "?do=search&q=" . rawurldecode($pageName),
208                            "More ...",
209                            'class="" rel="nofollow" title="More..."',
210                            $return = true
211                        ) . '</li>');
212                    break;
213                }
214                if ($title == null) {
215                    $title = $pageId;
216                }
217                $message->addHtmlContent('<li>' .
218                    tpl_link(
219                        wl($pageId),
220                        $title,
221                        'class="" rel="nofollow" title="' . $title . '"',
222                        $return = true
223                    ) . '</li>');
224            }
225            $message->addHtmlContent('</ul>');
226        }
227
228    }
229
230
231    /**
232     * Set the redirect in a session that will be be read after the redirect
233     * in order to show a message to the user
234     * @param string $id
235     * @param string $redirectSource
236     */
237    static function notify($id, $redirectSource)
238    {
239        // Msg via session
240        if (!defined('NOSESSION')) {
241            //reopen session, store data and close session again
242            self::sessionStart();
243            $_SESSION[DOKU_COOKIE][self::ORIGIN_PAGE] = $id;
244            $_SESSION[DOKU_COOKIE][self::ORIGIN_TYPE] = $redirectSource;
245            self::sessionClose();
246
247        }
248    }
249
250
251    private static function sessionStart()
252    {
253        $sessionStatus = session_status();
254        switch ($sessionStatus) {
255            case PHP_SESSION_DISABLED:
256                throw new RuntimeException("Sessions are disabled");
257
258            case PHP_SESSION_NONE:
259                $result = @session_start();
260                if (!$result) {
261                    throw new RuntimeException("The session was not successfully started");
262                }
263                break;
264            case PHP_SESSION_ACTIVE:
265                break;
266        }
267    }
268
269    private static function sessionClose()
270    {
271        // Close the session
272        $phpVersion = phpversion();
273        if ($phpVersion > "7.2.0") {
274            $result = session_write_close();
275            if (!$result) {
276                // Session is really not a well known mechanism
277                // Set this error in a info level to not fail the test
278                LogUtility::msg("Failure to write the session", LogUtility::LVL_MSG_INFO);
279            }
280        } else {
281            session_write_close();
282        }
283
284    }
285
286    /**
287     * We don't saw the message if it was planned and
288     * it's a reader
289     * @return bool
290     */
291    private function showMessageIfPublicAndPlanned(): bool
292    {
293        if (Identity::isWriter()){
294            return true;
295        }
296        return $this->getConf(self::CONF_SHOW_MESSAGE_CLASSIC, self::CONF_SHOW_MESSAGE_CLASSIC_DEFAULT) == 1;
297    }
298
299}
300