15f891b7eSNickeau<?php 25f891b7eSNickeau 3c3437056SNickeauuse ComboStrap\CacheManager; 4c3437056SNickeauuse ComboStrap\ExceptionCombo; 5*4cadd4f8SNickeauuse ComboStrap\HtmlDocument; 65f891b7eSNickeauuse ComboStrap\LogUtility; 7*4cadd4f8SNickeauuse ComboStrap\Page; 85f891b7eSNickeauuse ComboStrap\PluginUtility; 9*4cadd4f8SNickeauuse ComboStrap\RenderUtility; 10c3437056SNickeauuse ComboStrap\SnippetManager; 115f891b7eSNickeau 125f891b7eSNickeauif (!defined('DOKU_INC')) die(); 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 23*4cadd4f8SNickeau const CLASS_SNIPPET_IN_CONTENT = "snippet-content-combo"; 24*4cadd4f8SNickeau 255f891b7eSNickeau /** 265f891b7eSNickeau * @var bool - to trace if the header output was called 275f891b7eSNickeau */ 285f891b7eSNickeau private $headerOutputWasCalled = false; 295f891b7eSNickeau 305f891b7eSNickeau function __construct() 315f891b7eSNickeau { 325f891b7eSNickeau // enable direct access to language strings 335f891b7eSNickeau // ie $this->lang 345f891b7eSNickeau $this->setupLocale(); 355f891b7eSNickeau } 365f891b7eSNickeau 375f891b7eSNickeau public function register(Doku_Event_Handler $controller) 385f891b7eSNickeau { 398aa9d0e6Sgerardnico 4021913ab3SNickeau /** 4121913ab3SNickeau * To add the snippets in the header 4221913ab3SNickeau */ 435f891b7eSNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'componentSnippetHead', array()); 4421913ab3SNickeau 4521913ab3SNickeau /** 4621913ab3SNickeau * To add the snippets in the content 4721913ab3SNickeau * if they have not been added to the header 48531e725cSNickeau * 49531e725cSNickeau * Not https://www.dokuwiki.org/devel:event:tpl_content_display TPL_ACT_RENDER 50531e725cSNickeau * or https://www.dokuwiki.org/devel:event:tpl_act_render 51531e725cSNickeau * because it works only for the main content 52531e725cSNickeau * in {@link tpl_content()} 53531e725cSNickeau * 54531e725cSNickeau * We use 55531e725cSNickeau * https://www.dokuwiki.org/devel:event:renderer_content_postprocess 56531e725cSNickeau * that is in {@link p_render()} and takes into account also the slot page. 5721913ab3SNickeau */ 58531e725cSNickeau $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'componentSnippetContent', array()); 598aa9d0e6Sgerardnico 6021913ab3SNickeau /** 6121913ab3SNickeau * To reset the value 6221913ab3SNickeau */ 6321913ab3SNickeau $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'close', array()); 648aa9d0e6Sgerardnico 6521913ab3SNickeau 665f891b7eSNickeau } 675f891b7eSNickeau 685f891b7eSNickeau /** 6932b85071SNickeau * Reset variable 7032b85071SNickeau * Otherwise in test, when we call it two times, it just fail 7132b85071SNickeau */ 7221913ab3SNickeau function close() 7321913ab3SNickeau { 7432b85071SNickeau 7532b85071SNickeau $this->headerOutputWasCalled = false; 7632b85071SNickeau 7732b85071SNickeau /** 7832b85071SNickeau * Fighting the fact that in 7.2, 7932b85071SNickeau * there is still a cache 8032b85071SNickeau */ 81*4cadd4f8SNickeau SnippetManager::reset(); 8232b85071SNickeau 8332b85071SNickeau } 8432b85071SNickeau 8532b85071SNickeau /** 865f891b7eSNickeau * Dokuwiki has already a canonical methodology 875f891b7eSNickeau * https://www.dokuwiki.org/canonical 885f891b7eSNickeau * 895f891b7eSNickeau * @param $event 905f891b7eSNickeau */ 915f891b7eSNickeau function componentSnippetHead($event) 925f891b7eSNickeau { 935f891b7eSNickeau 945f891b7eSNickeau 955f891b7eSNickeau global $ID; 965f891b7eSNickeau if (empty($ID)) { 97e8b2ff59SNickeau 9821913ab3SNickeau global $_SERVER; 99e8b2ff59SNickeau $scriptName = $_SERVER['SCRIPT_NAME']; 100e8b2ff59SNickeau 101e8b2ff59SNickeau /** 102e8b2ff59SNickeau * If this is an ajax call, return 103e8b2ff59SNickeau * only if this not from webcode 104e8b2ff59SNickeau */ 105e8b2ff59SNickeau if (strpos($scriptName, "/lib/exe/ajax.php") !== false) { 10621913ab3SNickeau global $_REQUEST; 10721913ab3SNickeau $call = $_REQUEST['call']; 10821913ab3SNickeau if ($call != action_plugin_combo_webcode::CALL_ID) { 1095f891b7eSNickeau return; 1105f891b7eSNickeau } 111e8b2ff59SNickeau } else if (!(strpos($scriptName, "/lib/exe/detail.php") !== false)) { 112e8b2ff59SNickeau /** 113e8b2ff59SNickeau * Image page has an header and footer that may needs snippet 114e8b2ff59SNickeau * We return only if this is not a image/detail page 115e8b2ff59SNickeau */ 116e8b2ff59SNickeau return; 11721913ab3SNickeau } 11821913ab3SNickeau } 1195f891b7eSNickeau 1205f891b7eSNickeau /** 1215f891b7eSNickeau * Advertise that the header output was called 1225f891b7eSNickeau * If the user is using another template 1235f891b7eSNickeau * than strap that does not put the component snippet 1245f891b7eSNickeau * in the head 1255f891b7eSNickeau * Used in 1265f891b7eSNickeau */ 1275f891b7eSNickeau $this->headerOutputWasCalled = true; 1285f891b7eSNickeau 1295f891b7eSNickeau $snippetManager = PluginUtility::getSnippetManager(); 1305f891b7eSNickeau 1315f891b7eSNickeau /** 132*4cadd4f8SNickeau * For each processed slot in the page, retrieve the snippets 1335f891b7eSNickeau */ 134*4cadd4f8SNickeau $cacheReporters = CacheManager::getOrCreate()->getCacheResults(); 135*4cadd4f8SNickeau if ($cacheReporters !== null) { 136*4cadd4f8SNickeau foreach ($cacheReporters as $cacheReporter) { 1378aa9d0e6Sgerardnico 138*4cadd4f8SNickeau foreach ($cacheReporter->getResults() as $report) { 1398aa9d0e6Sgerardnico 140*4cadd4f8SNickeau if ($report->getMode() !== HtmlDocument::mode) { 141*4cadd4f8SNickeau continue; 1425f891b7eSNickeau } 143*4cadd4f8SNickeau 144*4cadd4f8SNickeau $slotId = $report->getSlotId(); 145*4cadd4f8SNickeau Page::createPageFromId($slotId) 146*4cadd4f8SNickeau ->getHtmlDocument() 147*4cadd4f8SNickeau ->loadSnippets(); 148d2ffcff9Sgerardnico 1498aa9d0e6Sgerardnico } 150c3437056SNickeau 1515f891b7eSNickeau 1528aa9d0e6Sgerardnico } 153*4cadd4f8SNickeau } 1545f891b7eSNickeau /** 15521913ab3SNickeau * Snippets 156*4cadd4f8SNickeau * (Slot and request snippets) 1575f891b7eSNickeau */ 158*4cadd4f8SNickeau try { 159*4cadd4f8SNickeau $allSnippets = $snippetManager->getAllSnippetsToDokuwikiArray(); 160*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 161*4cadd4f8SNickeau LogUtility::msg("Error: We couldn't add the snippets in the head. Error: {$e->getMessage()}"); 162*4cadd4f8SNickeau return; 163*4cadd4f8SNickeau } 164c3437056SNickeau foreach ($allSnippets as $tagType => $tags) { 16521913ab3SNickeau 16621913ab3SNickeau foreach ($tags as $tag) { 16721913ab3SNickeau $event->data[$tagType][] = $tag; 1685f891b7eSNickeau } 1695f891b7eSNickeau 1705f891b7eSNickeau } 1715f891b7eSNickeau 1725f891b7eSNickeau $snippetManager->close(); 1735f891b7eSNickeau 1745f891b7eSNickeau } 1755f891b7eSNickeau 1765f891b7eSNickeau /** 1775f891b7eSNickeau * Used if the template does not run the content 1785f891b7eSNickeau * before the calling of the header as strap does. 1795f891b7eSNickeau * 1805f891b7eSNickeau * In this case, the {@link \ComboStrap\SnippetManager::close()} has 1815f891b7eSNickeau * not run, and the snippets are still in memory. 1825f891b7eSNickeau * 1835f891b7eSNickeau * We store them in the HTML and they 1845f891b7eSNickeau * follows then the HTML cache of DokuWiki 1855f891b7eSNickeau * @param $event 1865f891b7eSNickeau */ 1875f891b7eSNickeau function componentSnippetContent($event) 1885f891b7eSNickeau { 1895f891b7eSNickeau 190531e725cSNickeau $format = $event->data[0]; 191531e725cSNickeau if ($format !== "xhtml") { 192531e725cSNickeau return; 193531e725cSNickeau } 1945f891b7eSNickeau 1955f891b7eSNickeau /** 196*4cadd4f8SNickeau * Add snippet in the content 197*4cadd4f8SNickeau * - if the header output was already called 198*4cadd4f8SNickeau * - if this is not a page rendering (ie an admin rendering) 199*4cadd4f8SNickeau * for instance, the upgrade plugin call {@link p_cached_output()} on local file 2005f891b7eSNickeau */ 201*4cadd4f8SNickeau global $ACT; 202*4cadd4f8SNickeau if ($ACT === RenderUtility::DYNAMIC_RENDERING) { 203*4cadd4f8SNickeau return; 204*4cadd4f8SNickeau } 205*4cadd4f8SNickeau $putSnippetInContent = 206*4cadd4f8SNickeau $this->headerOutputWasCalled 207*4cadd4f8SNickeau || 208*4cadd4f8SNickeau ($ACT !== "show" && $ACT !== null); // admin page rendering 209*4cadd4f8SNickeau if ($putSnippetInContent) { 2105f891b7eSNickeau 2115f891b7eSNickeau $snippetManager = PluginUtility::getSnippetManager(); 212531e725cSNickeau $xhtmlContent = &$event->data[1]; 213*4cadd4f8SNickeau try { 214*4cadd4f8SNickeau $snippets = $snippetManager->getAllSnippetsToDokuwikiArray(); 215*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 216*4cadd4f8SNickeau LogUtility::msg("Error: We couldn't add the snippets in the content. Error: {$e->getMessage()}"); 217*4cadd4f8SNickeau return; 218*4cadd4f8SNickeau } 219*4cadd4f8SNickeau if (sizeof($snippets) > 0) { 220*4cadd4f8SNickeau 221*4cadd4f8SNickeau $class = self::CLASS_SNIPPET_IN_CONTENT; 222*4cadd4f8SNickeau $xhtmlContent .= "<div class=\"$class\">\n"; 223*4cadd4f8SNickeau foreach ($snippets as $htmlElement => $tags) { 22421913ab3SNickeau 22521913ab3SNickeau foreach ($tags as $tag) { 226*4cadd4f8SNickeau $xhtmlContent .= DOKU_LF . "<$htmlElement"; 22721913ab3SNickeau $attributes = ""; 22821913ab3SNickeau $content = null; 229*4cadd4f8SNickeau 230*4cadd4f8SNickeau /** 231*4cadd4f8SNickeau * This code runs in editing mode 232*4cadd4f8SNickeau * or if the template is not strap 233*4cadd4f8SNickeau * No preload is then supported 234*4cadd4f8SNickeau */ 235*4cadd4f8SNickeau if ($htmlElement === "link") { 236*4cadd4f8SNickeau $relValue = $tag["rel"]; 237*4cadd4f8SNickeau $relAs = $tag["as"]; 238*4cadd4f8SNickeau if ($relValue === "preload") { 239*4cadd4f8SNickeau if ($relAs === "style") { 240*4cadd4f8SNickeau $tag["rel"] = "stylesheet"; 241*4cadd4f8SNickeau unset($tag["as"]); 242*4cadd4f8SNickeau } 243*4cadd4f8SNickeau } 244*4cadd4f8SNickeau } 245*4cadd4f8SNickeau 246*4cadd4f8SNickeau /** 247*4cadd4f8SNickeau * Print 248*4cadd4f8SNickeau */ 24921913ab3SNickeau foreach ($tag as $attributeName => $attributeValue) { 250*4cadd4f8SNickeau if ($attributeName !== "_data") { 25121913ab3SNickeau $attributes .= " $attributeName=\"$attributeValue\""; 2525f891b7eSNickeau } else { 2535f891b7eSNickeau $content = $attributeValue; 2545f891b7eSNickeau } 2555f891b7eSNickeau } 256531e725cSNickeau $xhtmlContent .= "$attributes>"; 2575f891b7eSNickeau if (!empty($content)) { 258531e725cSNickeau $xhtmlContent .= $content; 2595f891b7eSNickeau } 260*4cadd4f8SNickeau $xhtmlContent .= "</$htmlElement>" . DOKU_LF; 2615f891b7eSNickeau } 2625f891b7eSNickeau 2635f891b7eSNickeau } 264*4cadd4f8SNickeau $xhtmlContent .= "</div>\n"; 265*4cadd4f8SNickeau 266*4cadd4f8SNickeau } 2675f891b7eSNickeau 2685f891b7eSNickeau $snippetManager->close(); 2695f891b7eSNickeau 2705f891b7eSNickeau } 2715f891b7eSNickeau 2725f891b7eSNickeau } 2735f891b7eSNickeau 2748aa9d0e6Sgerardnico 2755f891b7eSNickeau} 276