137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeauuse ComboStrap\CacheManager; 44cadd4f8SNickeauuse ComboStrap\CacheMenuItem; 54cadd4f8SNickeauuse ComboStrap\CacheReportHtmlDataBlockArray; 604fd306cSNickeauuse ComboStrap\ExecutionContext; 71fa8c418SNickeauuse ComboStrap\Http; 84cadd4f8SNickeauuse ComboStrap\Identity; 904fd306cSNickeauuse ComboStrap\IFetcher; 1037748cd8SNickeauuse ComboStrap\PluginUtility; 1104fd306cSNickeauuse ComboStrap\SiteConfig; 1237748cd8SNickeau 1337748cd8SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 1437748cd8SNickeau 1537748cd8SNickeau/** 1637748cd8SNickeau * Can we use the parser cache 174cadd4f8SNickeau * 184cadd4f8SNickeau * 194cadd4f8SNickeau * 2037748cd8SNickeau */ 2137748cd8SNickeauclass action_plugin_combo_cache extends DokuWiki_Action_Plugin 2237748cd8SNickeau{ 234cadd4f8SNickeau 2437748cd8SNickeau 251fa8c418SNickeau const CANONICAL = "cache"; 261fa8c418SNickeau const STATIC_SCRIPT_NAMES = ["/lib/exe/jquery.php", "/lib/exe/js.php", "/lib/exe/css.php"]; 271fa8c418SNickeau 28c3437056SNickeau 29c3437056SNickeau /** 3037748cd8SNickeau * @param Doku_Event_Handler $controller 3137748cd8SNickeau */ 3237748cd8SNickeau function register(Doku_Event_Handler $controller) 3337748cd8SNickeau { 3437748cd8SNickeau 3537748cd8SNickeau /** 364cadd4f8SNickeau * Create a {@link \ComboStrap\CacheResult} 3737748cd8SNickeau */ 384cadd4f8SNickeau $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'createCacheResult', array()); 3937748cd8SNickeau 4037748cd8SNickeau 4137748cd8SNickeau /** 42c3437056SNickeau * To add the cache result in the HTML 431fa8c418SNickeau */ 44c3437056SNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'addCacheLogHtmlDataBlock', array()); 4537748cd8SNickeau 4637748cd8SNickeau 471fa8c418SNickeau /** 481fa8c418SNickeau * To delete the VARY on css.php, jquery.php, js.php 491fa8c418SNickeau */ 501fa8c418SNickeau $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'deleteVaryFromStaticGeneratedResources', array()); 511fa8c418SNickeau 524cadd4f8SNickeau 53c3437056SNickeau /** 544cadd4f8SNickeau * Add a icon in the page tools menu 554cadd4f8SNickeau * https://www.dokuwiki.org/devel:event:menu_items_assembly 56c3437056SNickeau */ 574cadd4f8SNickeau $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addMenuItem'); 581fa8c418SNickeau 5937748cd8SNickeau } 6037748cd8SNickeau 6137748cd8SNickeau /** 6237748cd8SNickeau * 6337748cd8SNickeau * @param Doku_Event $event 6437748cd8SNickeau * @param $params 6537748cd8SNickeau */ 664cadd4f8SNickeau function createCacheResult(Doku_Event $event, $params) 6737748cd8SNickeau { 6837748cd8SNickeau 6937748cd8SNickeau /** 7037748cd8SNickeau * To log the cache used by bar 7137748cd8SNickeau * @var \dokuwiki\Cache\CacheParser $data 7237748cd8SNickeau */ 7337748cd8SNickeau $data = $event->data; 74c3437056SNickeau $slotId = $data->page; 7504fd306cSNickeau if (empty($slotId)) { 7604fd306cSNickeau // on edit mode, the page is emtpy 7704fd306cSNickeau return; 7804fd306cSNickeau } 7904fd306cSNickeau $cacheReporter = CacheManager::getFromContextExecution()->getCacheResultsForSlot($slotId); 804cadd4f8SNickeau $cacheReporter->setData($event); 8137748cd8SNickeau 8237748cd8SNickeau 8337748cd8SNickeau } 8437748cd8SNickeau 8537748cd8SNickeau 8637748cd8SNickeau /** 874cadd4f8SNickeau * Add cache data to the rendered html page 8837748cd8SNickeau * @param Doku_Event $event 8937748cd8SNickeau * @param $params 9037748cd8SNickeau */ 91c3437056SNickeau function addCacheLogHtmlDataBlock(Doku_Event $event, $params) 9237748cd8SNickeau { 9337748cd8SNickeau 9404fd306cSNickeau $isPublic = ExecutionContext::getActualOrCreateFromEnv() 9504fd306cSNickeau ->isPublicationAction(); 9604fd306cSNickeau if (!$isPublic) { 974cadd4f8SNickeau return; 984cadd4f8SNickeau } 9904fd306cSNickeau $cacheSlotResults = CacheReportHtmlDataBlockArray::getFromContext(); 100c3437056SNickeau $cacheJson = \ComboStrap\Json::createFromArray($cacheSlotResults); 10137748cd8SNickeau 102c3437056SNickeau if (PluginUtility::isDevOrTest()) { 103c3437056SNickeau $result = $cacheJson->toPrettyJsonString(); 10437748cd8SNickeau } else { 105c3437056SNickeau $result = $cacheJson->toMinifiedJsonString(); 10637748cd8SNickeau } 10737748cd8SNickeau 108c3437056SNickeau $event->data["script"][] = array( 1094cadd4f8SNickeau "type" => CacheReportHtmlDataBlockArray::APPLICATION_COMBO_CACHE_JSON, 110c3437056SNickeau "_data" => $result, 111c3437056SNickeau ); 11237748cd8SNickeau 1134cadd4f8SNickeau 11437748cd8SNickeau } 11537748cd8SNickeau 1161fa8c418SNickeau 1171fa8c418SNickeau /** 1181fa8c418SNickeau * Delete the Vary header 1191fa8c418SNickeau * @param Doku_Event $event 1201fa8c418SNickeau * @param $params 1211fa8c418SNickeau */ 1221fa8c418SNickeau public static function deleteVaryFromStaticGeneratedResources(Doku_Event $event, $params) 1231fa8c418SNickeau { 1241fa8c418SNickeau 1251fa8c418SNickeau $script = $_SERVER["SCRIPT_NAME"]; 1261fa8c418SNickeau if (in_array($script, self::STATIC_SCRIPT_NAMES)) { 127c3437056SNickeau // To be extra sure, they must have the buster key 12804fd306cSNickeau if (isset($_REQUEST[IFetcher::CACHE_BUSTER_KEY])) { 1291fa8c418SNickeau self::deleteVaryHeader(); 1301fa8c418SNickeau } 1311fa8c418SNickeau } 1321fa8c418SNickeau 1331fa8c418SNickeau } 1341fa8c418SNickeau 1351fa8c418SNickeau /** 1361fa8c418SNickeau * 1371fa8c418SNickeau * No Vary: Cookie 1381fa8c418SNickeau * Introduced at 1391fa8c418SNickeau * https://github.com/splitbrain/dokuwiki/issues/1594 1401fa8c418SNickeau * But cache problem at: 1411fa8c418SNickeau * https://github.com/splitbrain/dokuwiki/issues/2520 1421fa8c418SNickeau * 1431fa8c418SNickeau */ 1441fa8c418SNickeau public static function deleteVaryHeader(): void 1451fa8c418SNickeau { 14604fd306cSNickeau if (SiteConfig::getConfValue(action_plugin_combo_staticresource::CONF_STATIC_CACHE_ENABLED, 1)) { 1471fa8c418SNickeau Http::removeHeaderIfPresent("Vary"); 1481fa8c418SNickeau } 1491fa8c418SNickeau } 1501fa8c418SNickeau 1514cadd4f8SNickeau 1524cadd4f8SNickeau function addMenuItem(Doku_Event $event, $param) 153c3437056SNickeau { 154c3437056SNickeau 155c3437056SNickeau /** 1564cadd4f8SNickeau * The `view` property defines the menu that is currently built 1574cadd4f8SNickeau * https://www.dokuwiki.org/devel:menus 1584cadd4f8SNickeau * If this is not the page menu, return 159c3437056SNickeau */ 1604cadd4f8SNickeau if ($event->data['view'] != 'page') return; 161c3437056SNickeau 1624cadd4f8SNickeau global $INFO; 163*70bbd7f1Sgerardnico $exists = $INFO['exists'] ?? null; 164*70bbd7f1Sgerardnico if (!$exists) { 1654cadd4f8SNickeau return; 166c3437056SNickeau } 167c3437056SNickeau /** 1684cadd4f8SNickeau * Cache is for manager 169c3437056SNickeau */ 1704cadd4f8SNickeau if (!Identity::isManager()) { 1714cadd4f8SNickeau return; 172c3437056SNickeau } 1734cadd4f8SNickeau array_splice($event->data['items'], -1, 0, array(new CacheMenuItem())); 174c3437056SNickeau 175c3437056SNickeau 176c3437056SNickeau } 17737748cd8SNickeau 17837748cd8SNickeau} 179