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( 145 PluginUtility::STATE => $state, 146 PluginUtility::ATTRIBUTES=> $tagAttributes 147 ); 148 149 case DOKU_LEXER_UNMATCHED : 150 151 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 152 153 154 case DOKU_LEXER_EXIT : 155 156 return array(PluginUtility::STATE => $state); 157 158 159 } 160 161 return array(); 162 163 } 164 165 /** 166 * Render the output 167 * @param string $format 168 * @param Doku_Renderer $renderer 169 * @param array $data - what the function handle() return'ed 170 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 171 * @see DokuWiki_Syntax_Plugin::render() 172 * 173 * 174 */ 175 function render($format, Doku_Renderer $renderer, $data) 176 { 177 $state = $data[PluginUtility::STATE]; 178 switch ($format) { 179 case 'xhtml': 180 /** @var Doku_Renderer_xhtml $renderer */ 181 182 switch ($state) { 183 184 case DOKU_LEXER_ENTER : 185 186 $attributes = $data[PluginUtility::ATTRIBUTES]; 187 188 // The button is the hamburger menu that will be shown 189 $idElementToCollapse = 'navbarcollapse'; 190 $renderer->doc .= '<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#' . $idElementToCollapse . '" aria-controls="' . $idElementToCollapse . '" aria-expanded="false" aria-label="Toggle navigation"'; 191 if (array_key_exists("order", $attributes)) { 192 $renderer->doc .= ' style="order:' . $attributes["order"] . '"'; 193 unset($attributes["order"]); 194 } 195 $renderer->doc .= '>' . DOKU_LF; 196 $renderer->doc .= '<span class="navbar-toggler-icon"></span>' . DOKU_LF; 197 $renderer->doc .= '</button>' . DOKU_LF; 198 199 200 $classValue = "collapse navbar-collapse"; 201 if (array_key_exists("class", $attributes)) { 202 $attributes["class"] .= " {$classValue}"; 203 } else { 204 $attributes["class"] = "{$classValue}"; 205 } 206 $renderer->doc .= '<div id="' . $idElementToCollapse . '" ' . PluginUtility::array2HTMLAttributes($attributes) . '>'; 207 208 // All element below will collapse 209 break; 210 211 case DOKU_LEXER_UNMATCHED: 212 $renderer->doc .= NavBarUtility::text(PluginUtility::renderUnmatched($data)); 213 break; 214 215 216 case DOKU_LEXER_EXIT : 217 218 $renderer->doc .= '</div>' . DOKU_LF; 219 break; 220 } 221 return true; 222 223 } 224 return false; 225 } 226 227 228 public static function getElementName() 229 { 230 return PluginUtility::getTagName(get_called_class()); 231 } 232 233 234} 235