xref: /template/strap/action/imgmove.php (revision 70bbd7f1f72440223cc13f3495efdcb2b0a11514)
121913ab3SNickeau<?php
221913ab3SNickeau
304fd306cSNickeauuse ComboStrap\ExceptionBadArgument;
404fd306cSNickeauuse ComboStrap\ExceptionCompile;
504fd306cSNickeauuse ComboStrap\ExceptionNotFound;
604fd306cSNickeauuse ComboStrap\ExceptionRuntime;
704fd306cSNickeauuse ComboStrap\ExecutionContext;
837748cd8SNickeauuse ComboStrap\LogUtility;
904fd306cSNickeauuse ComboStrap\MarkupPath;
1004fd306cSNickeauuse ComboStrap\Meta\Api\MetadataImage;
1104fd306cSNickeauuse ComboStrap\Meta\Api\MetadataSystem;
1204fd306cSNickeauuse ComboStrap\Meta\Field\PageImages;
1304fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore;
14c3437056SNickeauuse ComboStrap\MetadataFrontmatterStore;
15c3437056SNickeauuse ComboStrap\PageImageUsage;
1621913ab3SNickeauuse ComboStrap\PluginUtility;
1704fd306cSNickeauuse ComboStrap\WikiPath;
1821913ab3SNickeau
1904fd306cSNickeaurequire_once(__DIR__ . '/../vendor/autoload.php');
2021913ab3SNickeau
2121913ab3SNickeau/**
2221913ab3SNickeau * Handle the move of a image
2321913ab3SNickeau */
2421913ab3SNickeauclass action_plugin_combo_imgmove extends DokuWiki_Action_Plugin
2521913ab3SNickeau{
2604fd306cSNickeau    const CANONICAL = "imgmove";
2721913ab3SNickeau
2821913ab3SNickeau    /**
2921913ab3SNickeau     * As explained https://www.dokuwiki.org/plugin:move
3021913ab3SNickeau     * @param Doku_Event_Handler $controller
3121913ab3SNickeau     */
3221913ab3SNickeau    function register(Doku_Event_Handler $controller)
3321913ab3SNickeau    {
3421913ab3SNickeau        $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'handle_move', array());
35c3437056SNickeau
36c3437056SNickeau
37c3437056SNickeau        $controller->register_hook('PLUGIN_MOVE_MEDIA_RENAME', 'AFTER', $this, 'fileSystemStoreUpdate', array());
38c3437056SNickeau    }
39c3437056SNickeau
40c3437056SNickeau    /**
41c3437056SNickeau     * Update the metadatas
42c3437056SNickeau     * @param Doku_Event $event
43c3437056SNickeau     * @param $params
44c3437056SNickeau     */
45c3437056SNickeau    function fileSystemStoreUpdate(Doku_Event $event, $params)
46c3437056SNickeau    {
47c3437056SNickeau
4804fd306cSNickeau
49c3437056SNickeau        $affectedPagesId = $event->data["affected_pages"];
50c3437056SNickeau        $sourceImageId = $event->data["src_id"];
51c3437056SNickeau        $targetImageId = $event->data["dst_id"];
5204fd306cSNickeau
5304fd306cSNickeau        /**
5404fd306cSNickeau         * Advertise the move
5504fd306cSNickeau         */
5604fd306cSNickeau        ExecutionContext::getActualOrCreateFromEnv()
5704fd306cSNickeau            ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $sourceImageId);
5804fd306cSNickeau        try {
59c3437056SNickeau            foreach ($affectedPagesId as $affectedPageId) {
6004fd306cSNickeau                $affectedPage = MarkupPath::createMarkupFromId($affectedPageId)
61c3437056SNickeau                    ->setReadStore(MetadataDokuWikiStore::class);
62c3437056SNickeau
6304fd306cSNickeau                foreach (MetadataImage::PERSISTENT_IMAGE_NAMES as $persistentImage) {
6404fd306cSNickeau                    try {
6504fd306cSNickeau                        $metadata = MetadataSystem::getForName($persistentImage)
6604fd306cSNickeau                            ->setResource($affectedPage)
6704fd306cSNickeau                            ->setReadStore(MetadataDokuWikiStore::class);
6804fd306cSNickeau                    } catch (ExceptionNotFound $e) {
6904fd306cSNickeau                        LogUtility::internalError("Hardcoded should exists");
7004fd306cSNickeau                        continue;
7104fd306cSNickeau                    }
7204fd306cSNickeau                    try {
7304fd306cSNickeau                        $value = $metadata->getValue();
7404fd306cSNickeau                    } catch (ExceptionNotFound $e) {
7504fd306cSNickeau                        // no value
7604fd306cSNickeau                        continue;
7704fd306cSNickeau                    }
7804fd306cSNickeau                    if ($value === $sourceImageId) {
7904fd306cSNickeau                        try {
8004fd306cSNickeau                            $metadata
8104fd306cSNickeau                                ->setValue($targetImageId)
8204fd306cSNickeau                                ->persist();
8304fd306cSNickeau                        } catch (ExceptionBadArgument $e) {
8404fd306cSNickeau                            LogUtility::error("The target path image ($targetImageId) is not a path", self::CANONICAL, $e);
8504fd306cSNickeau                        }
8604fd306cSNickeau                    }
8704fd306cSNickeau                }
88c3437056SNickeau
8904fd306cSNickeau
9004fd306cSNickeau                /**
9104fd306cSNickeau                 * Deprecated but yeah
9204fd306cSNickeau                 */
9304fd306cSNickeau                $pageImages = PageImages::createForPage($affectedPage);
94c3437056SNickeau                $sourceImagePath = ":$sourceImageId";
95c3437056SNickeau                $row = $pageImages->getRow($sourceImagePath);
96c3437056SNickeau                if ($row === null) {
97c3437056SNickeau                    // This is a move of an image in the markup
98c3437056SNickeau                    continue;
99c3437056SNickeau                }
10004fd306cSNickeau                $souceImageWikiPath = WikiPath::createMediaPathFromId($sourceImagePath);
10104fd306cSNickeau                $pageImages->remove($souceImageWikiPath);
102c3437056SNickeau                try {
103*70bbd7f1Sgerardnico                    $imageUsage = $row[PageImageUsage::getPersistentName()] ?? null;
104c3437056SNickeau                    $imageUsageValue = null;
105c3437056SNickeau                    if ($imageUsage !== null) {
106c3437056SNickeau                        $imageUsageValue = $imageUsage->getValue();
107c3437056SNickeau                    }
108c3437056SNickeau                    $pageImages
109c3437056SNickeau                        ->addImage($targetImageId, $imageUsageValue)
110c3437056SNickeau                        ->persist();
11104fd306cSNickeau                } catch (ExceptionCompile $e) {
11204fd306cSNickeau                    LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical(), $e);
113c3437056SNickeau                }
114c3437056SNickeau
11504fd306cSNickeau            }
11604fd306cSNickeau        } finally {
11704fd306cSNickeau            /**
11804fd306cSNickeau             * Stop advertising the move
11904fd306cSNickeau             */
12004fd306cSNickeau            ExecutionContext::getActualOrCreateFromEnv()
12104fd306cSNickeau                ->closeAndRemoveRuntimeVariableIfExists(action_plugin_combo_linkmove::FILE_MOVE_OPERATION);
122c3437056SNickeau        }
123c3437056SNickeau
12421913ab3SNickeau    }
12521913ab3SNickeau
12621913ab3SNickeau    /**
12721913ab3SNickeau     * Handle the move of a image
12821913ab3SNickeau     * @param Doku_Event $event
12921913ab3SNickeau     * @param $params
13021913ab3SNickeau     */
13121913ab3SNickeau    function handle_move(Doku_Event $event, $params)
13221913ab3SNickeau    {
13321913ab3SNickeau        /**
13421913ab3SNickeau         * The handlers is the name of the component (ie refers to the {@link syntax_plugin_combo_media} handler)
13521913ab3SNickeau         * and 'move_combo_img' to the below method
13621913ab3SNickeau         */
13721913ab3SNickeau        $event->data['handlers'][syntax_plugin_combo_media::COMPONENT] = array($this, 'move_combo_img');
13837748cd8SNickeau        $event->data['handlers'][syntax_plugin_combo_frontmatter::COMPONENT] = array($this, 'move_combo_frontmatter_img');
139c3437056SNickeau
14021913ab3SNickeau    }
14121913ab3SNickeau
14221913ab3SNickeau    /**
14321913ab3SNickeau     *
14421913ab3SNickeau     * @param $match
14521913ab3SNickeau     * @param $state
14621913ab3SNickeau     * @param $pos
14721913ab3SNickeau     * @param $plugin
14821913ab3SNickeau     * @param helper_plugin_move_handler $handler
14921913ab3SNickeau     */
15021913ab3SNickeau    public function move_combo_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler)
15121913ab3SNickeau    {
15221913ab3SNickeau        /**
15321913ab3SNickeau         * The original move method
15421913ab3SNickeau         * is {@link helper_plugin_move_handler::media()}
155c3437056SNickeau         * Rewrite the media links match
156c3437056SNickeau         * from {@link syntax_plugin_combo_media}
15721913ab3SNickeau         */
15821913ab3SNickeau        $handler->media($match, $state, $pos);
15921913ab3SNickeau
16021913ab3SNickeau    }
16121913ab3SNickeau
16237748cd8SNickeau    /**
16337748cd8SNickeau     *
16437748cd8SNickeau     * @param $match
16537748cd8SNickeau     * @param $state
16637748cd8SNickeau     * @param $pos
16737748cd8SNickeau     * @param $plugin
16837748cd8SNickeau     * @param helper_plugin_move_handler $handler
16937748cd8SNickeau     * @return string
17037748cd8SNickeau     */
17137748cd8SNickeau    public function move_combo_frontmatter_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler)
17237748cd8SNickeau    {
17337748cd8SNickeau        /**
17437748cd8SNickeau         * The original move method
17537748cd8SNickeau         * is {@link helper_plugin_move_handler::media()}
17637748cd8SNickeau         */
17704fd306cSNickeau        $page = MarkupPath::createMarkupFromId("move-fake-id");
178c3437056SNickeau        try {
179c3437056SNickeau            $metadataFrontmatterStore = MetadataFrontmatterStore::createFromFrontmatterString($page, $match);
18004fd306cSNickeau        } catch (ExceptionCompile $e) {
181c3437056SNickeau            LogUtility::msg("The frontmatter could not be loaded. " . $e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
18237748cd8SNickeau            return $match;
183c3437056SNickeau        }
18404fd306cSNickeau        $data = $metadataFrontmatterStore->getData();
18504fd306cSNickeau
18604fd306cSNickeau        /**
18704fd306cSNickeau         * Advertise the move
18804fd306cSNickeau         */
18904fd306cSNickeau        $moveOpeation = true;
19004fd306cSNickeau        ExecutionContext::getActualOrCreateFromEnv()
19104fd306cSNickeau            ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $moveOpeation);
19204fd306cSNickeau        try {
19304fd306cSNickeau            foreach ($data as $key => $value) {
19404fd306cSNickeau
19504fd306cSNickeau                try {
19604fd306cSNickeau                    $metadata = MetadataSystem::getForName($key)
19704fd306cSNickeau                        ->setResource($page)
19804fd306cSNickeau                        ->setReadStore($metadataFrontmatterStore)
19904fd306cSNickeau                        ->setWriteStore($metadataFrontmatterStore);
20004fd306cSNickeau                } catch (ExceptionNotFound $e) {
20104fd306cSNickeau                    continue;
20237748cd8SNickeau                }
20337748cd8SNickeau
20404fd306cSNickeau                /**
20504fd306cSNickeau                 * Old deprecated
20604fd306cSNickeau                 */
20704fd306cSNickeau                if ($metadata instanceof PageImages) {
20804fd306cSNickeau                    $pageImagesObject = $metadata;
20904fd306cSNickeau                    $images = $metadata->getValueAsPageImages();
21004fd306cSNickeau                    if (empty($images)) {
21104fd306cSNickeau                        return $match;
21204fd306cSNickeau                    }
21337748cd8SNickeau                    try {
214c3437056SNickeau
215c3437056SNickeau                        foreach ($images as $image) {
21604fd306cSNickeau                            $path = $image->getImagePath();
21704fd306cSNickeau                            $imageId = $path->toAbsolutePath()->toAbsoluteId();
218c3437056SNickeau                            $before = $imageId;
219c3437056SNickeau                            $this->moveImage($imageId, $handler);
22004fd306cSNickeau                            if ($before !== $imageId) {
22104fd306cSNickeau                                $pageImagesObject->remove($path);
222c3437056SNickeau                                $pageImagesObject->addImage($imageId, $image->getUsages());
22337748cd8SNickeau                            }
22437748cd8SNickeau                        }
22537748cd8SNickeau
226c3437056SNickeau                        $pageImagesObject->sendToWriteStore();
227c3437056SNickeau
22804fd306cSNickeau                    } catch (ExceptionCompile $e) {
229c3437056SNickeau                        // Could not resolve the image, image does not exist, ... return the data without modification
230c3437056SNickeau                        if (PluginUtility::isDevOrTest()) {
23104fd306cSNickeau                            throw new ExceptionRuntime($e->getMessage(), $e->getCanonical(), 0, $e);
232c3437056SNickeau                        } else {
233c3437056SNickeau                            LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
234c3437056SNickeau                        }
23504fd306cSNickeau                        continue;
23637748cd8SNickeau                    }
23704fd306cSNickeau                }
23804fd306cSNickeau                if (!($metadata instanceof MetadataImage)) {
23904fd306cSNickeau                    continue;
24004fd306cSNickeau                }
24104fd306cSNickeau                try {
24204fd306cSNickeau                    $imageId = $metadata->getValue()->toAbsoluteId();
24304fd306cSNickeau                } catch (ExceptionNotFound $e) {
24404fd306cSNickeau                    continue;
24504fd306cSNickeau                }
24604fd306cSNickeau                $before = $imageId;
24704fd306cSNickeau                try {
24804fd306cSNickeau                    $this->moveImage($imageId, $handler);
24904fd306cSNickeau                    if ($before !== $imageId) {
25004fd306cSNickeau                        $metadata->setValue($imageId)->persist();
25104fd306cSNickeau                    }
25204fd306cSNickeau                } catch (\Exception $e) {
25304fd306cSNickeau                    if (PluginUtility::isDevOrTest()) {
25404fd306cSNickeau                        throw new ExceptionRuntime($e->getMessage(), self::CANONICAL, 0, $e);
25504fd306cSNickeau                    } else {
25604fd306cSNickeau                        LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, self::CANONICAL, $e);
25704fd306cSNickeau                    }
25804fd306cSNickeau                    continue;
25904fd306cSNickeau                }
26004fd306cSNickeau            }
26104fd306cSNickeau        } finally {
26204fd306cSNickeau            /**
26304fd306cSNickeau             * Close the move
26404fd306cSNickeau             */
26504fd306cSNickeau            ExecutionContext::getActualOrCreateFromEnv()
26604fd306cSNickeau                ->closeAndRemoveRuntimeVariableIfExists(action_plugin_combo_linkmove::FILE_MOVE_OPERATION);
26704fd306cSNickeau        }
26804fd306cSNickeau
26937748cd8SNickeau
27037748cd8SNickeau        /**
27137748cd8SNickeau         * All good,
272c3437056SNickeau         * We don't modify the file system metadata for the page
27337748cd8SNickeau         * because the handler does not give it unfortunately
27437748cd8SNickeau         */
275c3437056SNickeau        return $metadataFrontmatterStore->toFrontmatterString();
27637748cd8SNickeau
27737748cd8SNickeau    }
27837748cd8SNickeau
27937748cd8SNickeau    /**
28037748cd8SNickeau     * Move a single image and update the JSon
281c3437056SNickeau     * @param $relativeOrAbsoluteWikiId
28237748cd8SNickeau     * @param helper_plugin_move_handler $handler
28304fd306cSNickeau     * @throws ExceptionCompile on bad argument
28437748cd8SNickeau     */
285c3437056SNickeau    private function moveImage(&$relativeOrAbsoluteWikiId, helper_plugin_move_handler $handler)
28637748cd8SNickeau    {
28737748cd8SNickeau        try {
288c3437056SNickeau            $newId = $handler->resolveMoves($relativeOrAbsoluteWikiId, "media");
28904fd306cSNickeau            $relativeOrAbsoluteWikiId = WikiPath::IdToAbsolutePath($newId);
29037748cd8SNickeau        } catch (Exception $e) {
29104fd306cSNickeau            throw new ExceptionCompile("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);
29237748cd8SNickeau        }
29337748cd8SNickeau    }
29437748cd8SNickeau
29521913ab3SNickeau
29621913ab3SNickeau}
297