xref: /plugin/combo/syntax/navbarcollapse.php (revision 32b85071e019dd3646a67c17fac4051338e495eb)
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