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