1<?php 2 3 4use ComboStrap\ExceptionNotFound; 5use ComboStrap\ExceptionRuntimeInternal; 6use ComboStrap\ExecutionContext; 7use ComboStrap\LogUtility; 8use ComboStrap\MarkupPath; 9use ComboStrap\Meta\Api\MetadataSystem; 10use ComboStrap\Meta\Field\PageH1; 11use ComboStrap\Meta\Field\PageImages; 12use ComboStrap\Meta\Store\MetadataDokuWikiStore; 13use ComboStrap\MetadataDokuWikiArrayStore; 14use ComboStrap\MetadataFrontmatterStore; 15use ComboStrap\MetadataMutation; 16use ComboStrap\PluginUtility; 17use ComboStrap\References; 18 19/** 20 * 21 * Handle meta rendering processing 22 * * notifiy of changes 23 * * and other 24 * 25 * 26 * The changes notification takes place at the document level 27 * because we want to notify modication on array level (such as references, images) 28 * and not only on scalar. 29 */ 30class action_plugin_combo_metaprocessing extends DokuWiki_Action_Plugin 31{ 32 33 34 private array $beforeMetaArray; 35 36 public function register(Doku_Event_Handler $controller) 37 { 38 /** 39 * https://www.dokuwiki.org/devel:event:parser_metadata_render 40 */ 41 $controller->register_hook('PARSER_METADATA_RENDER', 'BEFORE', $this, 'metadataProcessingBefore', array()); 42 $controller->register_hook('PARSER_METADATA_RENDER', 'AFTER', $this, 'metadataProcessingAfter', array()); 43 44 45 } 46 47 48 function metadataProcessingBefore($event) 49 { 50 51 /** 52 * Capture the before state 53 */ 54 if (isset($this->beforeMetaArray)) { 55 throw new ExceptionRuntimeInternal("The before variable should be unset in the after method"); 56 } 57 $this->beforeMetaArray = $event->data; 58 } 59 60 function metadataProcessingAfter($event) 61 { 62 63 $afterMetaArray = &$event->data; 64 $beforeMetaArray = $this->beforeMetaArray; 65 unset($this->beforeMetaArray); 66 67 $afterId = $afterMetaArray["page"]; 68 $beforeId = $beforeMetaArray["page"]; 69 if ($afterId !== $beforeId) { 70 LogUtility::internalError("The before ($beforeId) and after id ($afterId) are not the same", get_class($this)); 71 return; 72 } 73 74 /** 75 * To avoid 76 * Console Info: slot_footer.xhtml: Cache (1681473480) 77 * is older than dependent C:\Users\GERARD~1\AppData\Local\Temp\dwtests-1681473476.2836\data\meta\cache_manager_slot_test.meta (1681473480), cache is not usable 78 * See {@link \ComboStrap\Test\TestUtility::WaitToCreateCacheFile1SecLater()} 79 */ 80 if (PluginUtility::isDevOrTest()) { 81 sleep(1); 82 } 83 84 $page = MarkupPath::createMarkupFromId($afterId); 85 86 $primaryMetas = action_plugin_combo_pageprimarymetamutation::PRIMARY_METAS; 87 $referencesAttributes = [References::getPersistentName()]; 88 $qualityMetadata = action_plugin_combo_qualitymutation::getQualityMetas(); 89 $attributes = array_merge($primaryMetas, $referencesAttributes, $qualityMetadata); 90 91 $beforeStore = MetadataDokuWikiArrayStore::getOrCreateFromResource($page, $beforeMetaArray); 92 $afterStore = MetadataDokuWikiArrayStore::getOrCreateFromResource($page, $afterMetaArray); 93 /** 94 * The data should be formatted as if it was for the frontmatter 95 * TODO: make it a default for the mutation system ?? 96 */ 97 $targetStoreFormat = MetadataFrontmatterStore::class; 98 foreach ($attributes as $attribute) { 99 100 try { 101 $beforeMeta = MetadataSystem::getForName($attribute) 102 ->setReadStore($beforeStore) 103 ->setWriteStore($targetStoreFormat) 104 ->setResource($page); 105 $afterMeta = MetadataSystem::getForName($attribute) 106 ->setReadStore($afterStore) 107 ->setWriteStore($targetStoreFormat) 108 ->setResource($page); 109 } catch (ExceptionNotFound $e) { 110 LogUtility::internalError("The metadata was not found for the attribute ($attribute)"); 111 continue; 112 } 113 114 try { 115 $beforeMeta->getValue(); 116 $valueBefore = $beforeMeta->toStoreValue(); 117 } catch (Exception $e) { 118 // first value 119 $valueBefore = null; 120 } 121 122 $valueAfter = $afterMeta->toStoreValue(); 123 MetadataMutation::notifyMetadataMutation($attribute, $valueBefore, $valueAfter, $page); 124 125 } 126 127 128 /** 129 * We got a conflict Dokuwiki stores a `title` meta in the current 130 * Because we may delete the first heading, the stored title is the second 131 * heading, we update it 132 * See first line of {@link \Doku_Renderer_metadata::header()} 133 */ 134 $isWikiDisabled = ExecutionContext::getActualOrCreateFromEnv() 135 ->getConfig() 136 ->isHeadingWikiComponentDisabled(); 137 if ($isWikiDisabled) { 138 $event->data[MetadataDokuWikiStore::CURRENT_METADATA]['title'] = $event->data[MetadataDokuWikiStore::CURRENT_METADATA][PageH1::H1_PARSED]; 139 } 140 141 /** 142 * Trick, don't know if this is always true 143 */ 144 PageImages::createForPage($page)->modifyMetaDokuWikiArray($event->data); 145 146 } 147 148} 149