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