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