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