1<?php
2
3
4namespace ComboStrap;
5
6
7use dokuwiki\Cache\CacheParser;
8
9class HtmlDocument extends OutputDocument
10{
11    const mode = "xhtml";
12    /**
13     * @var CacheParser
14     */
15    private $snippetCache;
16    /**
17     * @var CacheDependencies
18     */
19    private $cacheDependencies;
20
21
22    /**
23     * HtmlDocument constructor.
24     * @param Page $page
25     */
26    public function __construct(Page $page)
27    {
28        parent::__construct($page);
29
30        /**
31         * Modifying the cache key and the corresponding output file
32         * from runtime dependencies
33         */
34        $this->cacheDependencies = CacheManager::getOrCreate()->getCacheDependenciesForSlot($page->getDokuwikiId());
35        $this->cacheDependencies->rerouteCacheDestination($this->cache);
36
37    }
38
39
40    function getExtension(): string
41    {
42        return self::mode;
43    }
44
45
46    function getRendererName(): string
47    {
48        return self::mode;
49    }
50
51    public function shouldProcess(): bool
52    {
53        if (!Site::isHtmlRenderCacheOn()) {
54            return true;
55        }
56        return parent::shouldProcess();
57    }
58
59    /**
60     */
61    public function getOrProcessContent(): ?string
62    {
63
64
65        if ($this->shouldProcess()) {
66            $this->process();
67        }
68        return $this->getContent();
69
70
71    }
72
73
74    /**
75     * Html document is stored
76     */
77    public function storeContent($content)
78    {
79
80
81        /** We make the Snippet store to Html store an atomic operation
82         *
83         * Why ? Because if the rendering of the page is stopped,
84         * the cache of the HTML page may be stored but not the cache of the snippets
85         * leading to a bad page because the next rendering will see then no snippets.
86         */
87        $this->storeSnippets();
88
89        /**
90         * Cache output dependencies
91         */
92        $this->cacheDependencies->storeDependencies();
93        $this->cacheDependencies->rerouteCacheDestination($this->cache);
94
95        try {
96            return parent::storeContent($content);
97        } catch (\Exception $e) {
98            // if any write os exception
99            LogUtility::msg("Deleting the snippets, Error while storing the xhtml content: {$e->getMessage()}");
100            $this->removeSnippets();
101            return $this;
102        }
103    }
104
105    public function storeSnippets()
106    {
107
108        $slotId = $this->getPage()->getDokuwikiId();
109
110        /**
111         * Snippet
112         */
113        $snippetManager = PluginUtility::getSnippetManager();
114        $jsonDecodeSnippets = $snippetManager->getJsonArrayFromSlotSnippets($slotId);
115
116        /**
117         * Cache file
118         * Using a cache parser, set the page id and will trigger
119         * the parser cache use event in order to log/report the cache usage
120         * At {@link action_plugin_combo_cache::createCacheReport()}
121         */
122        $snippetCache = $this->getSnippetCacheStore();
123
124
125        if ($jsonDecodeSnippets !== null) {
126            $data1 = json_encode($jsonDecodeSnippets);
127            $snippetCache->storeCache($data1);
128        } else {
129            $snippetCache->removeCache();
130        }
131
132    }
133
134    /**
135     * @return Snippet[]
136     */
137    public
138    function loadSnippets(): array
139    {
140        $data = $this->getSnippetCacheStore()->retrieveCache();
141        $nativeSnippets = [];
142        if (!empty($data)) {
143            $jsonDecodeSnippets = json_decode($data, true);
144            foreach ($jsonDecodeSnippets as $snippet) {
145                try {
146                    $nativeSnippets[] = Snippet::createFromJson($snippet);
147                } catch (ExceptionCombo $e) {
148                    LogUtility::msg("The snippet json array cannot be build into a snippet object. " . $e->getMessage());
149                }
150
151            }
152        }
153        return $nativeSnippets;
154
155    }
156
157    private function removeSnippets()
158    {
159        $snippetCacheFile = $this->getSnippetCacheStore()->cache;
160        if ($snippetCacheFile !== null) {
161            if (file_exists($snippetCacheFile)) {
162                unlink($snippetCacheFile);
163            }
164        }
165    }
166
167    /**
168     * Cache file
169     * Using a cache parser, set the page id and will trigger
170     * the parser cache use event in order to log/report the cache usage
171     * At {@link action_plugin_combo_cache::createCacheReport()}
172     */
173    public function getSnippetCacheStore(): CacheParser
174    {
175        if ($this->snippetCache !== null) {
176            return $this->snippetCache;
177        }
178        $id = $this->getPage()->getDokuwikiId();
179        $slotLocalFilePath = $this->getPage()
180            ->getPath()
181            ->toLocalPath()
182            ->toAbsolutePath()
183            ->toString();
184        $this->snippetCache = new CacheParser($id, $slotLocalFilePath, "snippet.json");
185        return $this->snippetCache;
186    }
187
188    public function getDependencies(): CacheDependencies
189    {
190        return $this->cacheDependencies;
191    }
192
193    public function getCacheDependencies(): CacheDependencies
194    {
195        return $this->cacheDependencies;
196    }
197
198    public function getDependenciesCacheStore(): CacheParser
199    {
200        return $this->cacheDependencies->getDependenciesCacheStore();
201    }
202
203}
204