1<?php 2 3 4namespace ComboStrap; 5 6 7use dokuwiki\Cache\CacheParser; 8 9class CacheManager 10{ 11 12 const RESULT_STATUS = 'result'; 13 const DATE_MODIFIED = 'ftime'; 14 public const APPLICATION_COMBO_CACHE_JSON = "application/combo+cache+json"; 15 16 /** 17 * @var CacheManager 18 */ 19 private static $cacheManager; 20 21 /** 22 * Just an utility variable to tracks the cache result of each slot 23 * @var array the processed slot by: 24 * * requested page id, (to avoid inconsistency on multiple page run in one test) 25 * * slot id 26 */ 27 private $cacheResults = array(); 28 29 30 /** 31 * @return CacheManager 32 */ 33 public static function getOrCreate(): CacheManager 34 { 35 if (self::$cacheManager === null) { 36 self::$cacheManager = new CacheManager(); 37 } 38 return self::$cacheManager; 39 } 40 41 42 /** 43 * In test, we may run more than once 44 * This function delete the cache manager 45 * and is called when Dokuwiki close (ie {@link \action_plugin_combo_cache::close()}) 46 */ 47 public static function reset() 48 { 49 50 self::$cacheManager = null; 51 52 } 53 54 /** 55 * Keep track of the parsed slot (ie page in page) 56 * @param $slotId 57 * @param $result 58 * @param CacheParser $cacheParser 59 */ 60 public function addSlotForRequestedPage($slotId, $result, CacheParser $cacheParser) 61 { 62 63 $requestedPageSlotResults = &$this->getCacheSlotResultsForRequestedPage(); 64 65 66 if (!isset($requestedPageSlotResults[$slotId])) { 67 $requestedPageSlotResults[$slotId] = []; 68 } 69 70 /** 71 * Metadata and other rendering may occurs 72 * recursively in one request 73 * 74 * We record only the first one because the second call one will use the first 75 * one 76 */ 77 if (!isset($requestedPageSlotResults[$slotId][$cacheParser->mode])) { 78 $date = null; 79 if (file_exists($cacheParser->cache)) { 80 $date = Iso8601Date::createFromTimestamp(filemtime($cacheParser->cache))->getDateTime(); 81 } 82 $requestedPageSlotResults[$slotId][$cacheParser->mode] = [ 83 self::RESULT_STATUS => $result, 84 self::DATE_MODIFIED => $date 85 ]; 86 } 87 88 } 89 90 public function getXhtmlCacheSlotResultsForRequestedPage(): array 91 { 92 $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage(); 93 if ($cacheSlotResultsForRequestedPage === null) { 94 return []; 95 } 96 $xhtmlRenderResult = []; 97 foreach ($cacheSlotResultsForRequestedPage as $slotId => $modes) { 98 foreach ($modes as $mode => $values) { 99 if ($mode === "xhtml") { 100 $xhtmlRenderResult[$slotId] = $values[self::RESULT_STATUS]; 101 } 102 } 103 } 104 return $xhtmlRenderResult; 105 } 106 107 private function &getCacheSlotResultsForRequestedPage(): ?array 108 { 109 $requestedPage = $this->getRequestedPage(); 110 $requestedPageSlotResults = &$this->cacheResults[$requestedPage]; 111 if (!isset($requestedPageSlotResults)) { 112 $requestedPageSlotResults = []; 113 } 114 return $requestedPageSlotResults; 115 } 116 117 public function isCacheLogPresentForSlot($slotId, $mode): bool 118 { 119 $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage(); 120 return isset($cacheSlotResultsForRequestedPage[$slotId][$mode]); 121 } 122 123 124 /** 125 * @return array - a array that will be transformed as json HTML data block 126 * to be included in a HTML page 127 */ 128 public function getCacheSlotResultsAsHtmlDataBlockArray(): array 129 { 130 $htmlDataBlock = []; 131 $cacheSlotResultsForRequestedPage = $this->getCacheSlotResultsForRequestedPage(); 132 if ($cacheSlotResultsForRequestedPage === null) { 133 LogUtility::msg("No page slot results were found"); 134 return []; 135 } 136 foreach ($cacheSlotResultsForRequestedPage as $pageId => $resultByFormat) { 137 foreach ($resultByFormat as $format => $result) { 138 $modifiedDate = $result[self::DATE_MODIFIED]; 139 if ($modifiedDate !== null) { 140 $modifiedDate = Iso8601Date::createFromDateTime($modifiedDate)->toString(); 141 } 142 $htmlDataBlock[$pageId][$format] = [ 143 self::RESULT_STATUS => $result[self::RESULT_STATUS], 144 "mtime" => $modifiedDate 145 ]; 146 } 147 148 } 149 return $htmlDataBlock; 150 } 151 152 private function getRequestedPage() 153 { 154 global $_REQUEST; 155 $requestedPage = $_REQUEST[DokuwikiId::DOKUWIKI_ID_ATTRIBUTE]; 156 157 if ($requestedPage !== null) { 158 return $requestedPage; 159 } 160 161 /** 162 * We are not on a HTTP request 163 * but may be on a {@link Page::renderMetadataAndFlush() metadata rendering request} 164 */ 165 global $ID; 166 if ($ID !== null) { 167 return $ID; 168 } 169 170 if(PluginUtility::isTest()) { 171 /** 172 * {@link p_get_metadata()} check the cache and is used 173 * also in several place such as {@link feed.php} 174 * where we don't have any influence 175 */ 176 LogUtility::msg("The requested page should be known to register a page cache result"); 177 } 178 return "unknown"; 179 } 180 181 public function isEmpty(): bool 182 { 183 return sizeof($this->cacheResults) === 0; 184 } 185 186 187} 188