1<?php
2
3use ComboStrap\DokuPath;
4use ComboStrap\ExceptionCombo;
5use ComboStrap\ExceptionComboRuntime;
6use ComboStrap\LogUtility;
7use ComboStrap\MetadataDokuWikiStore;
8use ComboStrap\MetadataFrontmatterStore;
9use ComboStrap\Page;
10use ComboStrap\Metadata;
11use ComboStrap\PageImages;
12use ComboStrap\PageImageUsage;
13use ComboStrap\PluginUtility;
14
15require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
16
17/**
18 * Handle the move of a image
19 */
20class action_plugin_combo_imgmove extends DokuWiki_Action_Plugin
21{
22    const CANONICAL = "move";
23
24    /**
25     * As explained https://www.dokuwiki.org/plugin:move
26     * @param Doku_Event_Handler $controller
27     */
28    function register(Doku_Event_Handler $controller)
29    {
30        $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'handle_move', array());
31
32
33        $controller->register_hook('PLUGIN_MOVE_MEDIA_RENAME', 'AFTER', $this, 'fileSystemStoreUpdate', array());
34    }
35
36    /**
37     * Update the metadatas
38     * @param Doku_Event $event
39     * @param $params
40     */
41    function fileSystemStoreUpdate(Doku_Event $event, $params)
42    {
43
44        $affectedPagesId = $event->data["affected_pages"];
45        $sourceImageId = $event->data["src_id"];
46        $targetImageId = $event->data["dst_id"];
47        foreach ($affectedPagesId as $affectedPageId) {
48            $affectedPage = Page::createPageFromId($affectedPageId)
49                ->setReadStore(MetadataDokuWikiStore::class);
50
51            $pageImages = PageImages::createForPage($affectedPage);
52
53            $sourceImagePath = ":$sourceImageId";
54            $row = $pageImages->getRow($sourceImagePath);
55
56            if ($row === null) {
57                // This is a move of an image in the markup
58                continue;
59            }
60            $pageImages->remove($sourceImagePath);
61            try {
62                $imageUsage = $row[PageImageUsage::getPersistentName()];
63                $imageUsageValue = null;
64                if ($imageUsage !== null) {
65                    $imageUsageValue = $imageUsage->getValue();
66                }
67                $pageImages
68                    ->addImage($targetImageId, $imageUsageValue)
69                    ->persist();
70            } catch (ExceptionCombo $e) {
71                LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
72            }
73
74
75        }
76
77    }
78
79    /**
80     * Handle the move of a image
81     * @param Doku_Event $event
82     * @param $params
83     */
84    function handle_move(Doku_Event $event, $params)
85    {
86        /**
87         * The handlers is the name of the component (ie refers to the {@link syntax_plugin_combo_media} handler)
88         * and 'move_combo_img' to the below method
89         */
90        $event->data['handlers'][syntax_plugin_combo_media::COMPONENT] = array($this, 'move_combo_img');
91        $event->data['handlers'][syntax_plugin_combo_frontmatter::COMPONENT] = array($this, 'move_combo_frontmatter_img');
92
93    }
94
95    /**
96     *
97     * @param $match
98     * @param $state
99     * @param $pos
100     * @param $plugin
101     * @param helper_plugin_move_handler $handler
102     */
103    public function move_combo_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler)
104    {
105        /**
106         * The original move method
107         * is {@link helper_plugin_move_handler::media()}
108         * Rewrite the media links match
109         * from {@link syntax_plugin_combo_media}
110         */
111        $handler->media($match, $state, $pos);
112
113    }
114
115    /**
116     *
117     * @param $match
118     * @param $state
119     * @param $pos
120     * @param $plugin
121     * @param helper_plugin_move_handler $handler
122     * @return string
123     */
124    public function move_combo_frontmatter_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler)
125    {
126        /**
127         * The original move method
128         * is {@link helper_plugin_move_handler::media()}
129         */
130        $page = Page::createPageFromId("move-fake-id");
131        try {
132            $metadataFrontmatterStore = MetadataFrontmatterStore::createFromFrontmatterString($page, $match);
133        } catch (ExceptionCombo $e) {
134            LogUtility::msg("The frontmatter could not be loaded. " . $e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
135            return $match;
136        }
137        $pageImagesObject = PageImages::createForPage($page)
138            ->setReadStore($metadataFrontmatterStore);
139        $images = $pageImagesObject->getValueAsPageImages();
140        if ($images === null) {
141            return $match;
142        }
143
144        try {
145
146            foreach ($images as $image) {
147                $path = $image->getImage()->getPath();
148                if (!($path instanceof DokuPath)) {
149                    continue;
150                }
151                $imageId = $path->toAbsolutePath()->toString();
152                $before = $imageId;
153                $this->moveImage($imageId, $handler);
154                if ($before != $imageId) {
155                    $pageImagesObject->remove($before);
156                    $pageImagesObject->addImage($imageId, $image->getUsages());
157                }
158            }
159
160            $pageImagesObject->sendToWriteStore();
161
162        } catch (ExceptionCombo $e) {
163            // Could not resolve the image, image does not exist, ... return the data without modification
164            if (PluginUtility::isDevOrTest()) {
165                throw new ExceptionComboRuntime($e->getMessage(), $e->getCanonical(), 0, $e);
166            } else {
167                LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
168            }
169            return $match;
170        }
171
172        /**
173         * All good,
174         * We don't modify the file system metadata for the page
175         * because the handler does not give it unfortunately
176         */
177        return $metadataFrontmatterStore->toFrontmatterString();
178
179    }
180
181    /**
182     * Move a single image and update the JSon
183     * @param $relativeOrAbsoluteWikiId
184     * @param helper_plugin_move_handler $handler
185     * @throws ExceptionCombo on bad argument
186     */
187    private function moveImage(&$relativeOrAbsoluteWikiId, helper_plugin_move_handler $handler)
188    {
189        try {
190            $newId = $handler->resolveMoves($relativeOrAbsoluteWikiId, "media");
191            $relativeOrAbsoluteWikiId = DokuPath::IdToAbsolutePath($newId);
192        } catch (Exception $e) {
193            throw new ExceptionCombo("A move error has occurred while trying to move the image ($relativeOrAbsoluteWikiId). The target resolution function send the following error message: " . $e->getMessage(), self::CANONICAL);
194        }
195    }
196
197
198}
199