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 /** 58 * We don't accept link as substition 59 * @param string $mode 60 * @return bool 61 */ 62// public function accepts($mode) 63// { 64// $position = strpos($mode, 'link'); 65// if ($position === false){ 66// return parent::accepts($mode); 67// } else { 68// return false; 69// } 70// 71// } 72 73 74 /** 75 * How Dokuwiki will add P element 76 * 77 * * 'normal' - The plugin can be used inside paragraphs 78 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 79 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 80 * 81 * @see DokuWiki_Syntax_Plugin::getPType() 82 */ 83 function getPType() 84 { 85 return 'normal'; 86 } 87 88 /** 89 * @see Doku_Parser_Mode::getSort() 90 * 91 * the mode with the lowest sort number will win out 92 * the container (parent) must then have a lower number than the child 93 */ 94 function getSort() 95 { 96 return 100; 97 } 98 99 /** 100 * Create a pattern that will called this plugin 101 * 102 * @param string $mode 103 * @see Doku_Parser_Mode::connectTo() 104 */ 105 function connectTo($mode) 106 { 107 // Only inside a navbar 108 if ($mode == PluginUtility::getModeForComponent(syntax_plugin_combo_navbar::TAG)) { 109 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 110 $this->Lexer->addEntryPattern($pattern, $mode, 'plugin_' . PluginUtility::PLUGIN_BASE_NAME . '_' . $this->getPluginComponent()); 111 } 112 113 } 114 115 public function postConnect() 116 { 117 118 $this->Lexer->addExitPattern('</' . self::TAG . '>', 'plugin_' . PluginUtility::PLUGIN_BASE_NAME . '_' . $this->getPluginComponent()); 119 120 } 121 122 /** 123 * 124 * The handle function goal is to parse the matched syntax through the pattern function 125 * and to return the result for use in the renderer 126 * This result is always cached until the page is modified. 127 * @param string $match 128 * @param int $state 129 * @param int $pos 130 * @param Doku_Handler $handler 131 * @return array|bool 132 * @see DokuWiki_Syntax_Plugin::handle() 133 * 134 */ 135 function handle($match, $state, $pos, Doku_Handler $handler) 136 { 137 138 switch ($state) { 139 140 case DOKU_LEXER_ENTER: 141 142 $tagAttributes = PluginUtility::getTagAttributes($match); 143 return array($state, $tagAttributes); 144 145 case DOKU_LEXER_UNMATCHED : 146 147 return array($state, $match); 148 149 150 case DOKU_LEXER_EXIT : 151 152 return array($state, ''); 153 154 155 } 156 157 return array(); 158 159 } 160 161 /** 162 * Render the output 163 * @param string $format 164 * @param Doku_Renderer $renderer 165 * @param array $data - what the function handle() return'ed 166 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 167 * @see DokuWiki_Syntax_Plugin::render() 168 * 169 * 170 */ 171 function render($format, Doku_Renderer $renderer, $data) 172 { 173 list($state, $payload) = $data; 174 switch ($format) { 175 case 'xhtml': 176 /** @var Doku_Renderer_xhtml $renderer */ 177 178 switch ($state) { 179 180 case DOKU_LEXER_ENTER : 181 182 $attributes = $payload; 183 184 // The button is the hamburger menu that will be shown 185 $idElementToCollapse = 'navbarcollapse'; 186 $renderer->doc .= '<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#' . $idElementToCollapse . '" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"'; 187 if (array_key_exists("order", $attributes)) { 188 $renderer->doc .= ' style="order:' . $attributes["order"]; 189 unset($attributes["order"]); 190 } 191 $renderer->doc .= '"><span class="navbar-toggler-icon"></span></button>' . DOKU_LF; 192 193 194 $classValue = "collapse navbar-collapse"; 195 if (array_key_exists("class", $attributes)) { 196 $attributes["class"] .= " {$classValue}"; 197 } else { 198 $attributes["class"] = "{$classValue}"; 199 } 200 $renderer->doc .= '<div id="' . $idElementToCollapse . '" '.PluginUtility::array2HTMLAttributes($attributes).'>'; 201 202 // All element below will collapse 203 break; 204 205 case DOKU_LEXER_UNMATCHED: 206 $renderer->doc .= NavBarUtility::text(PluginUtility::escape($payload)); 207 break; 208 209 210 case DOKU_LEXER_EXIT : 211 212 $renderer->doc .= '</div>' . DOKU_LF; 213 break; 214 } 215 return true; 216 217 } 218 return false; 219 } 220 221 222 public static function getElementName() 223 { 224 return PluginUtility::getTagName(get_called_class()); 225 } 226 227 228} 229