1<?php 2 3use ComboStrap\CacheManager; 4use ComboStrap\CacheMenuItem; 5use ComboStrap\CacheReportHtmlDataBlockArray; 6use ComboStrap\ExecutionContext; 7use ComboStrap\Http; 8use ComboStrap\Identity; 9use ComboStrap\IFetcher; 10use ComboStrap\PluginUtility; 11use ComboStrap\SiteConfig; 12 13require_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 14 15/** 16 * Can we use the parser cache 17 * 18 * 19 * 20 */ 21class action_plugin_combo_cache extends DokuWiki_Action_Plugin 22{ 23 24 25 const CANONICAL = "cache"; 26 const STATIC_SCRIPT_NAMES = ["/lib/exe/jquery.php", "/lib/exe/js.php", "/lib/exe/css.php"]; 27 28 29 /** 30 * @param Doku_Event_Handler $controller 31 */ 32 function register(Doku_Event_Handler $controller) 33 { 34 35 /** 36 * Create a {@link \ComboStrap\CacheResult} 37 */ 38 $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'createCacheResult', array()); 39 40 41 /** 42 * To add the cache result in the HTML 43 */ 44 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addCacheLogHtmlDataBlock', array()); 45 46 47 /** 48 * To delete the VARY on css.php, jquery.php, js.php 49 */ 50 $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'deleteVaryFromStaticGeneratedResources', array()); 51 52 53 /** 54 * Add a icon in the page tools menu 55 * https://www.dokuwiki.org/devel:event:menu_items_assembly 56 */ 57 $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addMenuItem'); 58 59 } 60 61 /** 62 * 63 * @param Doku_Event $event 64 * @param $params 65 */ 66 function createCacheResult(Doku_Event $event, $params) 67 { 68 69 /** 70 * To log the cache used by bar 71 * @var \dokuwiki\Cache\CacheParser $data 72 */ 73 $data = $event->data; 74 $slotId = $data->page; 75 if (empty($slotId)) { 76 // on edit mode, the page is emtpy 77 return; 78 } 79 $cacheReporter = CacheManager::getFromContextExecution()->getCacheResultsForSlot($slotId); 80 $cacheReporter->setData($event); 81 82 83 } 84 85 86 /** 87 * Add cache data to the rendered html page 88 * @param Doku_Event $event 89 * @param $params 90 */ 91 function addCacheLogHtmlDataBlock(Doku_Event $event, $params) 92 { 93 94 $isPublic = ExecutionContext::getActualOrCreateFromEnv() 95 ->isPublicationAction(); 96 if (!$isPublic) { 97 return; 98 } 99 $cacheSlotResults = CacheReportHtmlDataBlockArray::getFromContext(); 100 $cacheJson = \ComboStrap\Json::createFromArray($cacheSlotResults); 101 102 if (PluginUtility::isDevOrTest()) { 103 $result = $cacheJson->toPrettyJsonString(); 104 } else { 105 $result = $cacheJson->toMinifiedJsonString(); 106 } 107 108 $event->data["script"][] = array( 109 "type" => CacheReportHtmlDataBlockArray::APPLICATION_COMBO_CACHE_JSON, 110 "_data" => $result, 111 ); 112 113 114 } 115 116 117 /** 118 * Delete the Vary header 119 * @param Doku_Event $event 120 * @param $params 121 */ 122 public static function deleteVaryFromStaticGeneratedResources(Doku_Event $event, $params) 123 { 124 125 $script = $_SERVER["SCRIPT_NAME"]; 126 if (in_array($script, self::STATIC_SCRIPT_NAMES)) { 127 // To be extra sure, they must have the buster key 128 if (isset($_REQUEST[IFetcher::CACHE_BUSTER_KEY])) { 129 self::deleteVaryHeader(); 130 } 131 } 132 133 } 134 135 /** 136 * 137 * No Vary: Cookie 138 * Introduced at 139 * https://github.com/splitbrain/dokuwiki/issues/1594 140 * But cache problem at: 141 * https://github.com/splitbrain/dokuwiki/issues/2520 142 * 143 */ 144 public static function deleteVaryHeader(): void 145 { 146 if (SiteConfig::getConfValue(action_plugin_combo_staticresource::CONF_STATIC_CACHE_ENABLED, 1)) { 147 Http::removeHeaderIfPresent("Vary"); 148 } 149 } 150 151 152 function addMenuItem(Doku_Event $event, $param) 153 { 154 155 /** 156 * The `view` property defines the menu that is currently built 157 * https://www.dokuwiki.org/devel:menus 158 * If this is not the page menu, return 159 */ 160 if ($event->data['view'] != 'page') return; 161 162 global $INFO; 163 $exists = $INFO['exists'] ?? null; 164 if (!$exists) { 165 return; 166 } 167 /** 168 * Cache is for manager 169 */ 170 if (!Identity::isManager()) { 171 return; 172 } 173 array_splice($event->data['items'], -1, 0, array(new CacheMenuItem())); 174 175 176 } 177 178} 179