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>&nbsp;</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