1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeau 4*04fd306cSNickeauuse ComboStrap\ExceptionNotFound; 5*04fd306cSNickeauuse ComboStrap\ExecutionContext; 6*04fd306cSNickeauuse ComboStrap\FragmentTag; 7*04fd306cSNickeauuse ComboStrap\MarkupCacheDependencies; 8*04fd306cSNickeauuse ComboStrap\CacheManager; 9*04fd306cSNickeauuse ComboStrap\CallStack; 10*04fd306cSNickeauuse ComboStrap\Canonical; 11*04fd306cSNickeauuse ComboStrap\ExceptionCompile; 12*04fd306cSNickeauuse ComboStrap\LogUtility; 13*04fd306cSNickeauuse ComboStrap\MarkupPath; 14*04fd306cSNickeauuse ComboStrap\CreationDate; 15*04fd306cSNickeauuse ComboStrap\PagePath; 16*04fd306cSNickeauuse ComboStrap\PagePublicationDate; 17*04fd306cSNickeauuse ComboStrap\PluginUtility; 18*04fd306cSNickeauuse ComboStrap\MarkupRenderUtility; 19*04fd306cSNickeauuse ComboStrap\ResourceName; 20*04fd306cSNickeauuse ComboStrap\TagAttributes; 21*04fd306cSNickeauuse ComboStrap\XmlTagProcessing; 22*04fd306cSNickeau 23*04fd306cSNickeau 24*04fd306cSNickeaurequire_once(__DIR__ . "/../ComboStrap/PluginUtility.php"); 25*04fd306cSNickeau 26*04fd306cSNickeau/** 27*04fd306cSNickeau * 28*04fd306cSNickeau * Fragment 29*04fd306cSNickeau * 30*04fd306cSNickeau * A fragment is a part of a markup file 31*04fd306cSNickeau * that captures the instructions 32*04fd306cSNickeau * and then render them with {@link \ComboStrap\FetcherMarkup} 33*04fd306cSNickeau * with different {@link \ComboStrap\FetcherMarkupBuilder::setContextData() context data} 34*04fd306cSNickeau * for each page. 35*04fd306cSNickeau * 36*04fd306cSNickeau * It should be used inside an iterator. 37*04fd306cSNickeau * 38*04fd306cSNickeau * 39*04fd306cSNickeau * 40*04fd306cSNickeau */ 41*04fd306cSNickeauclass syntax_plugin_combo_fragment extends DokuWiki_Syntax_Plugin 42*04fd306cSNickeau{ 43*04fd306cSNickeau 44*04fd306cSNickeau 45*04fd306cSNickeau /** 46*04fd306cSNickeau * Syntax Type. 47*04fd306cSNickeau * 48*04fd306cSNickeau * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 49*04fd306cSNickeau * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 50*04fd306cSNickeau * @see DokuWiki_Syntax_Plugin::getType() 51*04fd306cSNickeau */ 52*04fd306cSNickeau function getType(): string 53*04fd306cSNickeau { 54*04fd306cSNickeau return 'formatting'; 55*04fd306cSNickeau } 56*04fd306cSNickeau 57*04fd306cSNickeau /** 58*04fd306cSNickeau * How Dokuwiki will add P element 59*04fd306cSNickeau * 60*04fd306cSNickeau * * 'normal' - Inline 61*04fd306cSNickeau * * 'block' - Block (p are not created inside) 62*04fd306cSNickeau * * 'stack' - Block (p can be created inside) 63*04fd306cSNickeau * 64*04fd306cSNickeau * @see DokuWiki_Syntax_Plugin::getPType() 65*04fd306cSNickeau * @see https://www.dokuwiki.org/devel:syntax_plugins#ptype 66*04fd306cSNickeau */ 67*04fd306cSNickeau function getPType(): string 68*04fd306cSNickeau { 69*04fd306cSNickeau /** 70*04fd306cSNickeau * No P please 71*04fd306cSNickeau */ 72*04fd306cSNickeau return 'normal'; 73*04fd306cSNickeau } 74*04fd306cSNickeau 75*04fd306cSNickeau /** 76*04fd306cSNickeau * @return array 77*04fd306cSNickeau * Allow which kind of plugin inside 78*04fd306cSNickeau * 79*04fd306cSNickeau * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 80*04fd306cSNickeau * because we manage self the content and we call self the parser 81*04fd306cSNickeau * 82*04fd306cSNickeau * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 83*04fd306cSNickeau */ 84*04fd306cSNickeau function getAllowedTypes(): array 85*04fd306cSNickeau { 86*04fd306cSNickeau 87*04fd306cSNickeau return array('baseonly', 'container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 88*04fd306cSNickeau } 89*04fd306cSNickeau 90*04fd306cSNickeau function getSort(): int 91*04fd306cSNickeau { 92*04fd306cSNickeau return 201; 93*04fd306cSNickeau } 94*04fd306cSNickeau 95*04fd306cSNickeau public function accepts($mode) 96*04fd306cSNickeau { 97*04fd306cSNickeau return syntax_plugin_combo_preformatted::disablePreformatted($mode); 98*04fd306cSNickeau } 99*04fd306cSNickeau 100*04fd306cSNickeau 101*04fd306cSNickeau function connectTo($mode) 102*04fd306cSNickeau { 103*04fd306cSNickeau 104*04fd306cSNickeau foreach (FragmentTag::TAGS as $tag) { 105*04fd306cSNickeau $pattern = XmlTagProcessing::getContainerTagPattern($tag); 106*04fd306cSNickeau $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 107*04fd306cSNickeau } 108*04fd306cSNickeau 109*04fd306cSNickeau 110*04fd306cSNickeau } 111*04fd306cSNickeau 112*04fd306cSNickeau 113*04fd306cSNickeau public function postConnect() 114*04fd306cSNickeau { 115*04fd306cSNickeau foreach (FragmentTag::TAGS as $tag) { 116*04fd306cSNickeau $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeFromTag($this->getPluginComponent())); 117*04fd306cSNickeau } 118*04fd306cSNickeau 119*04fd306cSNickeau 120*04fd306cSNickeau } 121*04fd306cSNickeau 122*04fd306cSNickeau 123*04fd306cSNickeau /** 124*04fd306cSNickeau * 125*04fd306cSNickeau * The handle function goal is to parse the matched syntax through the pattern function 126*04fd306cSNickeau * and to return the result for use in the renderer 127*04fd306cSNickeau * This result is always cached until the page is modified. 128*04fd306cSNickeau * @param string $match 129*04fd306cSNickeau * @param int $state 130*04fd306cSNickeau * @param int $pos - byte position in the original source file 131*04fd306cSNickeau * @param Doku_Handler $handler 132*04fd306cSNickeau * @return array 133*04fd306cSNickeau * @throws Exception 134*04fd306cSNickeau * @see DokuWiki_Syntax_Plugin::handle() 135*04fd306cSNickeau * 136*04fd306cSNickeau */ 137*04fd306cSNickeau function handle($match, $state, $pos, Doku_Handler $handler): array 138*04fd306cSNickeau { 139*04fd306cSNickeau 140*04fd306cSNickeau switch ($state) { 141*04fd306cSNickeau 142*04fd306cSNickeau case DOKU_LEXER_ENTER : 143*04fd306cSNickeau 144*04fd306cSNickeau if (substr($match, 1, strlen(FragmentTag::TEMPLATE_TAG)) === FragmentTag::TEMPLATE_TAG) { 145*04fd306cSNickeau LogUtility::warning("The template component has been deprecated and replaced by the fragment component. Why ? Because a whole page is now a template. ", syntax_plugin_combo_iterator::CANONICAL); 146*04fd306cSNickeau } 147*04fd306cSNickeau $tagAttributes = TagAttributes::createFromTagMatch($match); 148*04fd306cSNickeau return array( 149*04fd306cSNickeau PluginUtility::STATE => $state, 150*04fd306cSNickeau PluginUtility::ATTRIBUTES => $tagAttributes->toCallStackArray() 151*04fd306cSNickeau ); 152*04fd306cSNickeau 153*04fd306cSNickeau case DOKU_LEXER_UNMATCHED : 154*04fd306cSNickeau 155*04fd306cSNickeau // We should not ever come here but a user does not not known that 156*04fd306cSNickeau return PluginUtility::handleAndReturnUnmatchedData(FragmentTag::FRAGMENT_TAG, $match, $handler); 157*04fd306cSNickeau 158*04fd306cSNickeau 159*04fd306cSNickeau case DOKU_LEXER_EXIT : 160*04fd306cSNickeau 161*04fd306cSNickeau /** 162*04fd306cSNickeau * Gather template stack 163*04fd306cSNickeau */ 164*04fd306cSNickeau $callStack = CallStack::createFromHandler($handler); 165*04fd306cSNickeau $templateEnterCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 166*04fd306cSNickeau $templateStack = []; 167*04fd306cSNickeau while ($actualCall = $callStack->next()) { 168*04fd306cSNickeau $templateStack[] = $actualCall->toCallArray(); 169*04fd306cSNickeau } 170*04fd306cSNickeau $callStack->deleteAllCallsAfter($templateEnterCall); 171*04fd306cSNickeau 172*04fd306cSNickeau /** 173*04fd306cSNickeau * Cache dependent on the requested page 174*04fd306cSNickeau */ 175*04fd306cSNickeau try { 176*04fd306cSNickeau ExecutionContext::getActualOrCreateFromEnv() 177*04fd306cSNickeau ->getExecutingMarkupHandler() 178*04fd306cSNickeau ->getOutputCacheDependencies() 179*04fd306cSNickeau ->addDependency(MarkupCacheDependencies::REQUESTED_PAGE_DEPENDENCY); 180*04fd306cSNickeau } catch (ExceptionNotFound $e) { 181*04fd306cSNickeau // not a fetcher markup run 182*04fd306cSNickeau } 183*04fd306cSNickeau 184*04fd306cSNickeau 185*04fd306cSNickeau return array( 186*04fd306cSNickeau PluginUtility::STATE => $state, 187*04fd306cSNickeau FragmentTag::CALLSTACK => $templateStack 188*04fd306cSNickeau ); 189*04fd306cSNickeau 190*04fd306cSNickeau 191*04fd306cSNickeau } 192*04fd306cSNickeau return array(); 193*04fd306cSNickeau 194*04fd306cSNickeau } 195*04fd306cSNickeau 196*04fd306cSNickeau /** 197*04fd306cSNickeau * Render the output 198*04fd306cSNickeau * @param string $format 199*04fd306cSNickeau * @param Doku_Renderer $renderer 200*04fd306cSNickeau * @param array $data - what the function handle() return'ed 201*04fd306cSNickeau * @return boolean - rendered correctly? (however, returned value is not used at the moment) 202*04fd306cSNickeau * @throws ExceptionNotFound 203*04fd306cSNickeau * @see DokuWiki_Syntax_Plugin::render() 204*04fd306cSNickeau * 205*04fd306cSNickeau * 206*04fd306cSNickeau */ 207*04fd306cSNickeau function render($format, Doku_Renderer $renderer, $data): bool 208*04fd306cSNickeau { 209*04fd306cSNickeau 210*04fd306cSNickeau if ($format === "xhtml") { 211*04fd306cSNickeau $state = $data[PluginUtility::STATE]; 212*04fd306cSNickeau switch ($state) { 213*04fd306cSNickeau case DOKU_LEXER_UNMATCHED: 214*04fd306cSNickeau $renderer->doc .= PluginUtility::renderUnmatched($data); 215*04fd306cSNickeau return true; 216*04fd306cSNickeau case DOKU_LEXER_EXIT: 217*04fd306cSNickeau $templateStack = $data[FragmentTag::CALLSTACK]; 218*04fd306cSNickeau if ($templateStack === null) { 219*04fd306cSNickeau $renderer->doc .= LogUtility::wrapInRedForHtml("Template instructions should not be null"); 220*04fd306cSNickeau return false; 221*04fd306cSNickeau } 222*04fd306cSNickeau $page = MarkupPath::createFromRequestedPage(); 223*04fd306cSNickeau $metadata = $page->getMetadataForRendering(); 224*04fd306cSNickeau try { 225*04fd306cSNickeau $renderer->doc .= MarkupRenderUtility::renderInstructionsToXhtml($templateStack, $metadata); 226*04fd306cSNickeau } catch (ExceptionCompile $e) { 227*04fd306cSNickeau $renderer->doc .= LogUtility::wrapInRedForHtml("Error while rendering the instruction. Error: {$e->getMessage()}"); 228*04fd306cSNickeau } 229*04fd306cSNickeau LogUtility::warning("There is no need anymore to use a template to render variable", FragmentTag::CANONICAL); 230*04fd306cSNickeau return true; 231*04fd306cSNickeau } 232*04fd306cSNickeau } 233*04fd306cSNickeau return false; 234*04fd306cSNickeau 235*04fd306cSNickeau } 236*04fd306cSNickeau 237*04fd306cSNickeau 238*04fd306cSNickeau} 239*04fd306cSNickeau 240