1<?php 2/** 3 * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved. 4 * 5 * This source code is licensed under the GPL license found in the 6 * COPYING file in the root directory of this source tree. 7 * 8 * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 9 * @author ComboStrap <support@combostrap.com> 10 * 11 */ 12 13use ComboStrap\HtmlUtility; 14use ComboStrap\LinkUtility; 15use ComboStrap\NavBarUtility; 16use ComboStrap\PluginUtility; 17 18 19require_once(__DIR__ . '/../class/PluginUtility.php'); 20require_once(__DIR__ . '/../class/NavBarUtility.php'); 21 22 23/** 24 * 25 * See https://getbootstrap.com/docs/4.0/components/collapse/ 26 * 27 * The name of the class must follow a pattern (don't change it) ie syntax_plugin_PluginName_ComponentName 28 */ 29class syntax_plugin_combo_navbarcollapse extends DokuWiki_Syntax_Plugin 30{ 31 const TAG = 'collapse'; 32 const COMPONENT = 'navbarcollapse'; 33 34 /** 35 * Syntax Type. 36 * 37 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 38 * @see DokuWiki_Syntax_Plugin::getType() 39 */ 40 function getType() 41 { 42 return 'container'; 43 } 44 45 /** 46 * @return array 47 * Allow which kind of plugin inside 48 * 49 * No one of array('container', 'baseonly', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 50 * because we manage self the content and we call self the parser 51 */ 52 public function getAllowedTypes() 53 { 54 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 55 } 56 57 public function accepts($mode) 58 { 59 $accept = true; 60 61 if (!$this->getConf(syntax_plugin_combo_preformatted::CONF_PREFORMATTED_ENABLE)) { 62 $accept = PluginUtility::disablePreformatted($mode); 63 } 64 65 // P element are not welcome in a navbar 66 if ($mode == "eol") { 67 $accept = false; 68 } 69 70 return $accept; 71 72 } 73 74 75 /** 76 * How Dokuwiki will add P element 77 * 78 * * 'normal' - The plugin can be used inside paragraphs 79 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 80 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 81 * 82 * @see DokuWiki_Syntax_Plugin::getPType() 83 */ 84 function getPType() 85 { 86 return 'normal'; 87 } 88 89 /** 90 * @see Doku_Parser_Mode::getSort() 91 * 92 * the mode with the lowest sort number will win out 93 * the container (parent) must then have a lower number than the child 94 */ 95 function getSort() 96 { 97 return 100; 98 } 99 100 /** 101 * Create a pattern that will called this plugin 102 * 103 * @param string $mode 104 * @see Doku_Parser_Mode::connectTo() 105 */ 106 function connectTo($mode) 107 { 108 // Only inside a navbar 109 if ($mode == PluginUtility::getModeForComponent(syntax_plugin_combo_navbar::TAG)) { 110 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 111 $this->Lexer->addEntryPattern($pattern, $mode, 'plugin_' . PluginUtility::PLUGIN_BASE_NAME . '_' . $this->getPluginComponent()); 112 } 113 114 } 115 116 public function postConnect() 117 { 118 119 $this->Lexer->addExitPattern('</' . self::TAG . '>', 'plugin_' . PluginUtility::PLUGIN_BASE_NAME . '_' . $this->getPluginComponent()); 120 121 } 122 123 /** 124 * 125 * The handle function goal is to parse the matched syntax through the pattern function 126 * and to return the result for use in the renderer 127 * This result is always cached until the page is modified. 128 * @param string $match 129 * @param int $state 130 * @param int $pos 131 * @param Doku_Handler $handler 132 * @return array|bool 133 * @see DokuWiki_Syntax_Plugin::handle() 134 * 135 */ 136 function handle($match, $state, $pos, Doku_Handler $handler) 137 { 138 139 switch ($state) { 140 141 case DOKU_LEXER_ENTER: 142 143 $tagAttributes = PluginUtility::getTagAttributes($match); 144 return array($state, $tagAttributes); 145 146 case DOKU_LEXER_UNMATCHED : 147 148 return array($state, $match); 149 150 151 case DOKU_LEXER_EXIT : 152 153 return array($state, ''); 154 155 156 } 157 158 return array(); 159 160 } 161 162 /** 163 * Render the output 164 * @param string $format 165 * @param Doku_Renderer $renderer 166 * @param array $data - what the function handle() return'ed 167 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 168 * @see DokuWiki_Syntax_Plugin::render() 169 * 170 * 171 */ 172 function render($format, Doku_Renderer $renderer, $data) 173 { 174 list($state, $payload) = $data; 175 switch ($format) { 176 case 'xhtml': 177 /** @var Doku_Renderer_xhtml $renderer */ 178 179 switch ($state) { 180 181 case DOKU_LEXER_ENTER : 182 183 $attributes = $payload; 184 185 // The button is the hamburger menu that will be shown 186 $idElementToCollapse = 'navbarcollapse'; 187 $renderer->doc .= '<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#' . $idElementToCollapse . '" aria-controls="' . $idElementToCollapse . '" aria-expanded="false" aria-label="Toggle navigation"'; 188 if (array_key_exists("order", $attributes)) { 189 $renderer->doc .= ' style="order:' . $attributes["order"] . '"'; 190 unset($attributes["order"]); 191 } 192 $renderer->doc .= '>' . DOKU_LF; 193 $renderer->doc .= '<span class="navbar-toggler-icon"></span>' . DOKU_LF; 194 $renderer->doc .= '</button>' . DOKU_LF; 195 196 197 $classValue = "collapse navbar-collapse"; 198 if (array_key_exists("class", $attributes)) { 199 $attributes["class"] .= " {$classValue}"; 200 } else { 201 $attributes["class"] = "{$classValue}"; 202 } 203 $renderer->doc .= '<div id="' . $idElementToCollapse . '" ' . PluginUtility::array2HTMLAttributes($attributes) . '>'; 204 205 // All element below will collapse 206 break; 207 208 case DOKU_LEXER_UNMATCHED: 209 $renderer->doc .= NavBarUtility::text(PluginUtility::escape($payload)); 210 break; 211 212 213 case DOKU_LEXER_EXIT : 214 215 $renderer->doc .= '</div>' . DOKU_LF; 216 break; 217 } 218 return true; 219 220 } 221 return false; 222 } 223 224 225 public static function getElementName() 226 { 227 return PluginUtility::getTagName(get_called_class()); 228 } 229 230 231} 232