1<?php 2/** 3 * DokuWiki Syntax Plugin Combostrap. 4 * 5 */ 6 7use ComboStrap\PluginUtility; 8use ComboStrap\Tag; 9use ComboStrap\TagAttributes; 10 11if (!defined('DOKU_INC')) { 12 die(); 13} 14 15if (!defined('DOKU_PLUGIN')) { 16 define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 17} 18 19require_once(__DIR__ . '/../class/PluginUtility.php'); 20 21/** 22 * All DokuWiki plugins to extend the parser/rendering mechanism 23 * need to inherit from this class 24 * 25 * The name of the class must follow a pattern (don't change it) 26 * ie: 27 * syntax_plugin_PluginName_ComponentName 28 * 29 * https://getbootstrap.com/docs/4.6/components/collapse/#accordion-example 30 * 31 * Ter info: 32 * https://jqueryui.com/accordion/ 33 */ 34class syntax_plugin_combo_accordion extends DokuWiki_Syntax_Plugin 35{ 36 37 38 const TAG = 'accordion'; 39 40 /** 41 * @var int a counter to give an id to the accordion card 42 */ 43 private $accordionCounter = 0; 44 45 /** 46 * Syntax Type. 47 * 48 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 49 * @see DokuWiki_Syntax_Plugin::getType() 50 */ 51 function getType() 52 { 53 return 'container'; 54 } 55 56 /** 57 * @return array 58 * Allow which kind of plugin inside 59 * 60 * One of array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 61 * 'baseonly' will run only in the base mode 62 * because we manage self the content and we call self the parser 63 * 64 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 65 */ 66 public function getAllowedTypes() 67 { 68 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 69 } 70 71 public function accepts($mode) 72 { 73 /** 74 * header mode is disable to take over 75 * and replace it with {@link syntax_plugin_combo_title} 76 */ 77 if ($mode == "header") { 78 return false; 79 } 80 /** 81 * 82 */ 83 return syntax_plugin_combo_preformatted::disablePreformatted($mode); 84 85 } 86 87 /** 88 * How Dokuwiki will add P element 89 * 90 * * 'normal' - The plugin can be used inside paragraphs 91 * * 'block' - Open paragraphs need to be closed before plugin output - 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 */ 96 function getPType() 97 { 98 return 'block'; 99 } 100 101 /** 102 * @see Doku_Parser_Mode::getSort() 103 * Higher number than the teaser-columns 104 * because the mode with the lowest sort number will win out 105 */ 106 function getSort() 107 { 108 return 200; 109 } 110 111 /** 112 * Create a pattern that will called this plugin 113 * 114 * @param string $mode 115 * @see Doku_Parser_Mode::connectTo() 116 */ 117 function connectTo($mode) 118 { 119 120 121 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 122 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 123 124 125 } 126 127 public function postConnect() 128 { 129 130 131 $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent())); 132 133 134 } 135 136 /** 137 * 138 * The handle function goal is to parse the matched syntax through the pattern function 139 * and to return the result for use in the renderer 140 * This result is always cached until the page is modified. 141 * @param string $match 142 * @param int $state 143 * @param int $pos 144 * @param Doku_Handler $handler 145 * @return array|bool 146 * @see DokuWiki_Syntax_Plugin::handle() 147 * 148 */ 149 function handle($match, $state, $pos, Doku_Handler $handler) 150 { 151 152 switch ($state) { 153 154 case DOKU_LEXER_ENTER: 155 156 $this->accordionCounter++; 157 $attributes = PluginUtility::getTagAttributes($match); 158 159 // Attributes has at 160 // https://getbootstrap.com/docs/4.6/components/collapse/#accordion-example 161 PluginUtility::addClass2Attributes("accordion", $attributes); 162 if (!in_array("id", $attributes)) { 163 $attributes["id"] = self::TAG . $this->accordionCounter; 164 } 165 166 return array( 167 PluginUtility::STATE => $state, 168 PluginUtility::ATTRIBUTES => $attributes 169 ); 170 171 case DOKU_LEXER_UNMATCHED : 172 173 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 174 175 176 case DOKU_LEXER_EXIT : 177 178 return array( 179 PluginUtility::STATE => $state 180 ); 181 182 183 } 184 185 return array(); 186 187 } 188 189 /** 190 * Render the output 191 * @param string $format 192 * @param Doku_Renderer $renderer 193 * @param array $data - what the function handle() return'ed 194 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 195 * @see DokuWiki_Syntax_Plugin::render() 196 * 197 * 198 */ 199 function render($format, Doku_Renderer $renderer, $data) 200 { 201 202 if ($format == 'xhtml') { 203 204 /** @var Doku_Renderer_xhtml $renderer */ 205 $state = $data[PluginUtility::STATE]; 206 switch ($state) { 207 case DOKU_LEXER_ENTER: 208 $attributes = TagAttributes::createFromCallStackArray($data[PluginUtility::ATTRIBUTES]); 209 $renderer->doc .= $attributes->toHtmlEnterTag("div") . DOKU_LF; 210 break; 211 case DOKU_LEXER_UNMATCHED: 212 $renderer->doc .= PluginUtility::renderUnmatched($data); 213 break; 214 case DOKU_LEXER_EXIT: 215 $renderer->doc .= '</div>' . DOKU_LF; 216 break; 217 } 218 219 220 return true; 221 } 222 return false; 223 } 224 225 226} 227