1<?php 2 3 4use ComboStrap\CallStack; 5use ComboStrap\PluginUtility; 6use ComboStrap\TagAttributes; 7 8require_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 9 10 11/** 12 * 13 * An iterator to iterate over templates. 14 * 15 * ******************* 16 * Iteration driver 17 * ******************* 18 * The end tag of the template node is driving the iteration. 19 * This way, the tags just after the template 20 * sees them in the {@link CallStack} and can change their context 21 * 22 * For instance, a {@link syntax_plugin_combo_masonry} 23 * component will change the context of all card inside it. 24 * 25 * ******************** 26 * Header and footer delimitation 27 * ******************** 28 * The iterator delimits also the header and footer. 29 * Some component needs the header to be generate completely. 30 * This is the case of a complex markup such as a table 31 * 32 * ****************************** 33 * Delete if no data 34 * ****************************** 35 * It gives also the possibility to {@link syntax_plugin_combo_iterator::EMPTY_ROWS_COUNT_ATTRIBUTE 36 * delete the whole block} 37 * (header and footer also) if there is no data 38 * 39 * ***************************** 40 * Always Contextual 41 * ***************************** 42 * We don't capture the text markup such as in a {@link syntax_plugin_combo_code} 43 * in order to loop because you can't pass the actual handler (ie callstack) 44 * when you {@link p_get_instructions() parse again} a markup. 45 * 46 * The markup is then seen as a new single page without any context. 47 * That may lead to problems. 48 * Example: `heading` may then think that they are `outline heading` ... 49 * 50 */ 51class syntax_plugin_combo_iterator extends DokuWiki_Syntax_Plugin 52{ 53 54 /** 55 * Tag in Dokuwiki cannot have a `-` 56 * This is the last part of the class 57 */ 58 const TAG = "iterator"; 59 60 /** 61 * Page canonical and tag pattern 62 */ 63 const CANONICAL = "iterator"; 64 65 /** 66 * An attribute that is set back 67 * by the {@link DOKU_LEXER_EXIT} state in {@link syntax_plugin_combo_template::handle()} 68 * in order to delete the whole iterator content (ie header, footer) 69 * at the {@link DOKU_LEXER_EXIT} state of {@link syntax_plugin_combo_iterator::handle()} 70 * if there is no rows to iterate 71 */ 72 const EMPTY_ROWS_COUNT_ATTRIBUTE = "emptyRowCount"; 73 74 75 /** 76 * Syntax Type. 77 * 78 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 79 * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 80 * @see DokuWiki_Syntax_Plugin::getType() 81 */ 82 function getType() 83 { 84 return 'container'; 85 } 86 87 /** 88 * How Dokuwiki will add P element 89 * 90 * * 'normal' - The plugin can be used inside paragraphs (inline or inside) 91 * * 'block' - Open paragraphs need to be closed before plugin output (box) - block should not be inside paragraphs 92 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 93 * 94 * @see DokuWiki_Syntax_Plugin::getPType() 95 * @see https://www.dokuwiki.org/devel:syntax_plugins#ptype 96 */ 97 function getPType() 98 { 99 return 'block'; 100 } 101 102 /** 103 * @return array 104 * Allow which kind of plugin inside 105 * 106 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 107 * because we manage self the content and we call self the parser 108 * 109 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 110 */ 111 function getAllowedTypes() 112 { 113 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 114 } 115 116 function getSort() 117 { 118 return 201; 119 } 120 121 public function accepts($mode) 122 { 123 return syntax_plugin_combo_preformatted::disablePreformatted($mode); 124 } 125 126 127 function connectTo($mode) 128 { 129 130 131 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 132 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 133 134 135 } 136 137 138 public function postConnect() 139 { 140 141 $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeFromTag($this->getPluginComponent())); 142 143 144 } 145 146 147 /** 148 * 149 * The handle function goal is to parse the matched syntax through the pattern function 150 * and to return the result for use in the renderer 151 * This result is always cached until the page is modified. 152 * @param string $match 153 * @param int $state 154 * @param int $pos - byte position in the original source file 155 * @param Doku_Handler $handler 156 * @return array|bool 157 * @throws Exception 158 * @see DokuWiki_Syntax_Plugin::handle() 159 * 160 */ 161 function handle($match, $state, $pos, Doku_Handler $handler) 162 { 163 164 switch ($state) { 165 166 case DOKU_LEXER_ENTER : 167 168 $tagAttributes = TagAttributes::createFromTagMatch($match); 169 $callStackArray = $tagAttributes->toCallStackArray(); 170 return array( 171 PluginUtility::STATE => $state, 172 PluginUtility::ATTRIBUTES => $callStackArray 173 ); 174 175 case DOKU_LEXER_UNMATCHED : 176 177 // We should not ever come here but a user does not not known that 178 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 179 180 181 case DOKU_LEXER_EXIT : 182 183 /** 184 * Do we need to delete all call because the data returns no rows 185 */ 186 $callStack = CallStack::createFromHandler($handler); 187 $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 188 if($openingCall->getAttribute(self::EMPTY_ROWS_COUNT_ATTRIBUTE,false)){ 189 $callStack->deleteAllCallsAfter($openingCall); 190 } 191 return array(PluginUtility::STATE => $state); 192 193 } 194 return array(); 195 196 } 197 198 /** 199 * Render the output 200 * @param string $format 201 * @param Doku_Renderer $renderer 202 * @param array $data - what the function handle() return'ed 203 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 204 * @see DokuWiki_Syntax_Plugin::render() 205 * 206 * 207 */ 208 function render($format, Doku_Renderer $renderer, $data) 209 { 210 // unsupported $mode 211 return false; 212 } 213 214 215} 216 217