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