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> </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