1<?php
2
3use ComboStrap\DirectoryLayout;
4use ComboStrap\LogUtility;
5use ComboStrap\PageRules;
6use ComboStrap\PluginUtility;
7use ComboStrap\Site;
8
9
10require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
11
12
13/**
14 * The admin pages
15 * need to inherit from this class
16 *
17 *
18 * ! important !
19 * The suffix of the class name should:
20 *   * be equal to the name of the file
21 *   * and have only letters
22 */
23class admin_plugin_combo_pagerules extends DokuWiki_Admin_Plugin
24{
25    const DELETE_ACTION = 'Delete';
26    const SAVE_ACTION = 'save';
27
28    /**
29     * @var PageRules
30     */
31    private PageRules $pageRuleManager;
32
33
34    /**
35     * admin_plugin_combo constructor.
36     *
37     * Use the get function instead
38     */
39    public function __construct()
40    {
41
42        // enable direct access to language strings
43        // of use of $this->getLang
44        $this->setupLocale();
45
46
47    }
48
49    /**
50     * Handle Sqlite instantiation  here and not in the constructor
51     * to not make sqlite mandatory everywhere
52     */
53    private function initiatePageRuleManager()
54    {
55
56        if (!isset($this->pageRuleManager)) {
57
58            $this->pageRuleManager = new PageRules();
59
60        }
61    }
62
63
64    /**
65     * Access for managers allowed
66     */
67    function forAdminOnly(): bool
68    {
69        return false;
70    }
71
72    /**
73     * return sort order for position in admin menu
74     */
75    function getMenuSort(): int
76    {
77        return 140;
78    }
79
80    /**
81     * return prompt for admin menu
82     * @param string $language
83     * @return string
84     */
85    function getMenuText($language): string
86    {
87        return ucfirst(PluginUtility::$PLUGIN_NAME) . " - " . $this->lang['PageRules'];
88    }
89
90    public function getMenuIcon()
91    {
92        return DirectoryLayout::getComboImagesDirectory()->resolve('page-next.svg')->toAbsoluteId();
93    }
94
95
96    /**
97     * handle user request
98     */
99    function handle()
100    {
101
102        $this->initiatePageRuleManager();
103
104        /**
105         * If one of the form submit has the add key
106         */
107        if (($_POST[self::SAVE_ACTION] ?? null) && checkSecurityToken()) {
108
109            $id = $_POST[PageRules::ID_NAME] ?? null;
110            $matcher = $_POST[PageRules::MATCHER_NAME] ?? null;
111            $target = $_POST[PageRules::TARGET_NAME] ?? null;
112            $priority = $_POST[PageRules::PRIORITY_NAME] ?? null;
113
114            if ($matcher == null) {
115                msg('Matcher can not be null', LogUtility::LVL_MSG_ERROR);
116                return;
117            }
118            if ($target == null) {
119                msg('Target can not be null', LogUtility::LVL_MSG_ERROR);
120                return;
121            }
122
123            if ($matcher == $target) {
124                msg($this->lang['SameSourceAndTargetAndPage'] . ': ' . $matcher . '', LogUtility::LVL_MSG_ERROR);
125                return;
126            }
127
128            if ($id == null) {
129                if (!$this->pageRuleManager->patternExists($matcher)) {
130                    $this->pageRuleManager->addRule($matcher, $target, $priority);
131                    msg($this->lang['Saved'], LogUtility::LVL_MSG_INFO);
132                } else {
133                    msg("The matcher pattern ($matcher) already exists. The page rule was not inserted.", LogUtility::LVL_MSG_ERROR);
134                }
135            } else {
136                $this->pageRuleManager->updateRule($id, $matcher, $target, $priority);
137                msg($this->lang['Saved'], LogUtility::LVL_MSG_INFO);
138            }
139
140
141        }
142
143        if (($_POST[self::DELETE_ACTION] ?? null) && checkSecurityToken()) {
144
145            $ruleId = $_POST[PageRules::ID_NAME];
146            $this->pageRuleManager->deleteRule($ruleId);
147            msg($this->lang['Deleted'], LogUtility::LVL_MSG_INFO);
148
149        }
150
151    }
152
153    /**
154     * output appropriate html
155     * TODO: Add variable parsing where the key is the key of the lang object ??
156     */
157    function html()
158    {
159
160        $this->initiatePageRuleManager();
161
162        ptln('<h1>' . ucfirst(PluginUtility::$PLUGIN_NAME) . ' - ' . ucfirst($this->getPluginComponent()) . '</a></h1>');
163        $relativePath = 'admin/' . $this->getPluginComponent() . '_intro';
164        echo $this->locale_xhtml($relativePath);
165
166        // Forms
167        if ($_POST['upsert'] ?? null) {
168
169            $matcher = null;
170            $target = null;
171            $priority = 1;
172
173            // Update ?
174            $id = $_POST[PageRules::ID_NAME];
175            if ($id != null) {
176                $rule = $this->pageRuleManager->getRule($id);
177                $matcher = $rule[PageRules::MATCHER_NAME];
178                $target = $rule[PageRules::TARGET_NAME];
179                $priority = $rule[PageRules::PRIORITY_NAME];
180            }
181
182
183            // Forms
184            ptln('<div class="level2" >');
185            ptln('<div id="form_container" style="max-width: 600px;">');
186            ptln('<form action="" method="post">');
187            ptln('<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />');
188            ptln('<p><b>If the Dokuwiki ID matches the following pattern:</b></p>');
189            $matcherDefault = "";
190            if ($matcher != null) {
191                $matcherDefault = 'value="' . $matcher . '"';
192            }
193            ptln('<label for="' . PageRules::MATCHER_NAME . '">(You can use the asterisk (*) character)</label>');
194            ptln('<p><input type="text"  style="width: 100%;" id="' . PageRules::MATCHER_NAME . '" required="required" name="' . PageRules::MATCHER_NAME . '" ' . $matcherDefault . ' class="edit" placeholder="pattern"/> </p>');
195            ptln('<p><b>Then applies this redirect settings:</b></p>');
196            $targetDefault = "";
197            if ($matcher != null) {
198                $targetDefault = 'value="' . $target . '"';
199            }
200            ptln('<label for="' . PageRules::TARGET_NAME . '">Target: (A DokuWiki Id or an URL where you can use the ($) group character)</label>');
201            ptln('<p><input type="text" style="width: 100%;" required="required" id="' . PageRules::TARGET_NAME . '" name="' . PageRules::TARGET_NAME . '" ' . $targetDefault . ' class="edit" placeholder="target" /></p>');
202            ptln('<label for="' . PageRules::PRIORITY_NAME . '">Priority: (The order in which rules are applied)</label>');
203            ptln('<p><input type="text" id="' . PageRules::PRIORITY_NAME . '." style="width: 100%;" required="required" placeholder="priority" name="' . PageRules::PRIORITY_NAME . '" value="' . $priority . '" class="edit" /></p>');
204            ptln('<input type="hidden" name="do"    value="admin" />');
205            if ($id != null) {
206                ptln('<input type="hidden" name="' . PageRules::ID_NAME . '" value="' . $id . '" />');
207            }
208            ptln('<input type="hidden" name="page"  value="' . $this->getPluginName() . '_' . $this->getPluginComponent() . '" />');
209            ptln('<p>');
210            ptln('<a class="btn btn-light" href="?do=admin&page=webcomponent_pagerules" > ' . 'Cancel' . ' <a/>');
211            ptln('<input class="btn btn-primary" type="submit" name="save" class="button" value="' . 'Save' . '" />');
212            ptln('</p>');
213            ptln('</form>');
214            ptln('</div>');
215
216            ptln('</div>');
217
218
219        } else {
220
221            ptln('<h2><a id="pagerules_list">' . 'Rules' . '</a></h2>');
222            ptln('<div class="level2">');
223
224            ptln('<form class="pt-3 pb-3" action="" method="post">');
225            ptln('<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />');
226            ptln('    <input type="hidden" name="do"    value="admin" />');
227            ptln('	<input type="hidden" name="page"  value="' . $this->getPluginName() . '_' . $this->getPluginComponent() . '" />');
228            ptln('	<input type="submit" name="upsert" name="Create a page rule" class="button" value="' . $this->getLangOrDefault('AddNewRule', 'Add a new rule') . '" />');
229            ptln('</form>');
230
231            // List of redirection
232            $rules = $this->pageRuleManager->getRules();
233
234            if (sizeof($rules) == 0) {
235                ptln('<p>No Rules found</p>');
236            } else {
237                ptln('<div class="table-responsive">');
238
239                ptln('<table class="table table-hover">');
240                ptln('	<thead>');
241                ptln('		<tr>');
242                ptln('			<th>&nbsp;</th>');
243                ptln('			<th>' . $this->getLangOrDefault('Priority', 'Priority') . '</th>');
244                ptln('			<th>' . $this->getLangOrDefault('Matcher', 'Matcher') . '</th>');
245                ptln('			<th>' . $this->getLangOrDefault('Target', 'Target') . '</th>');
246                ptln('			<th>' . $this->getLangOrDefault('NDate', 'Date') . '</th>');
247                ptln('	    </tr>');
248                ptln('	</thead>');
249                ptln('	<tbody>');
250
251
252                foreach ($rules as $key => $row) {
253
254                    $id = $row[PageRules::ID_NAME];
255                    $matcher = $row[PageRules::MATCHER_NAME];
256                    $target = $row[PageRules::TARGET_NAME];
257                    $timestamp = $row[PageRules::TIMESTAMP_NAME];
258                    $priority = $row[PageRules::PRIORITY_NAME];
259
260
261                    ptln('	  <tr class="redirect_info">');
262                    ptln('		<td>');
263                    ptln('			<form action="" method="post" style="display: inline-block">');
264                    ptln('<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />');
265                    ptln('<button style="background: none;border: 0;">');
266                    ptln(inlineSVG(DirectoryLayout::getComboImagesDirectory()->resolve('delete.svg')->toAbsoluteId()));
267                    ptln('</button>');
268                    ptln('				<input type="hidden" name="Delete"  value="Yes" />');
269                    ptln('				<input type="hidden" name="' . PageRules::ID_NAME . '"  value="' . $id . '" />');
270                    ptln('			</form>');
271                    ptln('			<form action="" method="post" style="display: inline-block">');
272                    ptln('<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />');
273                    ptln('<button style="background: none;border: 0;">');
274                    ptln(inlineSVG(DirectoryLayout::getComboImagesDirectory()->resolve('file-document-edit-outline.svg')->toAbsoluteId()));
275                    ptln('</button>');
276                    ptln('				<input type="hidden" name="upsert"  value="Yes" />');
277                    ptln('				<input type="hidden" name="' . PageRules::ID_NAME . '"  value="' . $id . '" />');
278                    ptln('			</form>');
279
280                    ptln('		</td>');
281                    ptln('		<td>' . $priority . '</td>');
282                    ptln('	    <td>' . $matcher . '</td>');
283                    ptln('		<td>' . $target . '</td>');
284                    ptln('		<td>' . $timestamp . '</td>');
285                    ptln('    </tr>');
286                }
287                ptln('  </tbody>');
288                ptln('</table>');
289                ptln('</div>'); //End Table responsive
290            }
291
292            ptln('</div>'); // End level 2
293
294
295        }
296
297
298    }
299
300    /**
301     * An utility function to return the plugin translation or a default value
302     * @param $id
303     * @param $default
304     * @return mixed|string
305     */
306    private function getLangOrDefault($id, $default)
307    {
308        $lang = $this->getLang($id);
309        return $lang != '' ? $lang : $default;
310    }
311
312
313    static function getAdminPageName()
314    {
315        return PluginUtility::getAdminPageName(get_called_class());
316    }
317
318}
319