xref: /plugin/combo/action/linkmove.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1007225e5Sgerardnico<?php
2007225e5Sgerardnico
337748cd8SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
4*c3437056SNickeau
5*c3437056SNickeauuse ComboStrap\Alias;
6*c3437056SNickeauuse ComboStrap\Aliases;
7*c3437056SNickeauuse ComboStrap\DatabasePageRow;
8*c3437056SNickeauuse ComboStrap\ExceptionComboRuntime;
9*c3437056SNickeauuse ComboStrap\File;
10*c3437056SNickeauuse ComboStrap\LinkUtility;
11*c3437056SNickeauuse ComboStrap\LogUtility;
12*c3437056SNickeauuse ComboStrap\MetadataDbStore;
13*c3437056SNickeauuse ComboStrap\MetadataDokuWikiStore;
14*c3437056SNickeauuse ComboStrap\Page;
15*c3437056SNickeauuse ComboStrap\PageId;
16*c3437056SNickeauuse ComboStrap\PluginUtility;
17*c3437056SNickeauuse ComboStrap\Site;
18*c3437056SNickeau
19007225e5Sgerardnico
20007225e5Sgerardnico/**
21007225e5Sgerardnico * Class action_plugin_combo_move
22*c3437056SNickeau * Handle the move of a page in order to update:
23*c3437056SNickeau *   * the link
24*c3437056SNickeau *   * the data in the database
25007225e5Sgerardnico */
26007225e5Sgerardnicoclass action_plugin_combo_linkmove extends DokuWiki_Action_Plugin
27007225e5Sgerardnico{
28007225e5Sgerardnico
29*c3437056SNickeau
30*c3437056SNickeau    const CANONICAL = "move";
31*c3437056SNickeau
32*c3437056SNickeau    private static function checkAndSendAMessageIfLockFilePresent(): bool
33*c3437056SNickeau    {
34*c3437056SNickeau        $lockFile = File::createFromPath(Site::getDataDirectory() . "/locks_plugin_move.lock");
35*c3437056SNickeau        if (!$lockFile->exists()) {
36*c3437056SNickeau            return false;
37*c3437056SNickeau        }
38*c3437056SNickeau        $lockFileDateTimeModified = $lockFile->getModifiedTime();
39*c3437056SNickeau        $lockFileModifiedTimestamp = $lockFileDateTimeModified->getTimestamp();
40*c3437056SNickeau        $now = time();
41*c3437056SNickeau
42*c3437056SNickeau        $distance = $now - $lockFileModifiedTimestamp;
43*c3437056SNickeau        $lockFileAgeInMinute = ($distance) / 60;
44*c3437056SNickeau        if ($lockFileAgeInMinute > 5) {
45*c3437056SNickeau            LogUtility::msg("The move lockfile ($lockFile) exists and is older than 5 minutes (exactly $lockFileAgeInMinute minutes). If you are no more in a move, you should delete this file otherwise it will disable the move of page and the cache.");
46*c3437056SNickeau            return true;
47*c3437056SNickeau        }
48*c3437056SNickeau        return false;
49*c3437056SNickeau    }
50*c3437056SNickeau
51007225e5Sgerardnico    /**
52531e725cSNickeau     * As explained https://www.dokuwiki.org/plugin:move#support_for_other_plugins
53007225e5Sgerardnico     * @param Doku_Event_Handler $controller
54007225e5Sgerardnico     */
55007225e5Sgerardnico    function register(Doku_Event_Handler $controller)
56007225e5Sgerardnico    {
57*c3437056SNickeau
58*c3437056SNickeau        /**
59*c3437056SNickeau         * To rewrite the page meta in the database
60*c3437056SNickeau         */
61*c3437056SNickeau        $controller->register_hook('PLUGIN_MOVE_PAGE_RENAME', 'BEFORE', $this, 'handle_rename_before', array());
62*c3437056SNickeau        $controller->register_hook('PLUGIN_MOVE_PAGE_RENAME', 'AFTER', $this, 'handle_rename_after', array());
63*c3437056SNickeau
64*c3437056SNickeau        /**
65*c3437056SNickeau         * To rewrite the link
66*c3437056SNickeau         */
67*c3437056SNickeau        $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'handle_link', array());
68*c3437056SNickeau
69*c3437056SNickeau
70*c3437056SNickeau        /**
71*c3437056SNickeau         * Check for the presence of a lock file
72*c3437056SNickeau         */
73*c3437056SNickeau        $controller->register_hook('PARSER_WIKITEXT_PREPROCESS', 'BEFORE', $this, 'check_lock_file_age', array());
74*c3437056SNickeau
75*c3437056SNickeau
76007225e5Sgerardnico    }
77007225e5Sgerardnico
78007225e5Sgerardnico    /**
79*c3437056SNickeau     * @param Doku_Event $event
80*c3437056SNickeau     * @param $params
81*c3437056SNickeau     *
82*c3437056SNickeau     * When a lock file is present,
83*c3437056SNickeau     * the move plugin will purge the data in {@link action_plugin_move_rewrite::handle_cache()}
84*c3437056SNickeau     * making the rendering fucking slow
85*c3437056SNickeau     * We check that the lock file is not
86*c3437056SNickeau     */
87*c3437056SNickeau    function check_lock_file_age(Doku_Event $event, $params)
88*c3437056SNickeau    {
89*c3437056SNickeau        self::checkAndSendAMessageIfLockFilePresent();
90*c3437056SNickeau
91*c3437056SNickeau    }
92*c3437056SNickeau
93*c3437056SNickeau    /**
94*c3437056SNickeau     * Handle the path modification of a page
95*c3437056SNickeau     * @param Doku_Event $event - https://www.dokuwiki.org/plugin:move#for_plugin_authors
96*c3437056SNickeau     * @param $params
97*c3437056SNickeau     *
98*c3437056SNickeau     */
99*c3437056SNickeau    function handle_rename_before(Doku_Event $event, $params)
100*c3437056SNickeau    {
101*c3437056SNickeau        /**
102*c3437056SNickeau         * Check that the lock file is not older
103*c3437056SNickeau         * Lock file bigger than 5 minutes
104*c3437056SNickeau         * Is not really possible
105*c3437056SNickeau         */
106*c3437056SNickeau        $result = self::checkAndSendAMessageIfLockFilePresent();
107*c3437056SNickeau        if ($result === true) {
108*c3437056SNickeau            $event->preventDefault();
109*c3437056SNickeau            LogUtility::msg("The move lock file is present, the move was canceled.");
110*c3437056SNickeau        }
111*c3437056SNickeau
112*c3437056SNickeau    }
113*c3437056SNickeau
114*c3437056SNickeau    /**
115*c3437056SNickeau     * Handle the path modification of a page after
116*c3437056SNickeau     *
117*c3437056SNickeau     * The metadata file should also have been moved
118*c3437056SNickeau     *
119*c3437056SNickeau     * @param Doku_Event $event - https://www.dokuwiki.org/plugin:move#for_plugin_authors
120*c3437056SNickeau     * @param $params
121*c3437056SNickeau     *
122*c3437056SNickeau     */
123*c3437056SNickeau    function handle_rename_after(Doku_Event $event, $params)
124*c3437056SNickeau    {
125*c3437056SNickeau        /**
126*c3437056SNickeau         *
127*c3437056SNickeau         * $event->data
128*c3437056SNickeau         * src_id ⇒ string – the original ID of the page
129*c3437056SNickeau         * dst_id ⇒ string – the new ID of the page
130*c3437056SNickeau         */
131*c3437056SNickeau        $sourceId = $event->data["src_id"];
132*c3437056SNickeau        $targetId = $event->data["dst_id"];
133*c3437056SNickeau        try {
134*c3437056SNickeau
135*c3437056SNickeau            /**
136*c3437056SNickeau             * Update the dokuwiki id and path
137*c3437056SNickeau             */
138*c3437056SNickeau            $databasePage = DatabasePageRow::createFromDokuWikiId($sourceId);
139*c3437056SNickeau            if (!$databasePage->exists()) {
140*c3437056SNickeau                return;
141*c3437056SNickeau            }
142*c3437056SNickeau            $databasePage->updatePathAndDokuwikiId($targetId);
143*c3437056SNickeau
144*c3437056SNickeau            /**
145*c3437056SNickeau             * Check page id
146*c3437056SNickeau             */
147*c3437056SNickeau            $targetPage = Page::createPageFromId($targetId);
148*c3437056SNickeau            $targetPageId = PageId::createForPage($targetPage);
149*c3437056SNickeau            $targetPageIdValue = $targetPageId->getValueFromStore();
150*c3437056SNickeau            $databasePageIdValue = $databasePage->getPageId();
151*c3437056SNickeau
152*c3437056SNickeau            if ($databasePageIdValue !== $targetPageIdValue) {
153*c3437056SNickeau                // this should never happened in test/dev
154*c3437056SNickeau                $targetPageId->setValueForce($targetPageIdValue);
155*c3437056SNickeau            }
156*c3437056SNickeau
157*c3437056SNickeau            /**
158*c3437056SNickeau             * Add the alias
159*c3437056SNickeau             */
160*c3437056SNickeau            Aliases::createForPage($targetPage)
161*c3437056SNickeau                ->addAlias($sourceId)
162*c3437056SNickeau                ->setWriteStore(MetadataDokuWikiStore::class)
163*c3437056SNickeau                ->sendToWriteStore()
164*c3437056SNickeau                ->persist()
165*c3437056SNickeau                ->setReadStore(MetadataDbStore::class)
166*c3437056SNickeau                ->sendToWriteStore()
167*c3437056SNickeau                ->persist();
168*c3437056SNickeau
169*c3437056SNickeau
170*c3437056SNickeau        } catch (Exception $exception) {
171*c3437056SNickeau            // We catch the errors if any to not stop the move
172*c3437056SNickeau            // There is no transaction feature (it happens or not)
173*c3437056SNickeau            $message = "An error occurred during the move replication to the database. Error message was: " . $exception->getMessage();
174*c3437056SNickeau            if (PluginUtility::isDevOrTest()) {
175*c3437056SNickeau                throw new RuntimeException($exception);
176*c3437056SNickeau            } else {
177*c3437056SNickeau                LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL);
178*c3437056SNickeau            }
179*c3437056SNickeau        }
180*c3437056SNickeau
181*c3437056SNickeau    }
182*c3437056SNickeau
183*c3437056SNickeau
184*c3437056SNickeau    /**
185007225e5Sgerardnico     * Handle the move of a page
186007225e5Sgerardnico     * @param Doku_Event $event
187007225e5Sgerardnico     * @param $params
188007225e5Sgerardnico     */
189*c3437056SNickeau    function handle_link(Doku_Event $event, $params)
190007225e5Sgerardnico    {
191007225e5Sgerardnico        /**
192ef295d81Sgerardnico         * The handlers is the name of the component (ie refers to the {@link syntax_plugin_combo_link} handler)
193ef295d81Sgerardnico         * and 'rewrite_combo' to the below method
194007225e5Sgerardnico         */
195ef295d81Sgerardnico        $event->data['handlers'][syntax_plugin_combo_link::COMPONENT] = array($this, 'rewrite_combo');
196007225e5Sgerardnico    }
197007225e5Sgerardnico
198007225e5Sgerardnico    /**
199007225e5Sgerardnico     *
200007225e5Sgerardnico     * @param $match
201007225e5Sgerardnico     * @param $state
202007225e5Sgerardnico     * @param $pos
203007225e5Sgerardnico     * @param $plugin
204007225e5Sgerardnico     * @param helper_plugin_move_handler $handler
205007225e5Sgerardnico     */
206007225e5Sgerardnico    public function rewrite_combo($match, $state, $pos, $plugin, helper_plugin_move_handler $handler)
207007225e5Sgerardnico    {
208007225e5Sgerardnico        /**
2095f891b7eSNickeau         * The original move method
2105f891b7eSNickeau         * is {@link helper_plugin_move_handler::internallink()}
2115f891b7eSNickeau         *
212007225e5Sgerardnico         */
2135f891b7eSNickeau        if ($state == DOKU_LEXER_ENTER) {
2145f891b7eSNickeau            $ref = LinkUtility::parse($match)[LinkUtility::ATTRIBUTE_REF];
2155f891b7eSNickeau            $link = new LinkUtility($ref);
2165f891b7eSNickeau            if ($link->getType() == LinkUtility::TYPE_INTERNAL) {
217007225e5Sgerardnico
2185f891b7eSNickeau                $handler->internallink($match, $state, $pos);
2195f891b7eSNickeau                $suffix = "]]";
22021913ab3SNickeau                if (substr($handler->calls, -strlen($suffix)) == $suffix) {
22121913ab3SNickeau                    $handler->calls = substr($handler->calls, 0, strlen($handler->calls) - strlen($suffix));
2225f891b7eSNickeau                }
2235f891b7eSNickeau
2245f891b7eSNickeau            } else {
2255f891b7eSNickeau
2265f891b7eSNickeau                // Other type of links
2275f891b7eSNickeau                $handler->calls .= $match;
2285f891b7eSNickeau
2295f891b7eSNickeau            }
2305f891b7eSNickeau        } else {
2315f891b7eSNickeau
2325f891b7eSNickeau            // Description and ending
2335f891b7eSNickeau            $handler->calls .= $match;
2345f891b7eSNickeau
2355f891b7eSNickeau        }
236007225e5Sgerardnico    }
237007225e5Sgerardnico
238007225e5Sgerardnico
239007225e5Sgerardnico}
240