1<?php 2 3 4namespace ComboStrap; 5 6 7use dokuwiki\Cache\CacheParser; 8 9class HtmlDocument extends OutputDocument 10{ 11 const mode = "xhtml"; 12 /** 13 * @var CacheParser 14 */ 15 private $snippetCache; 16 /** 17 * @var CacheDependencies 18 */ 19 private $cacheDependencies; 20 21 22 /** 23 * HtmlDocument constructor. 24 * @param Page $page 25 */ 26 public function __construct(Page $page) 27 { 28 parent::__construct($page); 29 30 /** 31 * Modifying the cache key and the corresponding output file 32 * from runtime dependencies 33 */ 34 $this->cacheDependencies = CacheManager::getOrCreate()->getCacheDependenciesForSlot($page->getDokuwikiId()); 35 $this->cacheDependencies->rerouteCacheDestination($this->cache); 36 37 } 38 39 40 function getExtension(): string 41 { 42 return self::mode; 43 } 44 45 46 function getRendererName(): string 47 { 48 return self::mode; 49 } 50 51 public function shouldProcess(): bool 52 { 53 if (!Site::isHtmlRenderCacheOn()) { 54 return true; 55 } 56 return parent::shouldProcess(); 57 } 58 59 /** 60 */ 61 public function getOrProcessContent(): ?string 62 { 63 64 65 if ($this->shouldProcess()) { 66 $this->process(); 67 } 68 return $this->getContent(); 69 70 71 } 72 73 74 /** 75 * Html document is stored 76 */ 77 public function storeContent($content) 78 { 79 80 81 /** We make the Snippet store to Html store an atomic operation 82 * 83 * Why ? Because if the rendering of the page is stopped, 84 * the cache of the HTML page may be stored but not the cache of the snippets 85 * leading to a bad page because the next rendering will see then no snippets. 86 */ 87 $this->storeSnippets(); 88 89 /** 90 * Cache output dependencies 91 */ 92 $this->cacheDependencies->storeDependencies(); 93 $this->cacheDependencies->rerouteCacheDestination($this->cache); 94 95 try { 96 return parent::storeContent($content); 97 } catch (\Exception $e) { 98 // if any write os exception 99 LogUtility::msg("Deleting the snippets, Error while storing the xhtml content: {$e->getMessage()}"); 100 $this->removeSnippets(); 101 return $this; 102 } 103 } 104 105 public function storeSnippets() 106 { 107 108 $slotId = $this->getPage()->getDokuwikiId(); 109 110 /** 111 * Snippet 112 */ 113 $snippetManager = PluginUtility::getSnippetManager(); 114 $jsonDecodeSnippets = $snippetManager->getJsonArrayFromSlotSnippets($slotId); 115 116 /** 117 * Cache file 118 * Using a cache parser, set the page id and will trigger 119 * the parser cache use event in order to log/report the cache usage 120 * At {@link action_plugin_combo_cache::createCacheReport()} 121 */ 122 $snippetCache = $this->getSnippetCacheStore(); 123 124 125 if ($jsonDecodeSnippets !== null) { 126 $data1 = json_encode($jsonDecodeSnippets); 127 $snippetCache->storeCache($data1); 128 } else { 129 $snippetCache->removeCache(); 130 } 131 132 } 133 134 /** 135 * @return Snippet[] 136 */ 137 public 138 function loadSnippets(): array 139 { 140 $data = $this->getSnippetCacheStore()->retrieveCache(); 141 $nativeSnippets = []; 142 if (!empty($data)) { 143 $jsonDecodeSnippets = json_decode($data, true); 144 foreach ($jsonDecodeSnippets as $snippet) { 145 try { 146 $nativeSnippets[] = Snippet::createFromJson($snippet); 147 } catch (ExceptionCombo $e) { 148 LogUtility::msg("The snippet json array cannot be build into a snippet object. " . $e->getMessage()); 149 } 150 151 } 152 } 153 return $nativeSnippets; 154 155 } 156 157 private function removeSnippets() 158 { 159 $snippetCacheFile = $this->getSnippetCacheStore()->cache; 160 if ($snippetCacheFile !== null) { 161 if (file_exists($snippetCacheFile)) { 162 unlink($snippetCacheFile); 163 } 164 } 165 } 166 167 /** 168 * Cache file 169 * Using a cache parser, set the page id and will trigger 170 * the parser cache use event in order to log/report the cache usage 171 * At {@link action_plugin_combo_cache::createCacheReport()} 172 */ 173 public function getSnippetCacheStore(): CacheParser 174 { 175 if ($this->snippetCache !== null) { 176 return $this->snippetCache; 177 } 178 $id = $this->getPage()->getDokuwikiId(); 179 $slotLocalFilePath = $this->getPage() 180 ->getPath() 181 ->toLocalPath() 182 ->toAbsolutePath() 183 ->toString(); 184 $this->snippetCache = new CacheParser($id, $slotLocalFilePath, "snippet.json"); 185 return $this->snippetCache; 186 } 187 188 public function getDependencies(): CacheDependencies 189 { 190 return $this->cacheDependencies; 191 } 192 193 public function getCacheDependencies(): CacheDependencies 194 { 195 return $this->cacheDependencies; 196 } 197 198 public function getDependenciesCacheStore(): CacheParser 199 { 200 return $this->cacheDependencies->getDependenciesCacheStore(); 201 } 202 203} 204