1<?php 2 3require_once(__DIR__ . '/../vendor/autoload.php'); 4 5use ComboStrap\CacheLog; 6use ComboStrap\Event; 7use ComboStrap\ExceptionCompile; 8use ComboStrap\ExceptionNotExists; 9use ComboStrap\LogUtility; 10use ComboStrap\MarkupCacheDependencies; 11use ComboStrap\MarkupPath; 12use ComboStrap\MetadataMutation; 13use ComboStrap\PagePath; 14use ComboStrap\Reference; 15use ComboStrap\References; 16 17 18/** 19 * Refresh the analytics when a backlink mutation occurs for a page 20 */ 21class action_plugin_combo_backlinkmutation extends DokuWiki_Action_Plugin 22{ 23 24 25 public const BACKLINK_MUTATION_EVENT_NAME = 'backlink_mutation'; 26 27 28 public function register(Doku_Event_Handler $controller) 29 { 30 31 32 /** 33 * create the async event 34 */ 35 $controller->register_hook(MetadataMutation::PAGE_METADATA_MUTATION_EVENT, 'AFTER', $this, 'create_backlink_mutation', array()); 36 37 /** 38 * process the Async event 39 */ 40 $controller->register_hook(self::BACKLINK_MUTATION_EVENT_NAME, 'AFTER', $this, 'handle_backlink_mutation'); 41 42 43 } 44 45 /** 46 * @param Doku_Event $event 47 * @param $param 48 * @return void 49 */ 50 public function handle_backlink_mutation(Doku_Event $event, $param) 51 { 52 53 54 $data = $event->data; 55 $pagePath = $data[PagePath::getPersistentName()] ?? null; 56 if ($pagePath === null) { 57 // https://github.com/ComboStrap/combo/issues/58 58 LogUtility::internalError("The page path should be present"); 59 return; 60 } 61 $reference = MarkupPath::createPageFromAbsoluteId($pagePath); 62 63 if ($reference->isSlot()) { 64 return; 65 } 66 67 /** 68 * Delete and recompute analytics 69 */ 70 try { 71 $analyticsDocument = $reference->fetchAnalyticsDocument(); 72 } catch (ExceptionNotExists $e) { 73 return; 74 } 75 CacheLog::deleteCacheIfExistsAndLog( 76 $analyticsDocument, 77 self::BACKLINK_MUTATION_EVENT_NAME, 78 "Backlink mutation" 79 ); 80 81 try { 82 /** 83 * This is only to recompute the {@link \ComboStrap\Meta\Field\BacklinkCount backlinks metric} and 84 * {@link \ComboStrap\LowQualityPage low quality page metrics} 85 * TODO: when the derived meta are in the meta array and not in the {@link renderer_plugin_combo_analytics document}, 86 * we could just compute them there and modify it with a plus 1 87 */ 88 $reference->getDatabasePage()->replicateAnalytics(); 89 } catch (ExceptionCompile $e) { 90 LogUtility::msg("Backlink Mutation: Error while trying to replicate the analytics. Error: {$e->getMessage()}"); 91 } 92 93 /** 94 * Render the (footer slot) if it has a backlink dependency 95 */ 96 MarkupCacheDependencies::reRenderSideSlotIfNeeded( 97 $pagePath, 98 MarkupCacheDependencies::BACKLINKS_DEPENDENCY, 99 self::BACKLINK_MUTATION_EVENT_NAME 100 ); 101 102 103 } 104 105 /** 106 */ 107 function create_backlink_mutation(Doku_Event $event, $params) 108 { 109 110 111 $data = $event->data; 112 113 /** 114 * If this is not a mutation on references we return. 115 */ 116 if ($data[MetadataMutation::NAME_ATTRIBUTE] !== References::getPersistentName()) { 117 return; 118 }; 119 120 $actualReferenceDatas = $data[MetadataMutation::NEW_VALUE_ATTRIBUTE]; 121 $oldReferenceDatas = $data[MetadataMutation::OLD_VALUE_ATTRIBUTE]; 122 123 /** 124 * Create an array of the actual reference with the key as path 125 */ 126 $actualReferences = []; 127 if ($actualReferenceDatas !== null) { 128 foreach ($actualReferenceDatas as $actualReferenceData) { 129 $actualReferenceWikiPathString = $actualReferenceData[Reference::getPersistentName()]; 130 $actualReferences[$actualReferenceWikiPathString] = $actualReferenceWikiPathString; 131 } 132 } 133 134 if ($oldReferenceDatas !== null) { 135 foreach ($oldReferenceDatas as $oldReferenceData) { 136 137 $oldReferenceWikiPathString = $oldReferenceData[Reference::getPersistentName()] ?? null; 138 139 if (isset($actualReferences[$oldReferenceWikiPathString])) { 140 unset($actualReferences[$oldReferenceWikiPathString]); 141 continue; 142 } 143 144 /** 145 * Deleted reference 146 */ 147 Event::createEvent( 148 action_plugin_combo_backlinkmutation::BACKLINK_MUTATION_EVENT_NAME, 149 [ 150 PagePath::getPersistentName() => $oldReferenceWikiPathString 151 ] 152 ); 153 154 } 155 } 156 157 /** 158 * The new references 159 */ 160 foreach ($actualReferences as $newReference) { 161 Event::createEvent( 162 action_plugin_combo_backlinkmutation::BACKLINK_MUTATION_EVENT_NAME, 163 [PagePath::getPersistentName() => $newReference]); 164 } 165 166 167 } 168 169 170} 171