121913ab3SNickeau<?php 221913ab3SNickeau 3*04fd306cSNickeauuse ComboStrap\ExceptionBadArgument; 4*04fd306cSNickeauuse ComboStrap\ExceptionCompile; 5*04fd306cSNickeauuse ComboStrap\ExceptionNotFound; 6*04fd306cSNickeauuse ComboStrap\ExceptionRuntime; 7*04fd306cSNickeauuse ComboStrap\ExecutionContext; 837748cd8SNickeauuse ComboStrap\LogUtility; 9*04fd306cSNickeauuse ComboStrap\MarkupPath; 10*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataImage; 11*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataSystem; 12*04fd306cSNickeauuse ComboStrap\Meta\Field\PageImages; 13*04fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore; 14c3437056SNickeauuse ComboStrap\MetadataFrontmatterStore; 15c3437056SNickeauuse ComboStrap\PageImageUsage; 1621913ab3SNickeauuse ComboStrap\PluginUtility; 17*04fd306cSNickeauuse ComboStrap\WikiPath; 1821913ab3SNickeau 19*04fd306cSNickeaurequire_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{ 26*04fd306cSNickeau 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 48*04fd306cSNickeau 49c3437056SNickeau $affectedPagesId = $event->data["affected_pages"]; 50c3437056SNickeau $sourceImageId = $event->data["src_id"]; 51c3437056SNickeau $targetImageId = $event->data["dst_id"]; 52*04fd306cSNickeau 53*04fd306cSNickeau /** 54*04fd306cSNickeau * Advertise the move 55*04fd306cSNickeau */ 56*04fd306cSNickeau ExecutionContext::getActualOrCreateFromEnv() 57*04fd306cSNickeau ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $sourceImageId); 58*04fd306cSNickeau try { 59c3437056SNickeau foreach ($affectedPagesId as $affectedPageId) { 60*04fd306cSNickeau $affectedPage = MarkupPath::createMarkupFromId($affectedPageId) 61c3437056SNickeau ->setReadStore(MetadataDokuWikiStore::class); 62c3437056SNickeau 63*04fd306cSNickeau foreach (MetadataImage::PERSISTENT_IMAGE_NAMES as $persistentImage) { 64*04fd306cSNickeau try { 65*04fd306cSNickeau $metadata = MetadataSystem::getForName($persistentImage) 66*04fd306cSNickeau ->setResource($affectedPage) 67*04fd306cSNickeau ->setReadStore(MetadataDokuWikiStore::class); 68*04fd306cSNickeau } catch (ExceptionNotFound $e) { 69*04fd306cSNickeau LogUtility::internalError("Hardcoded should exists"); 70*04fd306cSNickeau continue; 71*04fd306cSNickeau } 72*04fd306cSNickeau try { 73*04fd306cSNickeau $value = $metadata->getValue(); 74*04fd306cSNickeau } catch (ExceptionNotFound $e) { 75*04fd306cSNickeau // no value 76*04fd306cSNickeau continue; 77*04fd306cSNickeau } 78*04fd306cSNickeau if ($value === $sourceImageId) { 79*04fd306cSNickeau try { 80*04fd306cSNickeau $metadata 81*04fd306cSNickeau ->setValue($targetImageId) 82*04fd306cSNickeau ->persist(); 83*04fd306cSNickeau } catch (ExceptionBadArgument $e) { 84*04fd306cSNickeau LogUtility::error("The target path image ($targetImageId) is not a path", self::CANONICAL, $e); 85*04fd306cSNickeau } 86*04fd306cSNickeau } 87*04fd306cSNickeau } 88c3437056SNickeau 89*04fd306cSNickeau 90*04fd306cSNickeau /** 91*04fd306cSNickeau * Deprecated but yeah 92*04fd306cSNickeau */ 93*04fd306cSNickeau $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 } 100*04fd306cSNickeau $souceImageWikiPath = WikiPath::createMediaPathFromId($sourceImagePath); 101*04fd306cSNickeau $pageImages->remove($souceImageWikiPath); 102c3437056SNickeau try { 103c3437056SNickeau $imageUsage = $row[PageImageUsage::getPersistentName()]; 104c3437056SNickeau $imageUsageValue = null; 105c3437056SNickeau if ($imageUsage !== null) { 106c3437056SNickeau $imageUsageValue = $imageUsage->getValue(); 107c3437056SNickeau } 108c3437056SNickeau $pageImages 109c3437056SNickeau ->addImage($targetImageId, $imageUsageValue) 110c3437056SNickeau ->persist(); 111*04fd306cSNickeau } catch (ExceptionCompile $e) { 112*04fd306cSNickeau LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical(), $e); 113c3437056SNickeau } 114c3437056SNickeau 115*04fd306cSNickeau } 116*04fd306cSNickeau } finally { 117*04fd306cSNickeau /** 118*04fd306cSNickeau * Stop advertising the move 119*04fd306cSNickeau */ 120*04fd306cSNickeau ExecutionContext::getActualOrCreateFromEnv() 121*04fd306cSNickeau ->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 */ 177*04fd306cSNickeau $page = MarkupPath::createMarkupFromId("move-fake-id"); 178c3437056SNickeau try { 179c3437056SNickeau $metadataFrontmatterStore = MetadataFrontmatterStore::createFromFrontmatterString($page, $match); 180*04fd306cSNickeau } catch (ExceptionCompile $e) { 181c3437056SNickeau LogUtility::msg("The frontmatter could not be loaded. " . $e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical()); 18237748cd8SNickeau return $match; 183c3437056SNickeau } 184*04fd306cSNickeau $data = $metadataFrontmatterStore->getData(); 185*04fd306cSNickeau 186*04fd306cSNickeau /** 187*04fd306cSNickeau * Advertise the move 188*04fd306cSNickeau */ 189*04fd306cSNickeau $moveOpeation = true; 190*04fd306cSNickeau ExecutionContext::getActualOrCreateFromEnv() 191*04fd306cSNickeau ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $moveOpeation); 192*04fd306cSNickeau try { 193*04fd306cSNickeau foreach ($data as $key => $value) { 194*04fd306cSNickeau 195*04fd306cSNickeau try { 196*04fd306cSNickeau $metadata = MetadataSystem::getForName($key) 197*04fd306cSNickeau ->setResource($page) 198*04fd306cSNickeau ->setReadStore($metadataFrontmatterStore) 199*04fd306cSNickeau ->setWriteStore($metadataFrontmatterStore); 200*04fd306cSNickeau } catch (ExceptionNotFound $e) { 201*04fd306cSNickeau continue; 20237748cd8SNickeau } 20337748cd8SNickeau 204*04fd306cSNickeau /** 205*04fd306cSNickeau * Old deprecated 206*04fd306cSNickeau */ 207*04fd306cSNickeau if ($metadata instanceof PageImages) { 208*04fd306cSNickeau $pageImagesObject = $metadata; 209*04fd306cSNickeau $images = $metadata->getValueAsPageImages(); 210*04fd306cSNickeau if (empty($images)) { 211*04fd306cSNickeau return $match; 212*04fd306cSNickeau } 21337748cd8SNickeau try { 214c3437056SNickeau 215c3437056SNickeau foreach ($images as $image) { 216*04fd306cSNickeau $path = $image->getImagePath(); 217*04fd306cSNickeau $imageId = $path->toAbsolutePath()->toAbsoluteId(); 218c3437056SNickeau $before = $imageId; 219c3437056SNickeau $this->moveImage($imageId, $handler); 220*04fd306cSNickeau if ($before !== $imageId) { 221*04fd306cSNickeau $pageImagesObject->remove($path); 222c3437056SNickeau $pageImagesObject->addImage($imageId, $image->getUsages()); 22337748cd8SNickeau } 22437748cd8SNickeau } 22537748cd8SNickeau 226c3437056SNickeau $pageImagesObject->sendToWriteStore(); 227c3437056SNickeau 228*04fd306cSNickeau } catch (ExceptionCompile $e) { 229c3437056SNickeau // Could not resolve the image, image does not exist, ... return the data without modification 230c3437056SNickeau if (PluginUtility::isDevOrTest()) { 231*04fd306cSNickeau throw new ExceptionRuntime($e->getMessage(), $e->getCanonical(), 0, $e); 232c3437056SNickeau } else { 233c3437056SNickeau LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical()); 234c3437056SNickeau } 235*04fd306cSNickeau continue; 23637748cd8SNickeau } 237*04fd306cSNickeau } 238*04fd306cSNickeau if (!($metadata instanceof MetadataImage)) { 239*04fd306cSNickeau continue; 240*04fd306cSNickeau } 241*04fd306cSNickeau try { 242*04fd306cSNickeau $imageId = $metadata->getValue()->toAbsoluteId(); 243*04fd306cSNickeau } catch (ExceptionNotFound $e) { 244*04fd306cSNickeau continue; 245*04fd306cSNickeau } 246*04fd306cSNickeau $before = $imageId; 247*04fd306cSNickeau try { 248*04fd306cSNickeau $this->moveImage($imageId, $handler); 249*04fd306cSNickeau if ($before !== $imageId) { 250*04fd306cSNickeau $metadata->setValue($imageId)->persist(); 251*04fd306cSNickeau } 252*04fd306cSNickeau } catch (\Exception $e) { 253*04fd306cSNickeau if (PluginUtility::isDevOrTest()) { 254*04fd306cSNickeau throw new ExceptionRuntime($e->getMessage(), self::CANONICAL, 0, $e); 255*04fd306cSNickeau } else { 256*04fd306cSNickeau LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, self::CANONICAL, $e); 257*04fd306cSNickeau } 258*04fd306cSNickeau continue; 259*04fd306cSNickeau } 260*04fd306cSNickeau } 261*04fd306cSNickeau } finally { 262*04fd306cSNickeau /** 263*04fd306cSNickeau * Close the move 264*04fd306cSNickeau */ 265*04fd306cSNickeau ExecutionContext::getActualOrCreateFromEnv() 266*04fd306cSNickeau ->closeAndRemoveRuntimeVariableIfExists(action_plugin_combo_linkmove::FILE_MOVE_OPERATION); 267*04fd306cSNickeau } 268*04fd306cSNickeau 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 283*04fd306cSNickeau * @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"); 289*04fd306cSNickeau $relativeOrAbsoluteWikiId = WikiPath::IdToAbsolutePath($newId); 29037748cd8SNickeau } catch (Exception $e) { 291*04fd306cSNickeau 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