1<?php 2 3require_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 4 5use ComboStrap\Alias; 6use ComboStrap\Aliases; 7use ComboStrap\DatabasePageRow; 8use ComboStrap\ExceptionComboRuntime; 9use ComboStrap\File; 10use ComboStrap\FileSystems; 11use ComboStrap\MarkupRef; 12use ComboStrap\LogUtility; 13use ComboStrap\MetadataDbStore; 14use ComboStrap\MetadataDokuWikiStore; 15use ComboStrap\Page; 16use ComboStrap\PageId; 17use ComboStrap\PluginUtility; 18use ComboStrap\Site; 19 20 21/** 22 * Class action_plugin_combo_move 23 * Handle the move of a page in order to update: 24 * * the link 25 * * the data in the database 26 */ 27class action_plugin_combo_linkmove extends DokuWiki_Action_Plugin 28{ 29 30 31 const CANONICAL = "move"; 32 33 private static function checkAndSendAMessageIfLockFilePresent(): bool 34 { 35 $lockFile = Site::getDataDirectory()->resolve("locks_plugin_move.lock"); 36 if (!FileSystems::exists($lockFile)) { 37 return false; 38 } 39 $lockFileDateTimeModified = FileSystems::getModifiedTime($lockFile); 40 $lockFileModifiedTimestamp = $lockFileDateTimeModified->getTimestamp(); 41 $now = time(); 42 43 $distance = $now - $lockFileModifiedTimestamp; 44 $lockFileAgeInMinute = ($distance) / 60; 45 if ($lockFileAgeInMinute > 5) { 46 LogUtility::msg("The move lockfile ($lockFile) exists and is older than 5 minutes (exactly $lockFileAgeInMinute minutes). If you are no more in a move, you should delete this file otherwise it will disable the move of page and the cache."); 47 return true; 48 } 49 return false; 50 } 51 52 /** 53 * As explained https://www.dokuwiki.org/plugin:move#support_for_other_plugins 54 * @param Doku_Event_Handler $controller 55 */ 56 function register(Doku_Event_Handler $controller) 57 { 58 59 /** 60 * To rewrite the page meta in the database 61 */ 62 $controller->register_hook('PLUGIN_MOVE_PAGE_RENAME', 'BEFORE', $this, 'handle_rename_before', array()); 63 $controller->register_hook('PLUGIN_MOVE_PAGE_RENAME', 'AFTER', $this, 'handle_rename_after', array()); 64 65 /** 66 * To rewrite the link 67 */ 68 $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'handle_link', array()); 69 70 71 /** 72 * Check for the presence of a lock file 73 */ 74 $controller->register_hook('PARSER_WIKITEXT_PREPROCESS', 'BEFORE', $this, 'check_lock_file_age', array()); 75 76 77 } 78 79 /** 80 * @param Doku_Event $event 81 * @param $params 82 * 83 * When a lock file is present, 84 * the move plugin will purge the data in {@link action_plugin_move_rewrite::handle_cache()} 85 * making the rendering fucking slow 86 * We check that the lock file is not 87 */ 88 function check_lock_file_age(Doku_Event $event, $params) 89 { 90 self::checkAndSendAMessageIfLockFilePresent(); 91 92 } 93 94 /** 95 * Handle the path modification of a page 96 * @param Doku_Event $event - https://www.dokuwiki.org/plugin:move#for_plugin_authors 97 * @param $params 98 * 99 */ 100 function handle_rename_before(Doku_Event $event, $params) 101 { 102 /** 103 * Check that the lock file is not older 104 * Lock file bigger than 5 minutes 105 * Is not really possible 106 */ 107 $result = self::checkAndSendAMessageIfLockFilePresent(); 108 if ($result === true) { 109 $event->preventDefault(); 110 LogUtility::msg("The move lock file is present, the move was canceled."); 111 } 112 113 } 114 115 /** 116 * Handle the path modification of a page after 117 * 118 * The metadata file should also have been moved 119 * 120 * @param Doku_Event $event - https://www.dokuwiki.org/plugin:move#for_plugin_authors 121 * @param $params 122 * 123 */ 124 function handle_rename_after(Doku_Event $event, $params) 125 { 126 /** 127 * 128 * $event->data 129 * src_id ⇒ string – the original ID of the page 130 * dst_id ⇒ string – the new ID of the page 131 */ 132 $sourceId = $event->data["src_id"]; 133 $targetId = $event->data["dst_id"]; 134 try { 135 136 /** 137 * Update the dokuwiki id and path 138 */ 139 $databasePage = DatabasePageRow::createFromDokuWikiId($sourceId); 140 if (!$databasePage->exists()) { 141 return; 142 } 143 $databasePage->updatePathAndDokuwikiId($targetId); 144 145 /** 146 * Check page id 147 */ 148 $targetPage = Page::createPageFromId($targetId); 149 $targetPageId = PageId::createForPage($targetPage); 150 $targetPageIdValue = $targetPageId->getValueFromStore(); 151 $databasePageIdValue = $databasePage->getPageId(); 152 153 if ($databasePageIdValue !== $targetPageIdValue) { 154 // this should never happened in test/dev 155 $targetPageId->setValueForce($targetPageIdValue); 156 } 157 158 /** 159 * Add the alias 160 */ 161 Aliases::createForPage($targetPage) 162 ->addAlias($sourceId) 163 ->setWriteStore(MetadataDokuWikiStore::class) 164 ->sendToWriteStore() 165 ->persist() 166 ->setReadStore(MetadataDbStore::class) 167 ->sendToWriteStore() 168 ->persist(); 169 170 171 } catch (Exception $exception) { 172 // We catch the errors if any to not stop the move 173 // There is no transaction feature (it happens or not) 174 $message = "An error occurred during the move replication to the database. Error message was: " . $exception->getMessage(); 175 if (PluginUtility::isDevOrTest()) { 176 throw new RuntimeException($exception); 177 } else { 178 LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 179 } 180 } 181 182 } 183 184 185 /** 186 * Handle the move of a page 187 * @param Doku_Event $event 188 * @param $params 189 */ 190 function handle_link(Doku_Event $event, $params) 191 { 192 /** 193 * The handlers is the name of the component (ie refers to the {@link syntax_plugin_combo_link} handler) 194 * and 'rewrite_combo' to the below method 195 */ 196 $event->data['handlers'][syntax_plugin_combo_link::COMPONENT] = array($this, 'rewrite_combo'); 197 } 198 199 /** 200 * 201 * @param $match 202 * @param $state 203 * @param $pos 204 * @param $plugin 205 * @param helper_plugin_move_handler $handler 206 */ 207 public function rewrite_combo($match, $state, $pos, $plugin, helper_plugin_move_handler $handler) 208 { 209 /** 210 * The original move method 211 * is {@link helper_plugin_move_handler::internallink()} 212 * 213 */ 214 if ($state == DOKU_LEXER_ENTER) { 215 $ref = syntax_plugin_combo_link::parse($match)[syntax_plugin_combo_link::ATTRIBUTE_HREF]; 216 $link = new MarkupRef($ref); 217 if ($link->getUriType() == MarkupRef::WIKI_URI) { 218 219 $handler->internallink($match, $state, $pos); 220 $suffix = "]]"; 221 if (substr($handler->calls, -strlen($suffix)) == $suffix) { 222 $handler->calls = substr($handler->calls, 0, strlen($handler->calls) - strlen($suffix)); 223 } 224 225 } else { 226 227 // Other type of links 228 $handler->calls .= $match; 229 230 } 231 } else { 232 233 // Description and ending 234 $handler->calls .= $match; 235 236 } 237 } 238 239 240} 241