xref: /plugin/combo/action/snippets.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
15f891b7eSNickeau<?php
25f891b7eSNickeau
3c3437056SNickeauuse ComboStrap\CacheManager;
4*04fd306cSNickeauuse ComboStrap\ExceptionBadState;
5*04fd306cSNickeauuse ComboStrap\ExceptionNotExists;
6*04fd306cSNickeauuse ComboStrap\ExceptionNotFound;
7*04fd306cSNickeauuse ComboStrap\ExecutionContext;
8*04fd306cSNickeauuse ComboStrap\FetcherMarkup;
95f891b7eSNickeauuse ComboStrap\LogUtility;
105f891b7eSNickeauuse ComboStrap\PluginUtility;
11*04fd306cSNickeauuse ComboStrap\SnippetSystem;
125f891b7eSNickeau
135f891b7eSNickeau
145f891b7eSNickeau/**
155f891b7eSNickeau *
165f891b7eSNickeau *
175f891b7eSNickeau * Add the snippet needed by the components
185f891b7eSNickeau *
195f891b7eSNickeau */
205f891b7eSNickeauclass action_plugin_combo_snippets extends DokuWiki_Action_Plugin
215f891b7eSNickeau{
225f891b7eSNickeau
234cadd4f8SNickeau    const CLASS_SNIPPET_IN_CONTENT = "snippet-content-combo";
244cadd4f8SNickeau
255f891b7eSNickeau    /**
26*04fd306cSNickeau     * To known if we needs to put all snippet in the content
27*04fd306cSNickeau     * or not
285f891b7eSNickeau     */
29*04fd306cSNickeau    const HEAD_EVENT_WAS_CALLED = "head_event_was_called";
30*04fd306cSNickeau    const CANONICAL = "snippets";
31*04fd306cSNickeau
325f891b7eSNickeau
335f891b7eSNickeau    function __construct()
345f891b7eSNickeau    {
355f891b7eSNickeau        // enable direct access to language strings
365f891b7eSNickeau        // ie $this->lang
375f891b7eSNickeau        $this->setupLocale();
385f891b7eSNickeau    }
395f891b7eSNickeau
405f891b7eSNickeau    public function register(Doku_Event_Handler $controller)
415f891b7eSNickeau    {
428aa9d0e6Sgerardnico
4321913ab3SNickeau        /**
4421913ab3SNickeau         * To add the snippets in the header
4521913ab3SNickeau         */
465f891b7eSNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array());
4721913ab3SNickeau
4821913ab3SNickeau        /**
4921913ab3SNickeau         * To add the snippets in the content
5021913ab3SNickeau         * if they have not been added to the header
51531e725cSNickeau         *
52531e725cSNickeau         * Not https://www.dokuwiki.org/devel:event:tpl_content_display TPL_ACT_RENDER
53531e725cSNickeau         * or https://www.dokuwiki.org/devel:event:tpl_act_render
54531e725cSNickeau         * because it works only for the main content
55531e725cSNickeau         * in {@link tpl_content()}
56531e725cSNickeau         *
57531e725cSNickeau         * We use
58531e725cSNickeau         * https://www.dokuwiki.org/devel:event:renderer_content_postprocess
59531e725cSNickeau         * that is in {@link p_render()} and takes into account also the slot page.
6021913ab3SNickeau         */
61531e725cSNickeau        $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'componentSnippetContent', array());
628aa9d0e6Sgerardnico
6321913ab3SNickeau
645f891b7eSNickeau    }
655f891b7eSNickeau
6632b85071SNickeau
6732b85071SNickeau    /**
68*04fd306cSNickeau     *
69*04fd306cSNickeau     * Add the snippets in the head
705f891b7eSNickeau     *
715f891b7eSNickeau     * @param $event
725f891b7eSNickeau     */
735f891b7eSNickeau    function componentSnippetHead($event)
745f891b7eSNickeau    {
755f891b7eSNickeau
76*04fd306cSNickeau        /**
77*04fd306cSNickeau         * Advertise that this event has occurred
78*04fd306cSNickeau         * In a strap template, this event is last because head are added after content rendering
79*04fd306cSNickeau         * In another template, this event is first
80*04fd306cSNickeau         * The function {@link action_plugin_combo_snippets::componentSnippetContent()} used it to determine if
81*04fd306cSNickeau         * the snippets should be added into the content
82*04fd306cSNickeau         */
83*04fd306cSNickeau        ExecutionContext::getActualOrCreateFromEnv()
84*04fd306cSNickeau            ->setRuntimeBoolean(self::HEAD_EVENT_WAS_CALLED, true);
855f891b7eSNickeau
86e8b2ff59SNickeau
87e8b2ff59SNickeau
88e8b2ff59SNickeau        /**
89*04fd306cSNickeau         * For each processed slot in the execution, retrieve the snippets
90e8b2ff59SNickeau         */
91*04fd306cSNickeau        $cacheReporters = CacheManager::getFromContextExecution()->getCacheResults();
924cadd4f8SNickeau        foreach ($cacheReporters as $cacheReporter) {
938aa9d0e6Sgerardnico
944cadd4f8SNickeau            foreach ($cacheReporter->getResults() as $report) {
958aa9d0e6Sgerardnico
96*04fd306cSNickeau                if ($report->getMode() !== FetcherMarkup::XHTML_MODE) {
974cadd4f8SNickeau                    continue;
985f891b7eSNickeau                }
99*04fd306cSNickeau                $markupPath = $report->getMarkupPath();
1004cadd4f8SNickeau                try {
101*04fd306cSNickeau                    $fetcherMarkupForMarkup = $markupPath->createHtmlFetcherWithRequestedPathAsContextPath();
102*04fd306cSNickeau                } catch (ExceptionNotExists $e) {
103*04fd306cSNickeau                    LogUtility::internalError("The executing markup path ($markupPath) should exists because it was executed.");
104*04fd306cSNickeau                    continue;
1054cadd4f8SNickeau                }
106*04fd306cSNickeau                $fetcherMarkupForMarkup->loadSnippets();
107*04fd306cSNickeau            }
10821913ab3SNickeau
109*04fd306cSNickeau        }
110*04fd306cSNickeau
111*04fd306cSNickeau
112*04fd306cSNickeau        $snippetSystem = SnippetSystem::getFromContext();
113*04fd306cSNickeau
114*04fd306cSNickeau        $snippets = $snippetSystem->getSnippets();
115*04fd306cSNickeau        foreach ($snippets as $snippet) {
116*04fd306cSNickeau            /**
117*04fd306cSNickeau             * In a dokuwiki standard template, head is called
118*04fd306cSNickeau             * first, then the content, to not add the snippet in the head and in the content
119*04fd306cSNickeau             * there is an indicator that tracks if the output was asked
120*04fd306cSNickeau             */
121*04fd306cSNickeau            if (!$snippet->hasHtmlOutputAlreadyOccurred()) {
122*04fd306cSNickeau                try {
123*04fd306cSNickeau                    $tag = $snippet->toDokuWikiArray();
124*04fd306cSNickeau                } catch (\Exception $e) {
125*04fd306cSNickeau                    LogUtility::error("We couldn't get the attributes of the snippet ($snippet). It has been skipped. Error: {$e->getMessage()}", self::CANONICAL);
126*04fd306cSNickeau                    continue;
127*04fd306cSNickeau                }
128*04fd306cSNickeau                $tagType = $snippet->getHtmlTag();
12921913ab3SNickeau                $event->data[$tagType][] = $tag;
1305f891b7eSNickeau            }
1315f891b7eSNickeau
1325f891b7eSNickeau        }
1335f891b7eSNickeau
1345f891b7eSNickeau
1355f891b7eSNickeau    }
1365f891b7eSNickeau
1375f891b7eSNickeau    /**
1385f891b7eSNickeau     *
139*04fd306cSNickeau     * This function store the snippets in the HTML content when needed
140*04fd306cSNickeau     * (mostly admin page or any other template than strap ...)
1415f891b7eSNickeau     *
142*04fd306cSNickeau     * This event/function is called first because {@link \ComboStrap\FetcherPage} parse the main markup first (It's the driver)
143*04fd306cSNickeau     *
144*04fd306cSNickeau     * In any other template, they follows the creation of the page, the
145*04fd306cSNickeau     * header are called first, then the content
146*04fd306cSNickeau     *
147*04fd306cSNickeau     *
1485f891b7eSNickeau     * @param $event
1495f891b7eSNickeau     */
1505f891b7eSNickeau    function componentSnippetContent($event)
1515f891b7eSNickeau    {
1525f891b7eSNickeau
1535f891b7eSNickeau        /**
1544cadd4f8SNickeau         * Add snippet in the content
1554cadd4f8SNickeau         *  - if the header output was already called
1564cadd4f8SNickeau         *  - if this is not a page rendering (ie an admin rendering)
1574cadd4f8SNickeau         * for instance, the upgrade plugin call {@link p_cached_output()} on local file
1585f891b7eSNickeau         */
159*04fd306cSNickeau
160*04fd306cSNickeau        /**
161*04fd306cSNickeau         * Dynamic rendering call this event
162*04fd306cSNickeau         * We don't add any component at this moment
163*04fd306cSNickeau         */
1644cadd4f8SNickeau        global $ACT;
165*04fd306cSNickeau        if ($ACT === FetcherMarkup::MARKUP_DYNAMIC_EXECUTION_NAME) {
1664cadd4f8SNickeau            return;
1674cadd4f8SNickeau        }
168*04fd306cSNickeau
169*04fd306cSNickeau
170*04fd306cSNickeau        $format = $event->data[0];
171*04fd306cSNickeau        if ($format !== "xhtml") {
172*04fd306cSNickeau            return;
173*04fd306cSNickeau        }
174*04fd306cSNickeau
175*04fd306cSNickeau        $executionContext = ExecutionContext::getActualOrCreateFromEnv();
176*04fd306cSNickeau
177*04fd306cSNickeau        try {
178*04fd306cSNickeau            $headEventWasCalled = $executionContext->getRuntimeBoolean(self::HEAD_EVENT_WAS_CALLED);
179*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
180*04fd306cSNickeau            $headEventWasCalled = false;
181*04fd306cSNickeau        }
182*04fd306cSNickeau
183*04fd306cSNickeau        /**
184*04fd306cSNickeau         * Put snippet in the content
185*04fd306cSNickeau         * if this is not a show (ie Admin page rendering)
186*04fd306cSNickeau         *
187*04fd306cSNickeau         * And if the header output was already called
188*04fd306cSNickeau         * (case that the template is not strap)
189*04fd306cSNickeau         */
190*04fd306cSNickeau        $putAllSnippetsInContent =
191*04fd306cSNickeau            $headEventWasCalled === true
1924cadd4f8SNickeau            ||
193*04fd306cSNickeau            ($ACT !== "show" && $ACT !== null);
194*04fd306cSNickeau        if (!$putAllSnippetsInContent) {
195*04fd306cSNickeau            return;
196*04fd306cSNickeau        }
1975f891b7eSNickeau
1985f891b7eSNickeau        $snippetManager = PluginUtility::getSnippetManager();
199531e725cSNickeau        $xhtmlContent = &$event->data[1];
200*04fd306cSNickeau        /**
201*04fd306cSNickeau         * What fucked up is fucked up
202*04fd306cSNickeau         *
203*04fd306cSNickeau         * In admin page, as we don't know the source of the processing text
204*04fd306cSNickeau         * (It may be a partial (ie markup) to create the admin page
205*04fd306cSNickeau         * We may have several times the same global request slot
206*04fd306cSNickeau         *
207*04fd306cSNickeau         * We can't make the difference.
208*04fd306cSNickeau         *
209*04fd306cSNickeau         * For now, we add therefore only the snippet for the slots.
210*04fd306cSNickeau         * The snippet for the request should have been already added with the
211*04fd306cSNickeau         * DOKUWIKI_STARTED hook
212*04fd306cSNickeau         */
213*04fd306cSNickeau
214*04fd306cSNickeau        $snippets = $snippetManager->getSnippets();
215*04fd306cSNickeau        if (sizeof($snippets) > 0) {
216*04fd306cSNickeau            $class = self::CLASS_SNIPPET_IN_CONTENT;
217*04fd306cSNickeau            $htmlForSlots = $snippetManager->toHtmlForSlotSnippets();
218*04fd306cSNickeau            if (empty($htmlForSlots)) {
2194cadd4f8SNickeau                return;
2204cadd4f8SNickeau            }
221*04fd306cSNickeau            $htmlForSlotsWrapper = <<<EOF
222*04fd306cSNickeau<div class="$class">
223*04fd306cSNickeau    {$htmlForSlots}
224*04fd306cSNickeau</div>
225*04fd306cSNickeauEOF;
226*04fd306cSNickeau            $xhtmlContent .= $htmlForSlotsWrapper;
2275f891b7eSNickeau
2285f891b7eSNickeau        }
2295f891b7eSNickeau
2305f891b7eSNickeau    }
2315f891b7eSNickeau
2328aa9d0e6Sgerardnico
2335f891b7eSNickeau}
234