xref: /template/strap/action/snippets.php (revision 977ce05d19d8dab0a70c9a27f8da0b7039299e82)
1<?php
2
3use ComboStrap\CacheManager;
4use ComboStrap\ExceptionCombo;
5use ComboStrap\HtmlDocument;
6use ComboStrap\LogUtility;
7use ComboStrap\Page;
8use ComboStrap\PluginUtility;
9use ComboStrap\RenderUtility;
10use ComboStrap\SnippetManager;
11
12if (!defined('DOKU_INC')) die();
13
14/**
15 *
16 *
17 * Add the snippet needed by the components
18 *
19 */
20class action_plugin_combo_snippets extends DokuWiki_Action_Plugin
21{
22
23    const CLASS_SNIPPET_IN_CONTENT = "snippet-content-combo";
24
25    /**
26     * @var bool - to trace if the header output was called
27     */
28    private $headerOutputWasCalled = false;
29
30    function __construct()
31    {
32        // enable direct access to language strings
33        // ie $this->lang
34        $this->setupLocale();
35    }
36
37    public function register(Doku_Event_Handler $controller)
38    {
39
40        /**
41         * To add the snippets in the header
42         */
43        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array());
44
45        /**
46         * To add the snippets in the content
47         * if they have not been added to the header
48         *
49         * Not https://www.dokuwiki.org/devel:event:tpl_content_display TPL_ACT_RENDER
50         * or https://www.dokuwiki.org/devel:event:tpl_act_render
51         * because it works only for the main content
52         * in {@link tpl_content()}
53         *
54         * We use
55         * https://www.dokuwiki.org/devel:event:renderer_content_postprocess
56         * that is in {@link p_render()} and takes into account also the slot page.
57         */
58        $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'componentSnippetContent', array());
59
60        /**
61         * To reset the value
62         */
63        $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array());
64
65
66    }
67
68    /**
69     * Reset variable
70     * Otherwise in test, when we call it two times, it just fail
71     */
72    function close()
73    {
74
75        $this->headerOutputWasCalled = false;
76
77        /**
78         * Fighting the fact that in 7.2,
79         * there is still a cache
80         */
81        SnippetManager::reset();
82
83    }
84
85    /**
86     * Dokuwiki has already a canonical methodology
87     * https://www.dokuwiki.org/canonical
88     *
89     * @param $event
90     */
91    function componentSnippetHead($event)
92    {
93
94
95        global $ID;
96        if (empty($ID)) {
97
98            global $_SERVER;
99            $scriptName = $_SERVER['SCRIPT_NAME'];
100
101            /**
102             * If this is an ajax call, return
103             * only if this not from webcode
104             */
105            if (strpos($scriptName, "/lib/exe/ajax.php") !== false) {
106                global $_REQUEST;
107                $call = $_REQUEST['call'];
108                if ($call != action_plugin_combo_webcode::CALL_ID) {
109                    return;
110                }
111            } else if (!(strpos($scriptName, "/lib/exe/detail.php") !== false)) {
112                /**
113                 * Image page has an header and footer that may needs snippet
114                 * We return only if this is not a image/detail page
115                 */
116                return;
117            }
118        }
119
120        /**
121         * Advertise that the header output was called
122         * If the user is using another template
123         * than strap that does not put the component snippet
124         * in the head
125         * Used in
126         */
127        $this->headerOutputWasCalled = true;
128
129        $snippetManager = PluginUtility::getSnippetManager();
130
131        /**
132         * For each processed slot in the page, retrieve the snippets
133         */
134        $cacheReporters = CacheManager::getOrCreate()->getCacheResults();
135        if ($cacheReporters !== null) {
136            foreach ($cacheReporters as $cacheReporter) {
137
138                foreach ($cacheReporter->getResults() as $report) {
139
140                    if ($report->getMode() !== HtmlDocument::mode) {
141                        continue;
142                    }
143
144                    $slotId = $report->getSlotId();
145                    Page::createPageFromId($slotId)
146                        ->getHtmlDocument()
147                        ->loadSnippets();
148
149                }
150
151
152            }
153        }
154        /**
155         * Snippets
156         * (Slot and request snippets)
157         */
158        try {
159            $allSnippets = $snippetManager->getAllSnippetsToDokuwikiArray();
160        } catch (ExceptionCombo $e) {
161            LogUtility::msg("Error: We couldn't add the snippets in the head. Error: {$e->getMessage()}");
162            return;
163        }
164        foreach ($allSnippets as $tagType => $tags) {
165
166            foreach ($tags as $tag) {
167                $event->data[$tagType][] = $tag;
168            }
169
170        }
171
172        $snippetManager->close();
173
174    }
175
176    /**
177     * Used if the template does not run the content
178     * before the calling of the header as strap does.
179     *
180     * In this case, the {@link \ComboStrap\SnippetManager::close()} has
181     * not run, and the snippets are still in memory.
182     *
183     * We store them in the HTML and they
184     * follows then the HTML cache of DokuWiki
185     * @param $event
186     */
187    function componentSnippetContent($event)
188    {
189
190        $format = $event->data[0];
191        if ($format !== "xhtml") {
192            return;
193        }
194
195        /**
196         * Add snippet in the content
197         *  - if the header output was already called
198         *  - if this is not a page rendering (ie an admin rendering)
199         * for instance, the upgrade plugin call {@link p_cached_output()} on local file
200         */
201        global $ACT;
202        if ($ACT === RenderUtility::DYNAMIC_RENDERING) {
203            return;
204        }
205        $putSnippetInContent =
206            $this->headerOutputWasCalled
207            ||
208            ($ACT !== "show" && $ACT !== null); // admin page rendering
209        if ($putSnippetInContent) {
210
211            $snippetManager = PluginUtility::getSnippetManager();
212            $xhtmlContent = &$event->data[1];
213            try {
214                $snippets = $snippetManager->getAllSnippetsToDokuwikiArray();
215            } catch (ExceptionCombo $e) {
216                LogUtility::msg("Error: We couldn't add the snippets in the content. Error: {$e->getMessage()}");
217                return;
218            }
219            if (sizeof($snippets) > 0) {
220
221                $class = self::CLASS_SNIPPET_IN_CONTENT;
222                $xhtmlContent .= "<div class=\"$class\">\n";
223                foreach ($snippets as $htmlElement => $tags) {
224
225                    foreach ($tags as $tag) {
226                        $xhtmlContent .= DOKU_LF . "<$htmlElement";
227                        $attributes = "";
228                        $content = null;
229
230                        /**
231                         * This code runs in editing mode
232                         * or if the template is not strap
233                         * No preload is then supported
234                         */
235                        if ($htmlElement === "link") {
236                            $relValue = $tag["rel"];
237                            $relAs = $tag["as"];
238                            if ($relValue === "preload") {
239                                if ($relAs === "style") {
240                                    $tag["rel"] = "stylesheet";
241                                    unset($tag["as"]);
242                                }
243                            }
244                        }
245
246                        /**
247                         * Print
248                         */
249                        foreach ($tag as $attributeName => $attributeValue) {
250                            if ($attributeName !== "_data") {
251                                $attributes .= " $attributeName=\"$attributeValue\"";
252                            } else {
253                                $content = $attributeValue;
254                            }
255                        }
256                        $xhtmlContent .= "$attributes>";
257                        if (!empty($content)) {
258                            $xhtmlContent .= $content;
259                        }
260                        $xhtmlContent .= "</$htmlElement>" . DOKU_LF;
261                    }
262
263                }
264                $xhtmlContent .= "</div>\n";
265
266            }
267
268            $snippetManager->close();
269
270        }
271
272    }
273
274
275}
276