xref: /plugin/combo/syntax/navbarcollapse.php (revision 722648ea66ebf5492a297f883b2890d60f7e9bfa)
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            $this->Lexer->addPattern(LinkUtility::LINK_PATTERN, PluginUtility::getModeForComponent($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            case DOKU_LEXER_MATCHED:
151
152                $linkAttributes = LinkUtility::getAttributes($match);
153                return array($state, $linkAttributes);
154
155            case DOKU_LEXER_EXIT :
156
157                return array($state, '');
158
159
160        }
161
162        return array();
163
164    }
165
166    /**
167     * Render the output
168     * @param string $format
169     * @param Doku_Renderer $renderer
170     * @param array $data - what the function handle() return'ed
171     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
172     * @see DokuWiki_Syntax_Plugin::render()
173     *
174     *
175     */
176    function render($format, Doku_Renderer $renderer, $data)
177    {
178        list($state, $payload) = $data;
179        switch ($format) {
180            case 'xhtml':
181                /** @var Doku_Renderer_xhtml $renderer */
182
183                switch ($state) {
184
185                    case DOKU_LEXER_ENTER :
186
187                        $attributes = $payload;
188
189                        // The button is the hamburger menu that will be shown
190                        $idElementToCollapse = 'navbarcollapse';
191                        $renderer->doc .= '<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#' . $idElementToCollapse . '" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation"';
192                        if (array_key_exists("order", $attributes)) {
193                            $renderer->doc .= ' style="order:' . $attributes["order"];
194                            unset($attributes["order"]);
195                        }
196                        $renderer->doc .= '"><span class="navbar-toggler-icon"></span></button>' . DOKU_LF;
197
198
199                        $classValue = "collapse navbar-collapse";
200                        if (array_key_exists("class", $attributes)) {
201                            $attributes["class"] .= " {$classValue}";
202                        } else {
203                            $attributes["class"] = "{$classValue}";
204                        }
205                        $renderer->doc .= '<div id="' . $idElementToCollapse . '" '.PluginUtility::array2HTMLAttributes($attributes).'>';
206
207                        // All element below will collapse
208                        break;
209
210                    case DOKU_LEXER_UNMATCHED:
211                        $renderer->doc .= NavBarUtility::text(PluginUtility::escape($payload));
212                        break;
213
214                    case DOKU_LEXER_MATCHED:
215
216                        /**
217                         * Shortcut for a link in a {@link syntax_plugin_combo_navbargroup}
218                         */
219                        $html = LinkUtility::renderLinkDefault($renderer,$payload);
220                        $renderer->doc .= '<div class="navbar-nav">'.NavBarUtility::switchDokuwiki2BootstrapClass($html).'</div>';
221                        break;
222
223                    case DOKU_LEXER_EXIT :
224
225                        $renderer->doc .= '</div>' . DOKU_LF;
226                        break;
227                }
228                return true;
229            case 'metadata':
230
231                /**
232                 * Keep track of the backlinks ie meta['relation']['references']
233                 * @var Doku_Renderer_metadata $renderer
234                 */
235                if ($state == DOKU_LEXER_SPECIAL) {
236                    LinkUtility::handleMetadata($renderer, $data);
237                }
238                return true;
239                break;
240        }
241        return false;
242    }
243
244
245    public static function getElementName()
246    {
247        return PluginUtility::getTagName(get_called_class());
248    }
249
250
251}
252