xref: /plugin/combo/action/snippets.php (revision 531e725cdb5a652164f2d97f556304e31f720033)
15f891b7eSNickeau<?php
25f891b7eSNickeau
3654a02feSgerardnicouse ComboStrap\DokuPath;
45f891b7eSNickeauuse ComboStrap\LogUtility;
55f891b7eSNickeauuse ComboStrap\PluginUtility;
6654a02feSgerardnicouse ComboStrap\Resources;
78aa9d0e6Sgerardnicouse ComboStrap\Site;
88aa9d0e6Sgerardnicouse dokuwiki\Cache\CacheRenderer;
95f891b7eSNickeau
105f891b7eSNickeauif (!defined('DOKU_INC')) die();
115f891b7eSNickeau
125f891b7eSNickeau/**
135f891b7eSNickeau *
145f891b7eSNickeau *
155f891b7eSNickeau * Add the snippet needed by the components
165f891b7eSNickeau *
175f891b7eSNickeau */
185f891b7eSNickeauclass action_plugin_combo_snippets extends DokuWiki_Action_Plugin
195f891b7eSNickeau{
205f891b7eSNickeau
218aa9d0e6Sgerardnico    const COMBO_CACHE_PREFIX = "combo:cache:";
225f891b7eSNickeau
235f891b7eSNickeau    /**
245f891b7eSNickeau     * @var bool - to trace if the header output was called
255f891b7eSNickeau     */
265f891b7eSNickeau    private $headerOutputWasCalled = false;
275f891b7eSNickeau
285f891b7eSNickeau    function __construct()
295f891b7eSNickeau    {
305f891b7eSNickeau        // enable direct access to language strings
315f891b7eSNickeau        // ie $this->lang
325f891b7eSNickeau        $this->setupLocale();
335f891b7eSNickeau    }
345f891b7eSNickeau
355f891b7eSNickeau    public function register(Doku_Event_Handler $controller)
365f891b7eSNickeau    {
378aa9d0e6Sgerardnico
3821913ab3SNickeau        /**
3921913ab3SNickeau         * To add the snippets in the header
4021913ab3SNickeau         */
415f891b7eSNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array());
4221913ab3SNickeau
4321913ab3SNickeau        /**
4421913ab3SNickeau         * To add the snippets in the content
4521913ab3SNickeau         * if they have not been added to the header
46*531e725cSNickeau         *
47*531e725cSNickeau         * Not https://www.dokuwiki.org/devel:event:tpl_content_display TPL_ACT_RENDER
48*531e725cSNickeau         * or https://www.dokuwiki.org/devel:event:tpl_act_render
49*531e725cSNickeau         * because it works only for the main content
50*531e725cSNickeau         * in {@link tpl_content()}
51*531e725cSNickeau         *
52*531e725cSNickeau         * We use
53*531e725cSNickeau         * https://www.dokuwiki.org/devel:event:renderer_content_postprocess
54*531e725cSNickeau         * that is in {@link p_render()} and takes into account also the slot page.
5521913ab3SNickeau         */
56*531e725cSNickeau        $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'componentSnippetContent', array());
578aa9d0e6Sgerardnico
5821913ab3SNickeau        /**
5921913ab3SNickeau         * To reset the value
6021913ab3SNickeau         */
6121913ab3SNickeau        $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array());
628aa9d0e6Sgerardnico
6321913ab3SNickeau
6421913ab3SNickeau        /**
6521913ab3SNickeau         * To log the cache used by bar
6621913ab3SNickeau         */
678aa9d0e6Sgerardnico        $controller->register_hook('PARSER_CACHE_USE', 'AFTER', $this, 'barParsed', array());
688aa9d0e6Sgerardnico
695f891b7eSNickeau    }
705f891b7eSNickeau
715f891b7eSNickeau    /**
7232b85071SNickeau     * Reset variable
7332b85071SNickeau     * Otherwise in test, when we call it two times, it just fail
7432b85071SNickeau     */
7521913ab3SNickeau    function close()
7621913ab3SNickeau    {
7732b85071SNickeau
7832b85071SNickeau        $this->headerOutputWasCalled = false;
7932b85071SNickeau
8032b85071SNickeau        /**
8132b85071SNickeau         * Fighting the fact that in 7.2,
8232b85071SNickeau         * there is still a cache
8332b85071SNickeau         */
8432b85071SNickeau        PluginUtility::initSnippetManager();
8532b85071SNickeau
8632b85071SNickeau    }
8732b85071SNickeau
8832b85071SNickeau    /**
895f891b7eSNickeau     * Dokuwiki has already a canonical methodology
905f891b7eSNickeau     * https://www.dokuwiki.org/canonical
915f891b7eSNickeau     *
925f891b7eSNickeau     * @param $event
935f891b7eSNickeau     */
945f891b7eSNickeau    function componentSnippetHead($event)
955f891b7eSNickeau    {
965f891b7eSNickeau
975f891b7eSNickeau
985f891b7eSNickeau        global $ID;
995f891b7eSNickeau        if (empty($ID)) {
10021913ab3SNickeau            global $_SERVER;
10121913ab3SNickeau            $requestUri = $_SERVER['REQUEST_URI'];
10221913ab3SNickeau            if (!strpos($requestUri, "/lib/exe/ajax.php") !== false) {
10321913ab3SNickeau                global $_REQUEST;
10421913ab3SNickeau                $call = $_REQUEST['call'];
10521913ab3SNickeau                if ($call != action_plugin_combo_webcode::CALL_ID) {
1065f891b7eSNickeau                    return;
1075f891b7eSNickeau                }
10821913ab3SNickeau            }
10921913ab3SNickeau        }
1105f891b7eSNickeau
1115f891b7eSNickeau        /**
1125f891b7eSNickeau         * Advertise that the header output was called
1135f891b7eSNickeau         * If the user is using another template
1145f891b7eSNickeau         * than strap that does not put the component snippet
1155f891b7eSNickeau         * in the head
1165f891b7eSNickeau         * Used in
1175f891b7eSNickeau         */
1185f891b7eSNickeau        $this->headerOutputWasCalled = true;
1195f891b7eSNickeau
1205f891b7eSNickeau        $snippetManager = PluginUtility::getSnippetManager();
1215f891b7eSNickeau
1225f891b7eSNickeau        /**
1238aa9d0e6Sgerardnico         * For each processed bar in the page
1248aa9d0e6Sgerardnico         *   * retrieve the snippets from the cache or store the process one
1258aa9d0e6Sgerardnico         *   * add the cache information in meta
1265f891b7eSNickeau         */
1278aa9d0e6Sgerardnico        $bars = $snippetManager->getBarsOfPage();
128654a02feSgerardnico        foreach ($bars as $barId => $servedFromCache) {
1298aa9d0e6Sgerardnico
13021913ab3SNickeau            // Add cache information into the head meta
131e957c58cSgerardnico            // to test
132654a02feSgerardnico            $event->data["meta"][] = array("name" => self::COMBO_CACHE_PREFIX . $barId, "content" => var_export($servedFromCache, true));
1338aa9d0e6Sgerardnico
1348aa9d0e6Sgerardnico            // Get or store the data
135654a02feSgerardnico            $cache = new \dokuwiki\Cache\Cache($barId, "snippet");
136654a02feSgerardnico            $barFileSystemPath = DokuPath::createPagePathFromPath(DokuPath::SEPARATOR . $barId)->getFileSystemPath();
137654a02feSgerardnico            $dependencies = array(
138654a02feSgerardnico                "files" => [
139654a02feSgerardnico                    $barFileSystemPath,
140654a02feSgerardnico                    Resources::getComboHome() . "/plugin.info.txt"
141654a02feSgerardnico                ]
142654a02feSgerardnico            );
1438aa9d0e6Sgerardnico
1448aa9d0e6Sgerardnico            // if the bar was served from the cache
145654a02feSgerardnico            if ($servedFromCache && $cache->useCache($dependencies)) {
1468aa9d0e6Sgerardnico
14721913ab3SNickeau                // Retrieve snippets from previous run
1485f891b7eSNickeau                $data = $cache->retrieveCache();
1498aa9d0e6Sgerardnico
1505f891b7eSNickeau                if (!empty($data)) {
1518aa9d0e6Sgerardnico                    $snippets = unserialize($data);
152654a02feSgerardnico                    $snippetManager->addSnippetsFromCacheForBar($barId, $snippets);
1538aa9d0e6Sgerardnico
1548aa9d0e6Sgerardnico                    if (Site::debugIsOn()) {
1558aa9d0e6Sgerardnico                        LogUtility::log2file("Snippet cache file {$cache->cache} used", LogUtility::LVL_MSG_DEBUG);
1568aa9d0e6Sgerardnico                        $event->data['script'][] = array(
1578aa9d0e6Sgerardnico                            "type" => "application/json",
1588aa9d0e6Sgerardnico                            "_data" => json_encode($snippets),
159654a02feSgerardnico                            "class" => "combo-snippet-cache-" . str_replace(":", "-", $barId));
1605f891b7eSNickeau                    }
161d2ffcff9Sgerardnico
1628aa9d0e6Sgerardnico                }
1638aa9d0e6Sgerardnico            } else {
164654a02feSgerardnico                $snippets = $snippetManager->getSnippetsForBar($barId);
1658aa9d0e6Sgerardnico                if (!empty($snippets)) {
1668aa9d0e6Sgerardnico                    $cache->storeCache(serialize($snippets));
1678aa9d0e6Sgerardnico                }
1688aa9d0e6Sgerardnico            }
1695f891b7eSNickeau
1708aa9d0e6Sgerardnico        }
1715f891b7eSNickeau
1725f891b7eSNickeau        /**
17321913ab3SNickeau         * Snippets
1745f891b7eSNickeau         */
17521913ab3SNickeau        foreach ($snippetManager->getSnippets() as $tagType => $tags) {
17621913ab3SNickeau
17721913ab3SNickeau            foreach ($tags as $tag) {
17821913ab3SNickeau                $event->data[$tagType][] = $tag;
1795f891b7eSNickeau            }
1805f891b7eSNickeau
1815f891b7eSNickeau        }
1825f891b7eSNickeau
1835f891b7eSNickeau
1845f891b7eSNickeau        $snippetManager->close();
1855f891b7eSNickeau
1865f891b7eSNickeau    }
1875f891b7eSNickeau
1885f891b7eSNickeau    /**
1895f891b7eSNickeau     * Used if the template does not run the content
1905f891b7eSNickeau     * before the calling of the header as strap does.
1915f891b7eSNickeau     *
1925f891b7eSNickeau     * In this case, the {@link \ComboStrap\SnippetManager::close()} has
1935f891b7eSNickeau     * not run, and the snippets are still in memory.
1945f891b7eSNickeau     *
1955f891b7eSNickeau     * We store them in the HTML and they
1965f891b7eSNickeau     * follows then the HTML cache of DokuWiki
1975f891b7eSNickeau     * @param $event
1985f891b7eSNickeau     */
1995f891b7eSNickeau    function componentSnippetContent($event)
2005f891b7eSNickeau    {
2015f891b7eSNickeau
202*531e725cSNickeau        $format = $event->data[0];
203*531e725cSNickeau        if($format!=="xhtml"){
204*531e725cSNickeau            return;
205*531e725cSNickeau        }
2065f891b7eSNickeau
2075f891b7eSNickeau        /**
2085f891b7eSNickeau         * Run only if the header output was already called
2095f891b7eSNickeau         */
2105f891b7eSNickeau        if ($this->headerOutputWasCalled) {
2115f891b7eSNickeau
2125f891b7eSNickeau            $snippetManager = PluginUtility::getSnippetManager();
2135f891b7eSNickeau
214*531e725cSNickeau            $xhtmlContent = &$event->data[1];
215*531e725cSNickeau            $snippets = $snippetManager->getSnippets();
216*531e725cSNickeau            foreach ($snippets as $tagType => $tags) {
21721913ab3SNickeau
21821913ab3SNickeau                foreach ($tags as $tag) {
219*531e725cSNickeau                    $xhtmlContent .= DOKU_LF . "<$tagType";
22021913ab3SNickeau                    $attributes = "";
22121913ab3SNickeau                    $content = null;
22221913ab3SNickeau                    foreach ($tag as $attributeName => $attributeValue) {
2235f891b7eSNickeau                        if ($attributeName != "_data") {
22421913ab3SNickeau                            $attributes .= " $attributeName=\"$attributeValue\"";
2255f891b7eSNickeau                        } else {
2265f891b7eSNickeau                            $content = $attributeValue;
2275f891b7eSNickeau                        }
2285f891b7eSNickeau                    }
229*531e725cSNickeau                    $xhtmlContent .= "$attributes>";
2305f891b7eSNickeau                    if (!empty($content)) {
231*531e725cSNickeau                        $xhtmlContent .= $content;
2325f891b7eSNickeau                    }
233*531e725cSNickeau                    $xhtmlContent .= "</$tagType>" . DOKU_LF;
2345f891b7eSNickeau                }
2355f891b7eSNickeau
2365f891b7eSNickeau            }
2375f891b7eSNickeau
2385f891b7eSNickeau            $snippetManager->close();
2395f891b7eSNickeau
2405f891b7eSNickeau        }
2415f891b7eSNickeau
2425f891b7eSNickeau    }
2435f891b7eSNickeau
2448aa9d0e6Sgerardnico
2455f891b7eSNickeau    /**
2468aa9d0e6Sgerardnico     *
2478aa9d0e6Sgerardnico     * @param $event
2485f891b7eSNickeau     */
2498aa9d0e6Sgerardnico    function barParsed($event)
2505f891b7eSNickeau    {
2518aa9d0e6Sgerardnico        $data = $event->data;
2528aa9d0e6Sgerardnico        if ($data->mode == "xhtml") {
2535f891b7eSNickeau
2548aa9d0e6Sgerardnico            /* @var CacheRenderer $data */
255654a02feSgerardnico            $pageId = $data->page;
2568aa9d0e6Sgerardnico            $cached = $event->result;
257654a02feSgerardnico            PluginUtility::getSnippetManager()->addBar($pageId, $cached);
2585f891b7eSNickeau
2595f891b7eSNickeau        }
2605f891b7eSNickeau
2618aa9d0e6Sgerardnico
2628aa9d0e6Sgerardnico    }
2635f891b7eSNickeau
2645f891b7eSNickeau
2655f891b7eSNickeau}
266