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