1dbe5bc9dSAndreas Gohr<?php 2d6d97f60SAnna Dabrowska 37234bfb1Ssplitbrainuse dokuwiki\Extension\ActionPlugin; 47234bfb1Ssplitbrainuse dokuwiki\Extension\Event; 57fe2cdf2SAndreas Gohruse dokuwiki\Extension\EventHandler; 67234bfb1Ssplitbrainuse dokuwiki\plugin\sqlite\SQLiteDB; 7ae5c46faSAndreas Gohruse dokuwiki\plugin\struct\meta\Assignments; 8ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SearchConfig; 9ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SearchConfigParameters; 10dbe5bc9dSAndreas Gohr 11dbe5bc9dSAndreas Gohr/** 12dbe5bc9dSAndreas Gohr * Handle caching of pages containing struct aggregations 13dbe5bc9dSAndreas Gohr */ 147234bfb1Ssplitbrainclass action_plugin_struct_cache extends ActionPlugin 15d6d97f60SAnna Dabrowska{ 16dbe5bc9dSAndreas Gohr /** 17dbe5bc9dSAndreas Gohr * Registers a callback function for a given event 18dbe5bc9dSAndreas Gohr * 19*5e29103aSannda * @param EventHandler $controller DokuWiki's event controller object 20dbe5bc9dSAndreas Gohr * @return void 21dbe5bc9dSAndreas Gohr */ 227234bfb1Ssplitbrain public function register(EventHandler $controller) 23d6d97f60SAnna Dabrowska { 24748e747fSAnna Dabrowska $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handleCacheSchemachange'); 25748e747fSAnna Dabrowska $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handleCacheAggregation'); 26748e747fSAnna Dabrowska $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'handleCacheDynamic'); 27dbe5bc9dSAndreas Gohr } 28dbe5bc9dSAndreas Gohr 29dbe5bc9dSAndreas Gohr /** 30ae5c46faSAndreas Gohr * @return string the refresh file 31ae5c46faSAndreas Gohr */ 32d6d97f60SAnna Dabrowska public static function getSchemaRefreshFile() 33d6d97f60SAnna Dabrowska { 34ae5c46faSAndreas Gohr global $conf; 35ae5c46faSAndreas Gohr return $conf['cachedir'] . '/struct.schemarefresh'; 36ae5c46faSAndreas Gohr } 37ae5c46faSAndreas Gohr 38ae5c46faSAndreas Gohr /** 39ae5c46faSAndreas Gohr * For pages potentially containing schema data, refresh the cache when schema data has been 40ae5c46faSAndreas Gohr * updated 41ae5c46faSAndreas Gohr * 42*5e29103aSannda * @param Event $event event object by reference 43ae5c46faSAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 44ae5c46faSAndreas Gohr * handler was registered] 45ae5c46faSAndreas Gohr * @return bool 46ae5c46faSAndreas Gohr */ 477234bfb1Ssplitbrain public function handleCacheSchemachange(Event $event, $param) 48d6d97f60SAnna Dabrowska { 49ae5c46faSAndreas Gohr /** @var \cache_parser $cache */ 50ae5c46faSAndreas Gohr $cache = $event->data; 51ae5c46faSAndreas Gohr if ($cache->mode != 'xhtml') return true; 52ae5c46faSAndreas Gohr if (!$cache->page) return true; // not a page cache 53ae5c46faSAndreas Gohr 54ae5c46faSAndreas Gohr $assignments = Assignments::getInstance(); 55ae5c46faSAndreas Gohr if (!$assignments->getPageAssignments($cache->page)) return true; // no struct here 56ae5c46faSAndreas Gohr 57ae5c46faSAndreas Gohr $cache->depends['files'][] = self::getSchemaRefreshFile(); 58ae5c46faSAndreas Gohr return true; 59ae5c46faSAndreas Gohr } 60ae5c46faSAndreas Gohr 61ae5c46faSAndreas Gohr /** 62dbe5bc9dSAndreas Gohr * For pages containing an aggregation, add the last modified date of the database itself 63dbe5bc9dSAndreas Gohr * to the cache dependencies 64dbe5bc9dSAndreas Gohr * 65*5e29103aSannda * @param Event $event event object by reference 66dbe5bc9dSAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 67dbe5bc9dSAndreas Gohr * handler was registered] 68dbe5bc9dSAndreas Gohr * @return bool 69dbe5bc9dSAndreas Gohr */ 707234bfb1Ssplitbrain public function handleCacheAggregation(Event $event, $param) 71d6d97f60SAnna Dabrowska { 7216b7d914SAndreas Gohr global $INPUT; 7316b7d914SAndreas Gohr 74dbe5bc9dSAndreas Gohr /** @var \cache_parser $cache */ 75dbe5bc9dSAndreas Gohr $cache = $event->data; 76dbe5bc9dSAndreas Gohr if ($cache->mode != 'xhtml') return true; 77dbe5bc9dSAndreas Gohr if (!$cache->page) return true; // not a page cache 78dbe5bc9dSAndreas Gohr 79dbe5bc9dSAndreas Gohr $meta = p_get_metadata($cache->page, 'plugin struct'); 80dbe5bc9dSAndreas Gohr if (isset($meta['hasaggregation'])) { 81dbe5bc9dSAndreas Gohr /** @var helper_plugin_struct_db $db */ 82dbe5bc9dSAndreas Gohr $db = plugin_load('helper', 'struct_db'); 831dc771ecSAndreas Gohr // cache depends on last database save 847cbcfbdbSAndreas Gohr $sqlite = $db->getDB(false); 857234bfb1Ssplitbrain if ($sqlite instanceof SQLiteDB) { 8679b29326SAnna Dabrowska $cache->depends['files'][] = $sqlite->getDbFile(); 877cbcfbdbSAndreas Gohr } 8816b7d914SAndreas Gohr 891dc771ecSAndreas Gohr // dynamic renders should never overwrite the default page cache 901dc771ecSAndreas Gohr // we need this in additon to handle_cache_dynamic() below because we can only 911dc771ecSAndreas Gohr // influence if a cache is used, not that it will be written 921dc771ecSAndreas Gohr if ( 931dc771ecSAndreas Gohr $INPUT->has(SearchConfigParameters::$PARAM_FILTER) || 941dc771ecSAndreas Gohr $INPUT->has(SearchConfigParameters::$PARAM_OFFSET) || 951dc771ecSAndreas Gohr $INPUT->has(SearchConfigParameters::$PARAM_SORT) 961dc771ecSAndreas Gohr ) { 971dc771ecSAndreas Gohr $cache->key .= 'dynamic'; 981dc771ecSAndreas Gohr } 991dc771ecSAndreas Gohr 10016b7d914SAndreas Gohr // cache depends on today's date 10116b7d914SAndreas Gohr if ($meta['hasaggregation'] & SearchConfig::$CACHE_DATE) { 10216b7d914SAndreas Gohr $oldage = $cache->depends['age']; 10316b7d914SAndreas Gohr $newage = time() - mktime(0, 0, 1); // time since first second today 10416b7d914SAndreas Gohr $cache->depends['age'] = min($oldage, $newage); 10516b7d914SAndreas Gohr } 10616b7d914SAndreas Gohr 10716b7d914SAndreas Gohr // cache depends on current user 10816b7d914SAndreas Gohr if ($meta['hasaggregation'] & SearchConfig::$CACHE_USER) { 10916b7d914SAndreas Gohr $cache->key .= ';' . $INPUT->server->str('REMOTE_USER'); 11016b7d914SAndreas Gohr } 1111dc771ecSAndreas Gohr 1121dc771ecSAndreas Gohr // rebuild cachename 1131dc771ecSAndreas Gohr $cache->cache = getCacheName($cache->key, $cache->ext); 114dbe5bc9dSAndreas Gohr } 115dbe5bc9dSAndreas Gohr 116dbe5bc9dSAndreas Gohr return true; 117dbe5bc9dSAndreas Gohr } 118dbe5bc9dSAndreas Gohr 119dbe5bc9dSAndreas Gohr /** 120dbe5bc9dSAndreas Gohr * Disable cache when dymanic parameters are present 121dbe5bc9dSAndreas Gohr * 122*5e29103aSannda * @param Event $event event object by reference 123dbe5bc9dSAndreas Gohr * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 124dbe5bc9dSAndreas Gohr * handler was registered] 125dbe5bc9dSAndreas Gohr * @return bool 126dbe5bc9dSAndreas Gohr */ 1277234bfb1Ssplitbrain public function handleCacheDynamic(Event $event, $param) 128d6d97f60SAnna Dabrowska { 129dbe5bc9dSAndreas Gohr /** @var \cache_parser $cache */ 130dbe5bc9dSAndreas Gohr $cache = $event->data; 131dbe5bc9dSAndreas Gohr if ($cache->mode != 'xhtml') return true; 132dbe5bc9dSAndreas Gohr if (!$cache->page) return true; // not a page cache 133dbe5bc9dSAndreas Gohr global $INPUT; 134dbe5bc9dSAndreas Gohr 135dbe5bc9dSAndreas Gohr // disable cache use when one of these parameters is present 136d6d97f60SAnna Dabrowska foreach ( 1377fe2cdf2SAndreas Gohr [ 1387fe2cdf2SAndreas Gohr SearchConfigParameters::$PARAM_FILTER, 1397fe2cdf2SAndreas Gohr SearchConfigParameters::$PARAM_OFFSET, 1407fe2cdf2SAndreas Gohr SearchConfigParameters::$PARAM_SORT 1417fe2cdf2SAndreas Gohr ] as $key 142d6d97f60SAnna Dabrowska ) { 143dbe5bc9dSAndreas Gohr if ($INPUT->has($key)) { 144dbe5bc9dSAndreas Gohr $event->result = false; 145dbe5bc9dSAndreas Gohr return true; 146dbe5bc9dSAndreas Gohr } 147dbe5bc9dSAndreas Gohr } 148dbe5bc9dSAndreas Gohr 149dbe5bc9dSAndreas Gohr return true; 150dbe5bc9dSAndreas Gohr } 151dbe5bc9dSAndreas Gohr} 152