xref: /plugin/combo/syntax/accordion.php (revision 531e725cdb5a652164f2d97f556304e31f720033)
1<?php
2/**
3 * DokuWiki Syntax Plugin Combostrap.
4 *
5 */
6
7use ComboStrap\PluginUtility;
8use ComboStrap\Tag;
9use ComboStrap\TagAttributes;
10
11if (!defined('DOKU_INC')) {
12    die();
13}
14
15if (!defined('DOKU_PLUGIN')) {
16    define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
17}
18
19require_once(__DIR__ . '/../class/PluginUtility.php');
20
21/**
22 * All DokuWiki plugins to extend the parser/rendering mechanism
23 * need to inherit from this class
24 *
25 * The name of the class must follow a pattern (don't change it)
26 * ie:
27 *    syntax_plugin_PluginName_ComponentName
28 *
29 * https://getbootstrap.com/docs/4.6/components/collapse/#accordion-example
30 *
31 * Ter info:
32 * https://jqueryui.com/accordion/
33 *
34 * See also: https://getbootstrap.com/docs/5.0/content/reboot/#summary
35 * with a pointer
36 *
37 */
38class syntax_plugin_combo_accordion extends DokuWiki_Syntax_Plugin
39{
40
41
42    const TAG = 'accordion';
43
44    /**
45     * @var int a counter to give an id to the accordion card
46     */
47    private $accordionCounter = 0;
48
49    /**
50     * Syntax Type.
51     *
52     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
53     * @see DokuWiki_Syntax_Plugin::getType()
54     */
55    function getType()
56    {
57        return 'container';
58    }
59
60    /**
61     * @return array
62     * Allow which kind of plugin inside
63     *
64     * One of array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
65     * 'baseonly' will run only in the base mode
66     * because we manage self the content and we call self the parser
67     *
68     * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php
69     */
70    public function getAllowedTypes()
71    {
72        return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs');
73    }
74
75    public function accepts($mode)
76    {
77        /**
78         * header mode is disable to take over
79         * and replace it with {@link syntax_plugin_combo_heading}
80         */
81        if ($mode == "header") {
82            return false;
83        }
84        /**
85         *
86         */
87        return syntax_plugin_combo_preformatted::disablePreformatted($mode);
88
89    }
90
91    /**
92     * How Dokuwiki will add P element
93     *
94     * * 'normal' - The plugin can be used inside paragraphs
95     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
96     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
97     *
98     * @see DokuWiki_Syntax_Plugin::getPType()
99     */
100    function getPType()
101    {
102        return 'block';
103    }
104
105    /**
106     * @see Doku_Parser_Mode::getSort()
107     * Higher number than the teaser-columns
108     * because the mode with the lowest sort number will win out
109     */
110    function getSort()
111    {
112        return 200;
113    }
114
115    /**
116     * Create a pattern that will called this plugin
117     *
118     * @param string $mode
119     * @see Doku_Parser_Mode::connectTo()
120     */
121    function connectTo($mode)
122    {
123
124
125        $pattern = PluginUtility::getContainerTagPattern(self::TAG);
126        $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent()));
127
128
129    }
130
131    public function postConnect()
132    {
133
134
135        $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent()));
136
137
138    }
139
140    /**
141     *
142     * The handle function goal is to parse the matched syntax through the pattern function
143     * and to return the result for use in the renderer
144     * This result is always cached until the page is modified.
145     * @param string $match
146     * @param int $state
147     * @param int $pos
148     * @param Doku_Handler $handler
149     * @return array|bool
150     * @see DokuWiki_Syntax_Plugin::handle()
151     *
152     */
153    function handle($match, $state, $pos, Doku_Handler $handler)
154    {
155
156        switch ($state) {
157
158            case DOKU_LEXER_ENTER:
159
160                $this->accordionCounter++;
161                $attributes = PluginUtility::getTagAttributes($match);
162
163                // Attributes has at
164                // https://getbootstrap.com/docs/4.6/components/collapse/#accordion-example
165                PluginUtility::addClass2Attributes("accordion", $attributes);
166                if (!in_array("id", $attributes)) {
167                    $attributes["id"] = self::TAG . $this->accordionCounter;
168                }
169
170                return array(
171                    PluginUtility::STATE => $state,
172                    PluginUtility::ATTRIBUTES => $attributes
173                );
174
175            case DOKU_LEXER_UNMATCHED :
176
177                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
178
179
180            case DOKU_LEXER_EXIT :
181
182                return array(
183                    PluginUtility::STATE => $state
184                );
185
186
187        }
188
189        return array();
190
191    }
192
193    /**
194     * Render the output
195     * @param string $format
196     * @param Doku_Renderer $renderer
197     * @param array $data - what the function handle() return'ed
198     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
199     * @see DokuWiki_Syntax_Plugin::render()
200     *
201     *
202     */
203    function render($format, Doku_Renderer $renderer, $data)
204    {
205
206        if ($format == 'xhtml') {
207
208            /** @var Doku_Renderer_xhtml $renderer */
209            $state = $data[PluginUtility::STATE];
210            switch ($state) {
211                case DOKU_LEXER_ENTER:
212                    $attributes = TagAttributes::createFromCallStackArray($data[PluginUtility::ATTRIBUTES]);
213                    $renderer->doc .= $attributes->toHtmlEnterTag("div") . DOKU_LF;
214                    break;
215                case DOKU_LEXER_UNMATCHED:
216                    $renderer->doc .= PluginUtility::renderUnmatched($data);
217                    break;
218                case DOKU_LEXER_EXIT:
219                    $renderer->doc .= '</div>' . DOKU_LF;
220                    break;
221            }
222
223
224            return true;
225        }
226        return false;
227    }
228
229
230}
231