1<?php
2/**
3 * Move Plugin Page Rewrite Functionality
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <gohr@cosmocode.de>
7 */
8// must be run within Dokuwiki
9if(!defined('DOKU_INC')) die();
10
11/**
12 * Class action_plugin_move_rewrite
13 */
14class action_plugin_move_rewrite extends DokuWiki_Action_Plugin {
15
16    /**
17     * Register event handlers.
18     *
19     * @param Doku_Event_Handler $controller The plugin controller
20     */
21    public function register(Doku_Event_Handler $controller) {
22        $controller->register_hook('IO_WIKIPAGE_READ', 'AFTER', $this, 'handle_read', array());
23        $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache', array());
24    }
25
26    /**
27     * Rewrite pages when they are read and they need to be updated.
28     *
29     * @param Doku_Event $event The event object
30     * @param mixed      $param Optional parameters (not used)
31     */
32    function handle_read(Doku_Event $event, $param) {
33        global $ACT, $conf;
34        static $stack = array();
35        // handle only reads of the current revision
36        if($event->data[3]) return;
37
38        // only rewrite if not in move already
39        $save = true;
40        if(helper_plugin_move_rewrite::isLocked()) {
41            $save = false;
42        }
43
44        $id = $event->data[2];
45        if($event->data[1]) $id = $event->data[1] . ':' . $id;
46
47        if(!$id) {
48            // try to reconstruct the id from the filename
49            $path = $event->data[0][0];
50            if(strpos($path, $conf['datadir']) === 0) {
51                $path = substr($path, strlen($conf['datadir']) + 1);
52                $id   = pathID($path);
53            }
54        }
55
56        if(isset($stack[$id])) return;
57
58        // Don't change the page when the user is currently changing the page content or the page is locked
59        $forbidden_actions = array('save', 'preview', 'recover', 'revert');
60        if((isset($ACT) && (
61                    in_array($ACT, $forbidden_actions) || (is_array($ACT) && in_array(key($ACT), $forbidden_actions)
62                    )))
63            // checklock checks if the page lock hasn't expired and the page hasn't been locked by another user
64            // the file exists check checks if the page is reported unlocked if a lock exists which means that
65            // the page is locked by the current user
66            || checklock($id) !== false || @file_exists(wikiLockFN($id))
67        ) return;
68
69        /** @var helper_plugin_move_rewrite $helper */
70        $helper = plugin_load('helper', 'move_rewrite', true);
71        if(!is_null($helper)) {
72            $stack[$id]    = true;
73            $event->result = $helper->rewritePage($id, $event->result, $save);
74            unset($stack[$id]);
75        }
76    }
77
78    /**
79     * Handle the cache events, it looks if a page needs to be rewritten so it can expire the cache of the page
80     *
81     * @param Doku_Event $event The even object
82     * @param mixed      $param Optional parameters (not used)
83     */
84    function handle_cache(Doku_Event $event, $param) {
85        global $conf;
86        /** @var $cache cache_parser */
87        $cache = $event->data;
88        $id    = $cache->page;
89        if(!$id) {
90            // try to reconstruct the id from the filename
91            $path = $cache->file;
92            if(strpos($path, $conf['datadir']) === 0) {
93                $path = substr($path, strlen($conf['datadir']) + 1);
94                $id   = pathID($path);
95            }
96        }
97        if($id) {
98            /** @var helper_plugin_move_rewrite $helper */
99            $helper = $this->loadHelper('move_rewrite');
100            if(!is_null($helper)) {
101                $meta = $helper->getMoveMeta($id);
102                if($meta && ($meta['pages'] || $meta['media'])) {
103                    $file = wikiFN($id, '', false);
104                    if(is_writable($file))
105                        $cache->depends['purge'] = true;
106                    else // FIXME: print error here or fail silently?
107                        msg('Error: Page ' . hsc($id) . ' needs to be rewritten because of page renames but is not writable.', -1);
108                }
109            }
110        }
111    }
112}
113