1<?php
2
3use ComboStrap\ComboFs;
4use ComboStrap\DatabasePageRow;
5use ComboStrap\Event;
6use ComboStrap\ExceptionCompile;
7use ComboStrap\ExceptionNotFound;
8use ComboStrap\ExecutionContext;
9use ComboStrap\FileSystems;
10use ComboStrap\LocalPath;
11use ComboStrap\LogUtility;
12use ComboStrap\MarkupCacheDependencies;
13use ComboStrap\MarkupPath;
14use ComboStrap\PageId;
15use ComboStrap\PagePath;
16use ComboStrap\Site;
17use ComboStrap\SlotSystem;
18
19
20require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
21
22/**
23 * When a page is added or deleted from the file system
24 */
25class action_plugin_combo_pagesystemmutation extends DokuWiki_Action_Plugin
26{
27
28
29    public const PAGE_SYSTEM_MUTATION_EVENT_NAME = 'page_system_mutation';
30
31    const TYPE_ATTRIBUTE = "type";
32    const TYPE_CREATION = "creation";
33    const TYPE_DELETION = "deletion";
34    const CANONICAL = "combo-file-system";
35
36
37    public function register(Doku_Event_Handler $controller)
38    {
39
40
41        /**
42         *
43         * And To delete sidebar (cache) cache when a page was modified in a namespace
44         * https://combostrap.com/sideslots
45         */
46        $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'createFileSystemMutation', array());
47
48        /**
49         * Synchronization with the combo file system
50         */
51        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'comboFsSynchronization', array());
52
53        /**
54         * process the Async event
55         */
56        $controller->register_hook(self::PAGE_SYSTEM_MUTATION_EVENT_NAME, 'AFTER', $this, 'handleFileSystemMutation');
57
58    }
59
60    /**
61     * @param $event
62     * @throws Exception
63     * @link https://www.dokuwiki.org/devel:event:io_wikipage_write
64     *
65     * On update to an existing page this event is called twice, once for the transfer of the old version to the attic
66     * (rev will have a value)
67     * and once to write the new version of the page into the wiki (rev is false)
68     */
69    function createFileSystemMutation($event)
70    {
71
72        $data = $event->data;
73        $pageName = $data[2];
74
75        /**
76         * Modification to the secondary slot are not processed
77         */
78        if (in_array($pageName, SlotSystem::getSlotNames())) return;
79
80
81        /**
82         * TODO ?: the common uses the  common_wikipage_save instead ?
83         *   https://www.dokuwiki.org/devel:event:common_wikipage_save
84         * File creation
85         *
86         * ```
87         * Page creation may be detected by checking if the file already exists and the revision is false.
88         * ```
89         * From https://www.dokuwiki.org/devel:event:io_wikipage_write
90         *
91         */
92        $rev = $data[3];
93        $filePath = $data[0][0];
94        $file = LocalPath::createFromPathString($filePath);
95        if (!FileSystems::exists($file) && $rev === false) {
96            Event::createEvent(
97                action_plugin_combo_pagesystemmutation::PAGE_SYSTEM_MUTATION_EVENT_NAME,
98                [
99                    self::TYPE_ATTRIBUTE => self::TYPE_CREATION,
100                    PagePath::getPersistentName() => $file->toWikiPath()->toAbsoluteId()
101                ]
102            );
103            return;
104        }
105
106        /**
107         * File deletion
108         * (No content)
109         *
110         * ```
111         * Page deletion may be detected by checking for empty page content.
112         * On update to an existing page this event is called twice, once for the transfer
113         * of the old version to the attic (rev will have a value)
114         * and once to write the new version of the page into the wiki (rev is false)
115         * ```
116         * From https://www.dokuwiki.org/devel:event:io_wikipage_write
117         */
118        $append = $data[0][2];
119        if (!$append) {
120
121            $content = $data[0][1];
122            if (empty($content) && $rev === false) {
123                // Deletion
124                Event::createEvent(
125                    action_plugin_combo_pagesystemmutation::PAGE_SYSTEM_MUTATION_EVENT_NAME,
126                    [
127                        self::TYPE_ATTRIBUTE => self::TYPE_DELETION,
128                        PagePath::getPersistentName() => $file->toWikiPath()->toAbsoluteId()
129                    ]
130                );
131            }
132        }
133
134    }
135
136    public function handleFileSystemMutation($event)
137    {
138
139        /**
140         * We need to re-render the slot
141         * that are {@link \ComboStrap\MarkupCacheDependencies::PAGE_SYSTEM_DEPENDENCY}
142         * dependent
143         */
144        $data = $event->data;
145
146        /**
147         * Re-render
148         */
149        $pathAddedOrDeleted = $data[PagePath::getPersistentName()];
150        MarkupCacheDependencies::reRenderSideSlotIfNeeded(
151            $pathAddedOrDeleted,
152            MarkupCacheDependencies::PAGE_SYSTEM_DEPENDENCY,
153            self::PAGE_SYSTEM_MUTATION_EVENT_NAME
154        );
155
156    }
157
158    /**
159     * Store into the Combo file system
160     * @param $event
161     * @return void
162     */
163    public function comboFsSynchronization($event)
164    {
165
166        $id = $event->data['id'];
167        $markup = MarkupPath::createMarkupFromId($id);
168
169        $changedType = $event->data['changeType'];
170        switch ($changedType) {
171            // creation
172            case DOKU_CHANGE_TYPE_CREATE:
173                /**
174                 * For now, we just sync the page id in the index tables (pages)
175                 *
176                 * This is mandatory to allow permanent url redirection {@link PageUrlType})
177                 */
178                if (action_plugin_combo_linkmove::isMoveOperation()) {
179                    /**
180                     * Is this a creation from a move ?
181                     */
182                    return;
183                }
184                try {
185                    PageId::createForPage($markup)
186                        ->getValue();
187                } catch (ExceptionNotFound $e) {
188                    ComboFs::createIfNotExists($markup);
189                }
190                return;
191            case DOKU_CHANGE_TYPE_DELETE:
192                /**
193                 * Is this a delete from a move ?
194                 */
195                if (action_plugin_combo_linkmove::isMoveOperation()) {
196                    return;
197                }
198                ComboFs::delete($markup);
199                return;
200        }
201
202
203    }
204
205}
206
207
208
209