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