1<?php
2
3use dokuwiki\plugin\struct\meta\Assignments;
4use dokuwiki\plugin\struct\meta\SearchConfig;
5use dokuwiki\plugin\struct\meta\SearchConfigParameters;
6use dokuwiki\plugin\structat\meta\SearchConfigAtParameters;
7
8/**
9 * Handle caching of pages containing struct aggregations
10 */
11class action_plugin_structat_cache extends DokuWiki_Action_Plugin
12{
13
14    /**
15     * Registers a callback function for a given event
16     *
17     * @param Doku_Event_Handler $controller DokuWiki's event controller object
18     * @return void
19     */
20    public function register(Doku_Event_Handler $controller)
21    {
22        $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handleCacheAggregation', null, 1);
23        $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'handleCacheDynamic', null, 1);
24    }
25
26    /**
27     * For pages containing an aggregation, add the last modified date of the database itself
28     * to the cache dependencies
29     *
30     * @param Doku_Event $event event object by reference
31     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
32     *                           handler was registered]
33     * @return bool
34     */
35    public function handleCacheAggregation(Doku_Event $event, $param)
36    {
37        global $INPUT;
38
39        /** @var \cache_parser $cache */
40        $cache = $event->data;
41        if ($cache->mode != 'xhtml') return true;
42        if (!$cache->page) return true; // not a page cache
43
44        $meta = p_get_metadata($cache->page, 'plugin struct');
45        if (isset($meta['hasaggregation'])) {
46            // dynamic renders should never overwrite the default page cache
47            // we need this in additon to handle_cache_dynamic() below because we can only
48            // influence if a cache is used, not that it will be written
49            if (
50                $INPUT->has(SearchConfigAtParameters::$PARAM_AT)
51            ) {
52                // check if we have an user
53                $user_key = '';
54                if ($meta['hasaggregation'] & SearchConfig::$CACHE_USER) {
55                    //remove user part
56                    $user_key = ';' . $INPUT->server->str('REMOTE_USER');
57                    $cache->key = substr($cache->key, 0, -strlen($user_key));
58                }
59                // not dynamic yet
60                if (substr($cache->key, -strlen('dynamic')) != 'dynamic') {
61                    $cache->key .= 'dynamic';
62                }
63                $cache->key .= $user_key;
64            }
65
66            // rebuild cachename
67            $cache->cache = getCacheName($cache->key, $cache->ext);
68        }
69
70        return true;
71    }
72
73    /**
74     * Disable cache when dymanic parameters are present
75     *
76     * @param Doku_Event $event event object by reference
77     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
78     *                           handler was registered]
79     * @return bool
80     */
81    public function handleCacheDynamic(Doku_Event $event, $param)
82    {
83        /** @var \cache_parser $cache */
84        $cache = $event->data;
85        if ($cache->mode != 'xhtml') return true;
86        if (!$cache->page) return true; // not a page cache
87        global $INPUT;
88
89        // disable cache use when one of these parameters is present
90        foreach (
91            array(
92                    SearchConfigAtParameters::$PARAM_AT
93                ) as $key
94        ) {
95            if ($INPUT->has($key)) {
96                $event->result = false;
97                return true;
98            }
99        }
100
101        return true;
102    }
103}
104