xref: /plugin/combo/action/snippets.php (revision 32b85071e019dd3646a67c17fac4051338e495eb)
1<?php
2
3use ComboStrap\LogUtility;
4use ComboStrap\PluginUtility;
5use ComboStrap\Site;
6use ComboStrap\SnippetManager;
7use dokuwiki\Cache\CacheRenderer;
8
9if (!defined('DOKU_INC')) die();
10
11/**
12 *
13 *
14 * Add the snippet needed by the components
15 *
16 */
17class action_plugin_combo_snippets extends DokuWiki_Action_Plugin
18{
19
20    const COMBO_CACHE_PREFIX = "combo:cache:";
21
22    /**
23     * @var bool - to trace if the header output was called
24     */
25    private $headerOutputWasCalled = false;
26
27    function __construct()
28    {
29        // enable direct access to language strings
30        // ie $this->lang
31        $this->setupLocale();
32    }
33
34    public function register(Doku_Event_Handler $controller)
35    {
36
37        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array());
38        $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array());
39        $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'componentSnippetContent', array());
40
41
42        $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'barParsed', array());
43
44    }
45
46    /**
47     * Reset variable
48     * Otherwise in test, when we call it two times, it just fail
49     */
50    function close(){
51
52        $this->headerOutputWasCalled = false;
53
54        /**
55         * Fighting the fact that in 7.2,
56         * there is still a cache
57         */
58        PluginUtility::initSnippetManager();
59
60    }
61
62    /**
63     * Dokuwiki has already a canonical methodology
64     * https://www.dokuwiki.org/canonical
65     *
66     * @param $event
67     */
68    function componentSnippetHead($event)
69    {
70
71
72        global $ID;
73        if (empty($ID)) {
74            return;
75        }
76
77        /**
78         * Advertise that the header output was called
79         * If the user is using another template
80         * than strap that does not put the component snippet
81         * in the head
82         * Used in
83         */
84        $this->headerOutputWasCalled = true;
85
86        $snippetManager = PluginUtility::getSnippetManager();
87
88        /**
89         * For each processed bar in the page
90         *   * retrieve the snippets from the cache or store the process one
91         *   * add the cache information in meta
92         */
93        $bars = $snippetManager->getBarsOfPage();
94        foreach ($bars as $bar => $servedFromCache) {
95
96            // Add cache meta for info
97            $event->data["meta"][] = array("name" => self::COMBO_CACHE_PREFIX . $bar, "content" => var_export($servedFromCache, true));
98
99            // Get or store the data
100            $cache = new \dokuwiki\Cache\Cache($bar, "snippet");
101
102            // if the bar was served from the cache
103            if ($servedFromCache) {
104                // Retrieve snippets from previous run
105
106                $data = $cache->retrieveCache();
107
108                if (!empty($data)) {
109                    $snippets = unserialize($data);
110                    $snippetManager->addSnippetsFromCacheForBar($bar, $snippets);
111
112                    if (Site::debugIsOn()) {
113                        LogUtility::log2file("Snippet cache file {$cache->cache} used", LogUtility::LVL_MSG_DEBUG);
114                        $event->data['script'][] = array(
115                            "type" => "application/json",
116                            "_data" => json_encode($snippets),
117                            "class" => "combo-snippet-cache-" . str_replace(":", "-", $bar));
118                    }
119
120                }
121            } else {
122                $snippets = $snippetManager->getSnippetsForBar($bar);
123                if(!empty($snippets)) {
124                    $cache->storeCache(serialize($snippets));
125                }
126            }
127
128        }
129
130        /**
131         * tags
132         */
133        foreach ($snippetManager->getTags() as $component => $tags) {
134            foreach ($tags as $tagType => $tagRows) {
135                foreach ($tagRows as $tagRow) {
136                    $tagRow["class"] = SnippetManager::getClassFromTag($component);;
137                    $event->data[$tagType][] = $tagRow;
138                }
139            }
140        }
141
142        /**
143         * Css
144         */
145        foreach ($snippetManager->getCss() as $component => $snippet) {
146            $event->data['style'][] = array(
147                "class" => SnippetManager::getClassFromTag($component),
148                "_data" => $snippet
149            );
150        }
151
152        /**
153         * Javascript
154         */
155        foreach ($snippetManager->getJavascript() as $component => $snippet) {
156            $event->data['script'][] = array(
157                "class" => SnippetManager::getClassFromTag($component),
158                "type" => "text/javascript",
159                "_data" => $snippet
160            );
161        }
162
163
164        $snippetManager->close();
165
166    }
167
168    /**
169     * Used if the template does not run the content
170     * before the calling of the header as strap does.
171     *
172     * In this case, the {@link \ComboStrap\SnippetManager::close()} has
173     * not run, and the snippets are still in memory.
174     *
175     * We store them in the HTML and they
176     * follows then the HTML cache of DokuWiki
177     * @param $event
178     */
179    function componentSnippetContent($event)
180    {
181
182
183        /**
184         * Run only if the header output was already called
185         */
186        if ($this->headerOutputWasCalled) {
187
188            $snippetManager = PluginUtility::getSnippetManager();
189
190            /**
191             * tags
192             */
193            foreach ($snippetManager->getTags() as $component => $tags) {
194                foreach ($tags as $tagType => $tagRows) {
195                    foreach ($tagRows as $tagRow) {
196                        $class = SnippetManager::getClassFromTag($component);
197                        $event->data .= "<$tagType class=\"$class\"";
198                        foreach ($tagRow as $attributeName => $attributeValue) {
199                            if ($attributeName != "_data") {
200                                $event->data .= " $attributeName=\"$attributeValue\"";
201                            } else {
202                                $content = $attributeValue;
203                            }
204                        }
205                        $event->data .= ">";
206                        if (!empty($content)) {
207                            $event->data .= $content;
208                        }
209                        $event->data .= "</$tagType>";
210                    }
211                }
212            }
213
214            /**
215             * Css
216             */
217            foreach ($snippetManager->getCss() as $component => $snippet) {
218
219                $class = SnippetManager::getClassFromTag($component);
220                $event->data .= "<style class=\"$class\">$snippet</style>" . DOKU_LF;
221
222            }
223
224            /**
225             * Javascript
226             */
227            foreach ($snippetManager->getJavascript() as $component => $snippet) {
228                $class = SnippetManager::getClassFromTag($component);
229                $event->data .= "<script class=\"$class\" type=\"text/javascript\">$snippet</script>" . DOKU_LF;
230            }
231
232            $snippetManager->close();
233
234            /**
235             * Set the value back
236             */
237            $this->headerOutputWasCalled = false;
238
239        }
240
241    }
242
243
244    /**
245     *
246     * @param $event
247     */
248    function barParsed($event)
249    {
250        $data = $event->data;
251        if ($data->mode == "xhtml") {
252
253            /* @var CacheRenderer $data */
254            $page = $data->page;
255            $cached = $event->result;
256            PluginUtility::getSnippetManager()->addBar($page, $cached);
257
258        }
259
260
261    }
262
263
264}
265