1<?php
2
3
4namespace ComboStrap;
5
6/**
7 * Class BarCache
8 * @package ComboStrap
9 *
10 * This class resolve the following problem.
11 *
12 * An improvement request was done at:
13 * See:
14 * https://github.com/splitbrain/dokuwiki/issues/3496
15 *
16 * *The problem**
17 * Most of the [sidebar](https://www.dokuwiki.org/faq:sidebar) requires to disallow the cache with the tag `~~CACHE~~` to keep the content relevant.
18 * *Why ?**
19 * - The output of a sidebar is related to the context of the requested page. (ie `$ID`). They contains mostly navigational plugin (for instance, showing the list of pages for the parent namespace of the requested page.)
20 * - The sidebar functionality permits to have one `sidebar` page physical file at the root for all pages of the website (see the `page_findnearest` function at [pl_include_page](https://github.com/splitbrain/dokuwiki/blob/master/inc/template.php#L1570)
21 * - The cache is stored at the physical level with the key using the file path. See [CacheParse](https://github.com/splitbrain/dokuwiki/blob/master/inc/Cache/CacheParser.php#L30)
22 * ```
23 * parent::__construct($file . $_SERVER['HTTP_HOST'] . $_SERVER['SERVER_PORT'], '.' . $mode);
24 * ```
25 *
26 * This three points makes that:
27 * - for a `:sidebar` at the root of the website listing the pages of the current namespace
28 * - the first requested page (for instance, `:bar:page`) would see a sidebar with all pages of the namespace `bar`
29 * - the second requested page (for instance `:foo:page`) would hit the cache and would show all pages of the `bar` namespace and not `foo`
30 **Proposed solution**
31 *
32 * Can we have a logical key (ie the id) instead of the physical one (the file) ?
33 *
34 * ```
35 * parent::__construct($id . $_SERVER['HTTP_HOST'] . $_SERVER['SERVER_PORT'], '.' . $mode);
36 * ```
37 *
38 * It would then be possible to pass a different id (logical id):
39 * - for the first request  `:bar:sidebar`
40 * - for the second: `:foo:sidebar`
41 *
42 * and they would not share the same cache.
43 */
44class CacheByLogicalKey extends \dokuwiki\Cache\Cache
45{
46
47    public $file;
48    public $mode;
49
50    /**
51     * To be compatible with
52     * {@link action_plugin_move_rewrite::handle_cache()} line 88
53     * that expect the $page with the id
54     */
55    public $page;
56
57    /**
58     * @var Page $pageObject The page object
59     */
60    private $pageObject;
61
62    /**
63     * BarCache constructor.
64     *
65     *
66     *
67     * @param Page $pageObject - the page
68     * @param string $mode
69     */
70    public function __construct($pageObject, $mode)
71    {
72
73        $this->pageObject = $pageObject;
74        $this->mode = $mode;
75
76
77        $this->setEvent('PARSER_CACHE_USE');
78
79        /**
80         * Needed by the move plugin
81         */
82        $this->page = $pageObject->getId();
83
84        parent::__construct($this->getCacheKey(), $this->getExt());
85
86    }
87
88    protected function addDependencies()
89    {
90
91        /**
92         * Configuration
93         * File when they are touched the cache should be stale
94         */
95        $files = getConfigFiles('main');
96        /**
97         * The original file
98         */
99        $files[] = $this->pageObject->getFileSystemPath();
100
101        /**
102         * Update the dependency
103         */
104        $this->depends = ["files" => $files];
105
106        parent::addDependencies();
107
108    }
109
110    public function storeCache($data)
111    {
112
113        /**
114         * The logical id depends on the
115         * scope that can be set when the page is parsed
116         * (ie therefore after that the cache object is created
117         * if the cache does not exist)
118         *
119         * The logic is get the cache, if it does not exist
120         * parse it, then store the cache. If the cache does not exist,
121         * the logical id is not yet known
122         *
123         * We change the cache location file
124         * before storing
125         */
126        $this->cache = $this->getCacheFile();
127        return io_saveFile($this->cache, $data);
128
129    }
130
131    private function getCacheKey()
132    {
133        return $this->pageObject->getLogicalId() . $_SERVER['HTTP_HOST'] . $_SERVER['SERVER_PORT'];
134    }
135
136    protected function getCacheFile()
137    {
138        return getCacheName($this->getCacheKey(), $this->getExt());
139    }
140
141    private function getExt()
142    {
143        return '.' . $this->mode;
144    }
145
146
147
148
149}
150