1<?php 2// must be run within Dokuwiki 3if (!defined('DOKU_INC')) die(); 4 5if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 6 7// Surprisingly there is no constant for the info level 8if (!defined('MANAGER404_MSG_ERROR')) define('MANAGER404_MSG_ERROR', -1); 9if (!defined('MANAGER404_MSG_INFO')) define('MANAGER404_MSG_INFO', 0); 10if (!defined('MANAGER404_MSG_SUCCESS')) define('MANAGER404_MSG_SUCCESS', 1); 11if (!defined('MANAGER404_MSG_NOTIFY')) define('MANAGER404_MSG_NOTIFY', 2); 12 13require_once(DOKU_PLUGIN . 'admin.php'); 14require_once(DOKU_INC . 'inc/parser/xhtml.php'); 15 16/** 17 * All DokuWiki plugins to extend the admin function 18 * need to inherit from this class 19 * 20 */ 21class admin_plugin_404manager extends DokuWiki_Admin_Plugin 22{ 23 24 // A static function to hold the 404 manager 25 private static $manager404 = null; 26 27 // Data Store Type 28 // The Data Store Type variable 29 private $dataStoreType; 30 31 // The Data Store Type possible value 32 const DATA_STORE_TYPE_CONF_FILE = 'confFile'; 33 const DATA_STORE_TYPE_SQLITE = 'sqlite'; 34 35 36 // Variable var and not public/private because php4 can't handle this kind of variable 37 38 // ################################### 39 // Data Stored in a conf file 40 // Deprecated 41 // ################################### 42 // The file path of the direct redirection (from an Page to a Page or URL) 43 // No more used, replaced by a sqlite database 44 const DATA_STORE_CONF_FILE_PATH = __DIR__ . "/404managerRedirect.conf"; 45 // The content of the conf file in memory 46 var $pageRedirections = array(); 47 48 49 // Use to pass parameter between the handle and the html function to keep the form data 50 var $redirectionSource = ''; 51 var $redirectionTarget = ''; 52 var $currentDate = ''; 53 // Deprecated 54 private $redirectionType; 55 // Deprecated 56 var $isValidate = ''; 57 // Deprecated 58 var $targetResourceType = 'Default'; 59 60 private $infoPlugin; 61 62 /** @var helper_plugin_sqlite $sqlite */ 63 private $sqlite; 64 65 // Name of the variable in the HTML form 66 const FORM_NAME_SOURCE_PAGE = 'SourcePage'; 67 const FORM_NAME_TARGET_PAGE = 'TargetPage'; 68 69 70 /** 71 * admin_plugin_404manager constructor. 72 * 73 * Use the get function instead 74 */ 75 public function __construct() 76 { 77 78 // enable direct access to language strings 79 // of use of $this->getLang 80 $this->setupLocale(); 81 $this->currentDate = date("c"); 82 $this->infoPlugin = $this->getInfo(); 83 84 85 } 86 87 /** 88 * @return admin_plugin_404manager 89 */ 90 public static function get() 91 { 92 if (self::$manager404 == null) { 93 self::$manager404 = new admin_plugin_404manager(); 94 } 95 return self::$manager404; 96 } 97 98 99 /** 100 * Access for managers allowed 101 */ 102 function forAdminOnly() 103 { 104 return false; 105 } 106 107 /** 108 * return sort order for position in admin menu 109 */ 110 function getMenuSort() 111 { 112 return 140; 113 } 114 115 /** 116 * return prompt for admin menu 117 * @param string $language 118 * @return string 119 */ 120 function getMenuText($language) 121 { 122 $menuText = $this->lang['AdminPageName']; 123 if ($menuText == '') { 124 $menuText = $this->infoPlugin['name']; 125 } 126 return $menuText; 127 } 128 129 /** 130 * handle user request 131 */ 132 function handle() 133 { 134 135 if ($_POST['Add']) { 136 137 $this->redirectionSource = $_POST[self::FORM_NAME_SOURCE_PAGE]; 138 $this->redirectionTarget = $_POST[self::FORM_NAME_TARGET_PAGE]; 139 140 if ($this->redirectionSource == $this->redirectionTarget) { 141 msg($this->lang['SameSourceAndTargetAndPage'] . ': ' . $this->redirectionSource . '', -1); 142 return; 143 } 144 145 146 // This a direct redirection 147 // If the source page exist, do nothing 148 if (page_exists($this->redirectionSource)) { 149 150 $title = false; 151 global $conf; 152 if ($conf['useheading']) { 153 $title = p_get_first_heading($this->redirectionSource); 154 } 155 if (!$title) $title = $this->redirectionSource; 156 msg($this->lang['SourcePageExist'] . ' : <a href="' . wl($this->redirectionSource) . '">' . hsc($title) . '</a>', -1); 157 return; 158 159 } else { 160 161 // Is this a direct redirection to a valid target page 162 if (!page_exists($this->redirectionTarget)) { 163 164 if ($this->isValidURL($this->redirectionTarget)) { 165 166 $this->targetResourceType = 'Url'; 167 168 } else { 169 170 msg($this->lang['NotInternalOrUrlPage'] . ': ' . $this->redirectionTarget . '', -1); 171 return; 172 173 } 174 175 } else { 176 177 $this->targetResourceType = 'Internal Page'; 178 179 } 180 $this->addRedirection($this->redirectionSource, $this->redirectionTarget); 181 msg($this->lang['Saved'], 1); 182 183 } 184 185 186 } 187 188 if ($_POST['Delete']) { 189 190 $redirectionId = $_POST['SourcePage']; 191 $this->deleteRedirection($redirectionId); 192 msg($this->lang['Deleted'], 1); 193 194 } 195 if ($_POST['Validate']) { 196 $redirectionId = $_POST['SourcePage']; 197 $this->validateRedirection($redirectionId); 198 msg($this->lang['Validated'], 1); 199 } 200 } 201 202 /** 203 * output appropriate html 204 */ 205 function html() 206 { 207 208 global $conf; 209 210 echo $this->locale_xhtml('intro'); 211 212 // Add a redirection 213 ptln('<h2><a name="add_redirection" id="add_redirection">' . $this->lang['AddModifyRedirection'] . '</a></h2>'); 214 ptln('<div class="level2">'); 215 ptln('<form action="" method="post">'); 216 ptln('<table class="inline">'); 217 218 ptln('<thead>'); 219 ptln(' <tr><th>' . $this->lang['Field'] . '</th><th>' . $this->lang['Value'] . '</th> <th>' . $this->lang['Information'] . '</th></tr>'); 220 ptln('</thead>'); 221 222 ptln('<tbody>'); 223 ptln(' <tr><td><label for="add_sourcepage" >' . $this->lang['source_page'] . ': </label></td><td><input type="text" id="add_sourcepage" name="' . self::FORM_NAME_SOURCE_PAGE . '" value="' . $this->redirectionSource . '" class="edit" /></td><td>' . $this->lang['source_page_info'] . '</td></td></tr>'); 224 ptln(' <tr><td><label for="add_targetpage" >' . $this->lang['target_page'] . ': </label></td><td><input type="text" id="add_targetpage" name="' . self::FORM_NAME_TARGET_PAGE . '" value="' . $this->redirectionTarget . '" class="edit" /></td><td>' . $this->lang['target_page_info'] . '</td></tr>'); 225 ptln(' <tr>'); 226 ptln(' <td colspan="3">'); 227 ptln(' <input type="hidden" name="do" value="admin" />'); 228 ptln(' <input type="hidden" name="page" value="404manager" />'); 229 ptln(' <input type="submit" name="Add" class="button" value="' . $this->lang['btn_addmodify'] . '" />'); 230 ptln(' </td>'); 231 ptln(' </tr>'); 232 ptln('</tbody>'); 233 ptln('</table>'); 234 ptln('</form>'); 235 236 // Add the file add from the lang directory 237 echo $this->locale_xhtml('add'); 238 ptln('</div>'); 239 240 241// List of redirection 242 ptln('<h2><a name="list_redirection" id="list_redirection">' . $this->lang['ListOfRedirection'] . '</a></h2>'); 243 ptln('<div class="level2">'); 244 245 ptln('<div class="table-responsive">'); 246 247 ptln('<table class="table table-hover">'); 248 ptln(' <thead>'); 249 ptln(' <tr>'); 250 ptln(' <th> </th>'); 251 ptln(' <th>' . $this->lang['SourcePage'] . '</th>'); 252 ptln(' <th>' . $this->lang['TargetPage'] . '</th>'); 253 ptln(' <th>' . $this->lang['CreationDate'] . '</th>'); 254 ptln(' </tr>'); 255 ptln(' </thead>'); 256 257 ptln(' <tbody>'); 258 259 260 foreach ($this->getRedirections() as $key => $row) { 261 262 if ($this->dataStoreType == self::DATA_STORE_TYPE_SQLITE) { 263 $sourcePageId = $row['SOURCE']; 264 $targetPageId = $row['TARGET']; 265 $creationDate = $row['CREATION_TIMESTAMP']; 266 } else { 267 $sourcePageId = $key; 268 $targetPageId = $row['TargetPage']; 269 $creationDate = $row['CreationDate']; 270 } 271 $title = false; 272 if ($conf['useheading']) { 273 $title = p_get_first_heading($targetPageId); 274 } 275 if (!$title) $title = $targetPageId; 276 277 278 ptln(' <tr class="redirect_info">'); 279 ptln(' <td>'); 280 ptln(' <form action="" method="post">'); 281 ptln(' <input type="image" src="' . DOKU_BASE . 'lib/plugins/404manager/images/delete.jpg" name="Delete" title="Delete" alt="Delete" value="Submit" />'); 282 ptln(' <input type="hidden" name="Delete" value="Yes" />'); 283 ptln(' <input type="hidden" name="SourcePage" value="' . $sourcePageId . '" />'); 284 ptln(' </form>'); 285 286 ptln(' </td>'); 287 print(' <td>'); 288 tpl_link(wl($sourcePageId), $this->truncateString($sourcePageId, 30), 'title="' . $sourcePageId . '" class="wikilink2" rel="nofollow"'); 289 ptln(' </td>'); 290 print ' <td>'; 291 tpl_link(wl($targetPageId), $this->truncateString($targetPageId, 30), 'title="' . hsc($title) . ' (' . $targetPageId . ')"'); 292 ptln(' </td>'); 293 ptln(' <td>' . $creationDate . '</td>'); 294 ptln(' </tr>'); 295 } 296 ptln(' </tbody>'); 297 ptln('</table>'); 298 ptln('</div>'); //End Table responsive 299 ptln('</div>'); // End level 2 300 301 302 } 303 304 /** 305 * Generate a text with a max length of $length 306 * and add ... if above 307 */ 308 function truncateString($myString, $length) 309 { 310 if (strlen($myString) > $length) { 311 $myString = substr($myString, 0, $length) . ' ...'; 312 } 313 return $myString; 314 } 315 316 /** 317 * Delete Redirection 318 * @param string $sourcePageId 319 */ 320 function deleteRedirection($sourcePageId) 321 { 322 323 if ($this->dataStoreType == null) { 324 $this->initDataStore(); 325 } 326 327 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 328 unset($this->pageRedirections[strtolower($sourcePageId)]); 329 $this->savePageRedirections(); 330 } else { 331 332 $res = $this->sqlite->query('delete from redirections where source = ?', $sourcePageId); 333 if (!$res) { 334 $this->throwRuntimeException("Something went wrong when deleting the redirections"); 335 } 336 337 } 338 339 } 340 341 /** 342 * Is Redirection of a page Id Present 343 * @param string $sourcePageId 344 * @return int 345 */ 346 function isRedirectionPresent($sourcePageId) 347 { 348 $sourcePageId = strtolower($sourcePageId); 349 350 if ($this->dataStoreType == null) { 351 $this->initDataStore(); 352 } 353 354 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 355 356 if (isset($this->pageRedirections[$sourcePageId])) { 357 return 1; 358 } else { 359 return 0; 360 } 361 362 } else { 363 364 $res = $this->sqlite->query("SELECT * FROM redirections"); 365 $count = $this->sqlite->res2count($res); 366 return $count; 367 368 } 369 370 } 371 372 /** 373 * @param $sourcePageId 374 * @param $targetPageId 375 */ 376 function addRedirection($sourcePageId, $targetPageId) 377 { 378 $this->addRedirectionWithDate($sourcePageId, $targetPageId, $this->currentDate); 379 } 380 381 /** 382 * Add Redirection 383 * This function was needed to migrate the date of the file conf store 384 * You would use normally the function addRedirection 385 * @param string $sourcePageId 386 * @param string $targetPageId 387 * @param $creationDate 388 */ 389 function addRedirectionWithDate($sourcePageId, $targetPageId, $creationDate) 390 { 391 392 // Lower page name is the dokuwiki Id 393 $sourcePageId = strtolower($sourcePageId); 394 395 if ($this->dataStoreType == null) { 396 $this->initDataStore(); 397 } 398 399 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 400 401 if (isset($this->pageRedirections[$sourcePageId])) { 402 $this->throwRuntimeException('Redirection for page (' . $sourcePageId . 'already exist'); 403 } 404 405 $this->pageRedirections[$sourcePageId]['TargetPage'] = $targetPageId; 406 $this->pageRedirections[$sourcePageId]['CreationDate'] = $creationDate; 407 // If the call come from the admin page and not from the process function 408 if (substr_count($_SERVER['HTTP_REFERER'], 'admin.php')) { 409 410 $this->pageRedirections[$sourcePageId]['IsValidate'] = 'Y'; 411 $this->pageRedirections[$sourcePageId]['CountOfRedirection'] = 0; 412 $this->pageRedirections[$sourcePageId]['LastRedirectionDate'] = $this->lang['Never']; 413 $this->pageRedirections[$sourcePageId]['LastReferrer'] = 'Never'; 414 415 } else { 416 417 $this->pageRedirections[$sourcePageId]['IsValidate'] = 'N'; 418 $this->pageRedirections[$sourcePageId]['CountOfRedirection'] = 1; 419 $this->pageRedirections[$sourcePageId]['LastRedirectionDate'] = $creationDate; 420 if ($_SERVER['HTTP_REFERER'] <> '') { 421 $this->pageRedirections[$sourcePageId]['LastReferrer'] = $_SERVER['HTTP_REFERER']; 422 } else { 423 $this->pageRedirections[$sourcePageId]['LastReferrer'] = $this->lang['Direct Access']; 424 } 425 426 } 427 428 if (!$this->isValidURL($targetPageId)) { 429 $this->pageRedirections[$sourcePageId]['TargetPageType'] = 'Internal Page'; 430 } else { 431 $this->pageRedirections[$sourcePageId]['TargetPageType'] = 'Url'; 432 } 433 434 $this->savePageRedirections(); 435 436 } else { 437 438 // Note the order is important 439 // because it's used in the bin of the update statement 440 $entry = array( 441 'target' => $targetPageId, 442 'creation_timestamp' => $creationDate, 443 'source' => $sourcePageId 444 ); 445 446 $statement = 'select * from redirections where source = ?'; 447 $res = $this->sqlite->query($statement, $sourcePageId); 448 $count = $this->sqlite->res2count($res); 449 if ($count <> 1) { 450 $res = $this->sqlite->storeEntry('redirections', $entry); 451 if (!$res) { 452 $this->throwRuntimeException("There was a problem during insertion"); 453 } 454 } else { 455 // Primary key constraint, the storeEntry function does not use an UPSERT 456 $statement = 'update redirections set target = ?, creation_timestamp = ? where source = ?'; 457 $res = $this->sqlite->query($statement, $entry); 458 if (!$res) { 459 $this->throwRuntimeException("There was a problem during the update"); 460 } 461 } 462 463 } 464 } 465 466 /** 467 * Validate a Redirection 468 * @param string $sourcePageId 469 */ 470 function validateRedirection($sourcePageId) 471 { 472 $sourcePageId = strtolower($sourcePageId); 473 474 if ($this->dataStoreType == null) { 475 $this->initDataStore(); 476 } 477 478 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 479 480 $this->pageRedirections[$sourcePageId]['IsValidate'] = 'Y'; 481 $this->savePageRedirections(); 482 } else { 483 484 $this->throwRuntimeException('Not implemented for a SQLite data store'); 485 486 } 487 } 488 489 /** 490 * Get IsValidate Redirection 491 * @param string $sourcePageId 492 * @return string 493 */ 494 function getIsValidate($sourcePageId) 495 { 496 $sourcePageId = strtolower($sourcePageId); 497 498 if ($this->dataStoreType == null) { 499 $this->initDataStore(); 500 } 501 502 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 503 504 if ($this->pageRedirections[$sourcePageId]['IsValidate'] == null) { 505 return 'N'; 506 } else { 507 return $this->pageRedirections[$sourcePageId]['IsValidate']; 508 } 509 } else { 510 511 $this->throwRuntimeException("Not Yet implemented"); 512 513 } 514 } 515 516 /** 517 * Get TargetPageType 518 * @param string $sourcePageId 519 * @return 520 * @throws Exception 521 */ 522 function getTargetPageType($sourcePageId) 523 { 524 if ($this->dataStoreType == null) { 525 $this->initDataStore(); 526 } 527 528 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 529 530 $sourcePageId = strtolower($sourcePageId); 531 return $this->pageRedirections[$sourcePageId]['TargetPageType']; 532 533 } else { 534 535 throw new Exception('Not Yet implemented'); 536 537 } 538 539 } 540 541 /** 542 * Get TargetResource (It can be an external URL as an intern page id 543 * @param string $sourcePageId 544 * @return 545 * @throws Exception 546 */ 547 function getRedirectionTarget($sourcePageId) 548 { 549 550 if ($this->dataStoreType == null) { 551 $this->initDataStore(); 552 } 553 554 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 555 556 $sourcePageId = strtolower($sourcePageId); 557 return $this->pageRedirections[strtolower($sourcePageId)]['TargetPage']; 558 559 } else { 560 561 $res = $this->sqlite->query("select target from redirections where source = ?", $sourcePageId); 562 if (!$res) { 563 throw new RuntimeException("An exception has occurred with the query"); 564 } 565 $value = $this->sqlite->res2single($res); 566 return $value; 567 568 } 569 } 570 571 /** 572 * 573 * * For a conf file, it will update the Redirection Action Data as Referrer, Count Of Redirection, Redirection Date 574 * * For a SQlite database, it will add a row into the log 575 * 576 * @param string $sourcePageId 577 * @param $targetPageId 578 * @param $type 579 */ 580 function logRedirection($sourcePageId, $targetPageId, $type) 581 { 582 if ($this->dataStoreType == null) { 583 $this->initDataStore(); 584 } 585 586 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 587 588 $sourcePageId = strtolower($sourcePageId); 589 $this->pageRedirections[$sourcePageId]['LastRedirectionDate'] = $this->currentDate; 590 $this->pageRedirections[$sourcePageId]['LastReferrer'] = $_SERVER['HTTP_REFERER']; 591 // This cause to add one after the first insert but yeah, this is going to dye anyway 592 $this->pageRedirections[$sourcePageId]['CountOfRedirection'] += 1; 593 $this->savePageRedirections(); 594 595 } else { 596 597 $row = array( 598 "TIMESTAMP" => $this->currentDate, 599 "SOURCE" => $sourcePageId, 600 "TARGET" => $targetPageId, 601 "REFERRER" => $_SERVER['HTTP_REFERER'], 602 "TYPE" => $type 603 ); 604 $res = $this->sqlite->storeEntry('redirections_log', $row); 605 606 if (!$res) { 607 throw new RuntimeException("An error occurred"); 608 } 609 } 610 } 611 612 /** 613 * Serialize and save the redirection data file 614 * 615 * ie Flush 616 * 617 */ 618 function savePageRedirections() 619 { 620 621 if ($this->dataStoreType == null) { 622 $this->initDataStore(); 623 } 624 625 if ($this->dataStoreType == self::DATA_STORE_TYPE_CONF_FILE) { 626 627 io_saveFile(self::DATA_STORE_CONF_FILE_PATH, serialize($this->pageRedirections)); 628 629 } else { 630 631 $this->throwRuntimeException('SavePageRedirections must no be called for a SQLite data store'); 632 633 } 634 } 635 636 /** 637 * Validate URL 638 * Allows for port, path and query string validations 639 * @param string $url string containing url user input 640 * @return boolean Returns TRUE/FALSE 641 */ 642 function isValidURL($url) 643 { 644 // of preg_match('/^https?:\/\//',$url) ? from redirect plugin 645 return preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url); 646 } 647 648 649 /** 650 * @param $inputExpression 651 * @return false|int 1|0 652 * returns: 653 * - 1 if the input expression is a pattern, 654 * - 0 if not, 655 * - FALSE if an error occurred. 656 */ 657 static function isRegularExpression($inputExpression) 658 { 659 660 $regularExpressionPattern = "/(\\/.*\\/[gmixXsuUAJ]?)/"; 661 return preg_match($regularExpressionPattern, $inputExpression); 662 663 } 664 665 /** 666 * 667 * Set the data store type. The value must be one of the constants 668 * * DATA_STORE_TYPE_CONF_FILE 669 * * DATA_STORE_TYPE_SQLITE 670 * 671 * @param $dataStoreType 672 * @return $this 673 * 674 */ 675 public function setDataStoreType($dataStoreType) 676 { 677 $this->dataStoreType = $dataStoreType; 678 $this->initDataStore(); 679 return $this; 680 } 681 682 /** 683 * Init the data store 684 */ 685 private function initDataStore() 686 { 687 688 if ($this->dataStoreType == null) { 689 $this->sqlite = plugin_load('helper', 'sqlite'); 690 if (!$this->sqlite) { 691 $this->dataStoreType = self::DATA_STORE_TYPE_CONF_FILE; 692 } else { 693 $this->dataStoreType = self::DATA_STORE_TYPE_SQLITE; 694 } 695 } 696 697 if ($this->getDataStoreType() == self::DATA_STORE_TYPE_CONF_FILE) { 698 699 msg($this->getLang('SqliteMandatory'), MANAGER404_MSG_INFO, $allow = MSG_MANAGERS_ONLY); 700 701 //Set the redirection data 702 if (@file_exists(self::DATA_STORE_CONF_FILE_PATH)) { 703 $this->pageRedirections = unserialize(io_readFile(self::DATA_STORE_CONF_FILE_PATH, false)); 704 } 705 706 } else { 707 708 // initialize the database connection 709 $pluginName = $this->infoPlugin['base']; 710 if ($this->sqlite == null) { 711 $this->sqlite = plugin_load('helper', 'sqlite'); 712 if (!$this->sqlite) { 713 $this->throwRuntimeException("Unable to load the sqlite plugin"); 714 } 715 } 716 $init = $this->sqlite->init($pluginName, DOKU_PLUGIN . $pluginName . '/db/'); 717 if (!$init) { 718 msg($this->lang['SqliteUnableToInitialize'], MSG_MANAGERS_ONLY); 719 return; 720 } 721 722 // Migration of the old store 723 if (@file_exists(self::DATA_STORE_CONF_FILE_PATH)) { 724 $this->dataStoreMigration(); 725 } 726 727 728 } 729 730 } 731 732 /** 733 * Delete all redirections 734 * Use with caution 735 */ 736 function deleteAllRedirections() 737 { 738 if ($this->dataStoreType == null) { 739 $this->initDataStore(); 740 } 741 742 if ($this->dataStoreType == self::DATA_STORE_TYPE_SQLITE) { 743 744 $res = $this->sqlite->query("delete from redirections"); 745 if (!$res) { 746 $this->throwRuntimeException('Errors during delete of all redirections'); 747 } 748 749 } else { 750 751 if (file_exists(self::DATA_STORE_CONF_FILE_PATH)) { 752 $res = unlink(self::DATA_STORE_CONF_FILE_PATH); 753 if (!$res) { 754 $this->throwRuntimeException('Unable to delete the file ' . self::DATA_STORE_TYPE_CONF_FILE); 755 } 756 } 757 $this->pageRedirections = array(); 758 759 } 760 } 761 762 /** 763 * Return the number of redirections 764 * @return integer 765 */ 766 function countRedirections() 767 { 768 if ($this->dataStoreType == null) { 769 $this->initDataStore(); 770 } 771 772 if ($this->dataStoreType == self::DATA_STORE_TYPE_SQLITE) { 773 774 $res = $this->sqlite->query("select count(1) from redirections"); 775 if (!$res) { 776 throw new RuntimeException('Errors during delete of all redirections'); 777 } 778 $value = $this->sqlite->res2single($res); 779 return $value; 780 781 } else { 782 783 return count($this->pageRedirections); 784 785 } 786 } 787 788 public function getDataStoreType() 789 { 790 if ($this->dataStoreType == null) { 791 $this->initDataStore(); 792 } 793 return $this->dataStoreType; 794 } 795 796 /** 797 * @return array 798 */ 799 private function getRedirections() 800 { 801 if ($this->dataStoreType == null) { 802 $this->initDataStore(); 803 } 804 805 if ($this->dataStoreType == self::DATA_STORE_TYPE_SQLITE) { 806 807 $res = $this->sqlite->query("select * from redirections"); 808 if (!$res) { 809 throw new RuntimeException('Errors during select of all redirections'); 810 } 811 $row = $this->sqlite->res2arr($res); 812 return $row; 813 814 } else { 815 816 return $this->pageRedirections; 817 818 } 819 } 820 821 /** 822 * Dokuwiki will show a pink message when throwing an eexception 823 * and it's difficult to see from where it comes 824 * 825 * This utility function will add the plugin name to it 826 * 827 * @param $message 828 */ 829 private function throwRuntimeException($message): void 830 { 831 throw new RuntimeException($this->getPluginName() . ' - ' . $message); 832 } 833 834 /** 835 * Migrate from a conf file to sqlite 836 */ 837 function dataStoreMigration() 838 { 839 if (!file_exists(self::DATA_STORE_CONF_FILE_PATH)) { 840 $this->throwRuntimeException("The file to migrate does not exist (" . self::DATA_STORE_CONF_FILE_PATH . ")"); 841 } 842 // We cannot use the getRedirections method because this is a sqlite data store 843 // it will return nothing 844 $pageRedirections = unserialize(io_readFile(self::DATA_STORE_CONF_FILE_PATH, false)); 845 foreach ($pageRedirections as $key => $row) { 846 847 848 $sourcePageId = $key; 849 $targetPageId = $row['TargetPage']; 850 $creationDate = $row['CreationDate']; 851 $isValidate = $row['IsValidate']; 852 853 if ($isValidate == 'Y') { 854 $this->addRedirectionWithDate($sourcePageId, $targetPageId, $creationDate); 855 } 856 } 857 858 rename(self::DATA_STORE_CONF_FILE_PATH, self::DATA_STORE_CONF_FILE_PATH . '.migrated'); 859 860 } 861 862 863} 864