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