xref: /plugin/struct/action/cache.php (revision 5e29103a15bd9873f422f66a6a5239b6aec4651e)
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