1<?php 2use dokuwiki\plugin\struct\meta\Assignments; 3use dokuwiki\plugin\struct\meta\SearchConfig; 4use dokuwiki\plugin\struct\meta\SearchConfigParameters; 5 6/** 7 * Handle caching of pages containing struct aggregations 8 */ 9class action_plugin_struct_cache extends DokuWiki_Action_Plugin { 10 11 /** 12 * Registers a callback function for a given event 13 * 14 * @param Doku_Event_Handler $controller DokuWiki's event controller object 15 * @return void 16 */ 17 public function register(Doku_Event_Handler $controller) { 18 $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache_schemachange'); 19 $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache_aggregation'); 20 $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'handle_cache_dynamic'); 21 } 22 23 /** 24 * @return string the refresh file 25 */ 26 public static function getSchemaRefreshFile() { 27 global $conf; 28 return $conf['cachedir'] . '/struct.schemarefresh'; 29 } 30 31 /** 32 * For pages potentially containing schema data, refresh the cache when schema data has been 33 * updated 34 * 35 * @param Doku_Event $event event object by reference 36 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 37 * handler was registered] 38 * @return bool 39 */ 40 public function handle_cache_schemachange(Doku_Event $event, $param) { 41 /** @var \cache_parser $cache */ 42 $cache = $event->data; 43 if($cache->mode != 'xhtml') return true; 44 if(!$cache->page) return true; // not a page cache 45 46 $assignments = Assignments::getInstance(); 47 if(!$assignments->getPageAssignments($cache->page)) return true; // no struct here 48 49 $cache->depends['files'][] = self::getSchemaRefreshFile(); 50 return true; 51 } 52 53 /** 54 * For pages containing an aggregation, add the last modified date of the database itself 55 * to the cache dependencies 56 * 57 * @param Doku_Event $event event object by reference 58 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 59 * handler was registered] 60 * @return bool 61 */ 62 public function handle_cache_aggregation(Doku_Event $event, $param) { 63 global $INPUT; 64 65 /** @var \cache_parser $cache */ 66 $cache = $event->data; 67 if($cache->mode != 'xhtml') return true; 68 if(!$cache->page) return true; // not a page cache 69 70 $meta = p_get_metadata($cache->page, 'plugin struct'); 71 if(isset($meta['hasaggregation'])) { 72 /** @var helper_plugin_struct_db $db */ 73 $db = plugin_load('helper', 'struct_db'); 74 // cache depends on last database save 75 $sqlite = $db->getDB(false); 76 if($sqlite) { 77 $cache->depends['files'][] = $sqlite->getAdapter()->getDbFile(); 78 } 79 80 // dynamic renders should never overwrite the default page cache 81 // we need this in additon to handle_cache_dynamic() below because we can only 82 // influence if a cache is used, not that it will be written 83 if( 84 $INPUT->has(SearchConfigParameters::$PARAM_FILTER) || 85 $INPUT->has(SearchConfigParameters::$PARAM_OFFSET) || 86 $INPUT->has(SearchConfigParameters::$PARAM_SORT) 87 ) { 88 $cache->key .= 'dynamic'; 89 } 90 91 // cache depends on today's date 92 if($meta['hasaggregation'] & SearchConfig::$CACHE_DATE) { 93 $oldage = $cache->depends['age']; 94 $newage = time() - mktime(0, 0, 1); // time since first second today 95 $cache->depends['age'] = min($oldage, $newage); 96 } 97 98 // cache depends on current user 99 if($meta['hasaggregation'] & SearchConfig::$CACHE_USER) { 100 $cache->key .= ';' . $INPUT->server->str('REMOTE_USER'); 101 102 } 103 104 // rebuild cachename 105 $cache->cache = getCacheName($cache->key, $cache->ext); 106 } 107 108 return true; 109 } 110 111 /** 112 * Disable cache when dymanic parameters are present 113 * 114 * @param Doku_Event $event event object by reference 115 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 116 * handler was registered] 117 * @return bool 118 */ 119 public function handle_cache_dynamic(Doku_Event $event, $param) { 120 /** @var \cache_parser $cache */ 121 $cache = $event->data; 122 if($cache->mode != 'xhtml') return true; 123 if(!$cache->page) return true; // not a page cache 124 global $INPUT; 125 126 // disable cache use when one of these parameters is present 127 foreach(array( 128 SearchConfigParameters::$PARAM_FILTER, 129 SearchConfigParameters::$PARAM_OFFSET, 130 SearchConfigParameters::$PARAM_SORT 131 ) as $key) { 132 if($INPUT->has($key)) { 133 $event->result = false; 134 return true; 135 } 136 } 137 138 return true; 139 } 140 141} 142