1<?php 2 3use ComboStrap\ExceptionBadArgument; 4use ComboStrap\ExceptionCompile; 5use ComboStrap\ExceptionNotFound; 6use ComboStrap\ExceptionRuntime; 7use ComboStrap\ExecutionContext; 8use ComboStrap\LogUtility; 9use ComboStrap\MarkupPath; 10use ComboStrap\Meta\Api\MetadataImage; 11use ComboStrap\Meta\Api\MetadataSystem; 12use ComboStrap\Meta\Field\PageImages; 13use ComboStrap\Meta\Store\MetadataDokuWikiStore; 14use ComboStrap\MetadataFrontmatterStore; 15use ComboStrap\PageImageUsage; 16use ComboStrap\PluginUtility; 17use ComboStrap\WikiPath; 18 19require_once(__DIR__ . '/../vendor/autoload.php'); 20 21/** 22 * Handle the move of a image 23 */ 24class action_plugin_combo_imgmove extends DokuWiki_Action_Plugin 25{ 26 const CANONICAL = "imgmove"; 27 28 /** 29 * As explained https://www.dokuwiki.org/plugin:move 30 * @param Doku_Event_Handler $controller 31 */ 32 function register(Doku_Event_Handler $controller) 33 { 34 $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'handle_move', array()); 35 36 37 $controller->register_hook('PLUGIN_MOVE_MEDIA_RENAME', 'AFTER', $this, 'fileSystemStoreUpdate', array()); 38 } 39 40 /** 41 * Update the metadatas 42 * @param Doku_Event $event 43 * @param $params 44 */ 45 function fileSystemStoreUpdate(Doku_Event $event, $params) 46 { 47 48 49 $affectedPagesId = $event->data["affected_pages"]; 50 $sourceImageId = $event->data["src_id"]; 51 $targetImageId = $event->data["dst_id"]; 52 53 /** 54 * Advertise the move 55 */ 56 ExecutionContext::getActualOrCreateFromEnv() 57 ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $sourceImageId); 58 try { 59 foreach ($affectedPagesId as $affectedPageId) { 60 $affectedPage = MarkupPath::createMarkupFromId($affectedPageId) 61 ->setReadStore(MetadataDokuWikiStore::class); 62 63 foreach (MetadataImage::PERSISTENT_IMAGE_NAMES as $persistentImage) { 64 try { 65 $metadata = MetadataSystem::getForName($persistentImage) 66 ->setResource($affectedPage) 67 ->setReadStore(MetadataDokuWikiStore::class); 68 } catch (ExceptionNotFound $e) { 69 LogUtility::internalError("Hardcoded should exists"); 70 continue; 71 } 72 try { 73 $value = $metadata->getValue(); 74 } catch (ExceptionNotFound $e) { 75 // no value 76 continue; 77 } 78 if ($value === $sourceImageId) { 79 try { 80 $metadata 81 ->setValue($targetImageId) 82 ->persist(); 83 } catch (ExceptionBadArgument $e) { 84 LogUtility::error("The target path image ($targetImageId) is not a path", self::CANONICAL, $e); 85 } 86 } 87 } 88 89 90 /** 91 * Deprecated but yeah 92 */ 93 $pageImages = PageImages::createForPage($affectedPage); 94 $sourceImagePath = ":$sourceImageId"; 95 $row = $pageImages->getRow($sourceImagePath); 96 if ($row === null) { 97 // This is a move of an image in the markup 98 continue; 99 } 100 $souceImageWikiPath = WikiPath::createMediaPathFromId($sourceImagePath); 101 $pageImages->remove($souceImageWikiPath); 102 try { 103 $imageUsage = $row[PageImageUsage::getPersistentName()] ?? null; 104 $imageUsageValue = null; 105 if ($imageUsage !== null) { 106 $imageUsageValue = $imageUsage->getValue(); 107 } 108 $pageImages 109 ->addImage($targetImageId, $imageUsageValue) 110 ->persist(); 111 } catch (ExceptionCompile $e) { 112 LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical(), $e); 113 } 114 115 } 116 } finally { 117 /** 118 * Stop advertising the move 119 */ 120 ExecutionContext::getActualOrCreateFromEnv() 121 ->closeAndRemoveRuntimeVariableIfExists(action_plugin_combo_linkmove::FILE_MOVE_OPERATION); 122 } 123 124 } 125 126 /** 127 * Handle the move of a image 128 * @param Doku_Event $event 129 * @param $params 130 */ 131 function handle_move(Doku_Event $event, $params) 132 { 133 /** 134 * The handlers is the name of the component (ie refers to the {@link syntax_plugin_combo_media} handler) 135 * and 'move_combo_img' to the below method 136 */ 137 $event->data['handlers'][syntax_plugin_combo_media::COMPONENT] = array($this, 'move_combo_img'); 138 $event->data['handlers'][syntax_plugin_combo_frontmatter::COMPONENT] = array($this, 'move_combo_frontmatter_img'); 139 140 } 141 142 /** 143 * 144 * @param $match 145 * @param $state 146 * @param $pos 147 * @param $plugin 148 * @param helper_plugin_move_handler $handler 149 */ 150 public function move_combo_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler) 151 { 152 /** 153 * The original move method 154 * is {@link helper_plugin_move_handler::media()} 155 * Rewrite the media links match 156 * from {@link syntax_plugin_combo_media} 157 */ 158 $handler->media($match, $state, $pos); 159 160 } 161 162 /** 163 * 164 * @param $match 165 * @param $state 166 * @param $pos 167 * @param $plugin 168 * @param helper_plugin_move_handler $handler 169 * @return string 170 */ 171 public function move_combo_frontmatter_img($match, $state, $pos, $plugin, helper_plugin_move_handler $handler) 172 { 173 /** 174 * The original move method 175 * is {@link helper_plugin_move_handler::media()} 176 */ 177 $page = MarkupPath::createMarkupFromId("move-fake-id"); 178 try { 179 $metadataFrontmatterStore = MetadataFrontmatterStore::createFromFrontmatterString($page, $match); 180 } catch (ExceptionCompile $e) { 181 LogUtility::msg("The frontmatter could not be loaded. " . $e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical()); 182 return $match; 183 } 184 $data = $metadataFrontmatterStore->getData(); 185 186 /** 187 * Advertise the move 188 */ 189 $moveOpeation = true; 190 ExecutionContext::getActualOrCreateFromEnv() 191 ->setRuntimeObject(action_plugin_combo_linkmove::FILE_MOVE_OPERATION, $moveOpeation); 192 try { 193 foreach ($data as $key => $value) { 194 195 try { 196 $metadata = MetadataSystem::getForName($key) 197 ->setResource($page) 198 ->setReadStore($metadataFrontmatterStore) 199 ->setWriteStore($metadataFrontmatterStore); 200 } catch (ExceptionNotFound $e) { 201 continue; 202 } 203 204 /** 205 * Old deprecated 206 */ 207 if ($metadata instanceof PageImages) { 208 $pageImagesObject = $metadata; 209 $images = $metadata->getValueAsPageImages(); 210 if (empty($images)) { 211 return $match; 212 } 213 try { 214 215 foreach ($images as $image) { 216 $path = $image->getImagePath(); 217 $imageId = $path->toAbsolutePath()->toAbsoluteId(); 218 $before = $imageId; 219 $this->moveImage($imageId, $handler); 220 if ($before !== $imageId) { 221 $pageImagesObject->remove($path); 222 $pageImagesObject->addImage($imageId, $image->getUsages()); 223 } 224 } 225 226 $pageImagesObject->sendToWriteStore(); 227 228 } catch (ExceptionCompile $e) { 229 // Could not resolve the image, image does not exist, ... return the data without modification 230 if (PluginUtility::isDevOrTest()) { 231 throw new ExceptionRuntime($e->getMessage(), $e->getCanonical(), 0, $e); 232 } else { 233 LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical()); 234 } 235 continue; 236 } 237 } 238 if (!($metadata instanceof MetadataImage)) { 239 continue; 240 } 241 try { 242 $imageId = $metadata->getValue()->toAbsoluteId(); 243 } catch (ExceptionNotFound $e) { 244 continue; 245 } 246 $before = $imageId; 247 try { 248 $this->moveImage($imageId, $handler); 249 if ($before !== $imageId) { 250 $metadata->setValue($imageId)->persist(); 251 } 252 } catch (\Exception $e) { 253 if (PluginUtility::isDevOrTest()) { 254 throw new ExceptionRuntime($e->getMessage(), self::CANONICAL, 0, $e); 255 } else { 256 LogUtility::log2file($e->getMessage(), LogUtility::LVL_MSG_ERROR, self::CANONICAL, $e); 257 } 258 continue; 259 } 260 } 261 } finally { 262 /** 263 * Close the move 264 */ 265 ExecutionContext::getActualOrCreateFromEnv() 266 ->closeAndRemoveRuntimeVariableIfExists(action_plugin_combo_linkmove::FILE_MOVE_OPERATION); 267 } 268 269 270 /** 271 * All good, 272 * We don't modify the file system metadata for the page 273 * because the handler does not give it unfortunately 274 */ 275 return $metadataFrontmatterStore->toFrontmatterString(); 276 277 } 278 279 /** 280 * Move a single image and update the JSon 281 * @param $relativeOrAbsoluteWikiId 282 * @param helper_plugin_move_handler $handler 283 * @throws ExceptionCompile on bad argument 284 */ 285 private function moveImage(&$relativeOrAbsoluteWikiId, helper_plugin_move_handler $handler) 286 { 287 try { 288 $newId = $handler->resolveMoves($relativeOrAbsoluteWikiId, "media"); 289 $relativeOrAbsoluteWikiId = WikiPath::IdToAbsolutePath($newId); 290 } catch (Exception $e) { 291 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); 292 } 293 } 294 295 296} 297