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