1<?php 2 3use ComboStrap\CacheManager; 4use ComboStrap\Iso8601Date; 5use ComboStrap\PluginUtility; 6 7require_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 8 9/** 10 * Can we use the parser cache 11 */ 12class action_plugin_combo_cache extends DokuWiki_Action_Plugin 13{ 14 const COMBO_CACHE_PREFIX = "combo:cache:"; 15 16 /** 17 * @param Doku_Event_Handler $controller 18 */ 19 function register(Doku_Event_Handler $controller) 20 { 21 22 /** 23 * Log the cache usage and also 24 */ 25 $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'logCacheUsage', array()); 26 27 $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'purgeIfNeeded', array()); 28 29 /** 30 * To add the cache result in the header 31 */ 32 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addMeta', array()); 33 34 /** 35 * To reset the cache manager 36 * between two run in the test 37 */ 38 $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array()); 39 40 } 41 42 /** 43 * 44 * @param Doku_Event $event 45 * @param $params 46 */ 47 function logCacheUsage(Doku_Event $event, $params) 48 { 49 50 /** 51 * To log the cache used by bar 52 * @var \dokuwiki\Cache\CacheParser $data 53 */ 54 $data = $event->data; 55 $result = $event->result; 56 $pageId = $data->page; 57 $cacheManager = PluginUtility::getCacheManager(); 58 $cacheManager->addSlot($pageId, $result, $data); 59 60 61 } 62 63 /** 64 * 65 * @param Doku_Event $event 66 * @param $params 67 */ 68 function purgeIfNeeded(Doku_Event $event, $params) 69 { 70 71 /** 72 * No cache for all mode 73 * (ie xhtml, instruction) 74 */ 75 $data = &$event->data; 76 $pageId = $data->page; 77 /** 78 * Because of the recursive nature of rendering 79 * inside dokuwiki, we just handle the first 80 * rendering for a request. 81 * 82 * The first will be purged, the other one not 83 * because they can use the first one 84 */ 85 if (!PluginUtility::getCacheManager()->isCacheLogPresent($pageId, $data->mode)) { 86 $expirationStringDate = p_get_metadata($pageId, CacheManager::DATE_CACHE_EXPIRATION_META_KEY, METADATA_DONT_RENDER); 87 if ($expirationStringDate !== null) { 88 89 $expirationDate = Iso8601Date::create($expirationStringDate)->getDateTime(); 90 $actualDate = new DateTime(); 91 if ($expirationDate < $actualDate) { 92 /** 93 * As seen in {@link Cache::makeDefaultCacheDecision()} 94 * We request a purge 95 */ 96 $data->depends["purge"] = true; 97 } 98 } 99 } 100 101 102 } 103 104 /** 105 * Add HTML meta to be able to debug 106 * @param Doku_Event $event 107 * @param $params 108 */ 109 function addMeta(Doku_Event $event, $params) 110 { 111 112 $cacheManager = PluginUtility::getCacheManager(); 113 $slots = $cacheManager->getCacheSlotResults(); 114 foreach ($slots as $slotId => $modes) { 115 116 $cachedMode = []; 117 foreach ($modes as $mode => $values) { 118 if ($values[CacheManager::RESULT_STATUS] === true) { 119 $metaContentData = $mode; 120 if(!PluginUtility::isTest()){ 121 /** 122 * @var DateTime $dateModified 123 */ 124 $dateModified = $values[CacheManager::DATE_MODIFIED]; 125 $metaContentData .= ":". $dateModified->format('Y-m-d\TH:i:s'); 126 } 127 $cachedMode[] = $metaContentData; 128 } 129 } 130 131 if (sizeof($cachedMode) === 0) { 132 $value = "nocache"; 133 } else { 134 sort($cachedMode); 135 $value = implode(",", $cachedMode); 136 } 137 138 // Add cache information into the head meta 139 // to test 140 $event->data["meta"][] = array("name" => self::COMBO_CACHE_PREFIX . $slotId, "content" => hsc($value)); 141 } 142 143 } 144 145 function close(Doku_Event $event, $params) 146 { 147 CacheManager::close(); 148 } 149 150 151} 152