xref: /plugin/combo/syntax/label.php (revision 5f891b7e09648e05e78f5882f3fdde1e9df9b0f1) !
1*5f891b7eSNickeau<?php
2*5f891b7eSNickeau
3*5f891b7eSNickeau// implementation of
4*5f891b7eSNickeau// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite
5*5f891b7eSNickeau
6*5f891b7eSNickeau// must be run within Dokuwiki
7*5f891b7eSNickeauuse ComboStrap\HeaderUtility;
8*5f891b7eSNickeauuse ComboStrap\LogUtility;
9*5f891b7eSNickeauuse ComboStrap\TitleUtility;
10*5f891b7eSNickeauuse ComboStrap\PluginUtility;
11*5f891b7eSNickeauuse ComboStrap\StringUtility;
12*5f891b7eSNickeauuse ComboStrap\Tag;
13*5f891b7eSNickeau
14*5f891b7eSNickeaurequire_once(__DIR__ . '/../class/HeaderUtility.php');
15*5f891b7eSNickeau
16*5f891b7eSNickeauif (!defined('DOKU_INC')) die();
17*5f891b7eSNickeau
18*5f891b7eSNickeau
19*5f891b7eSNickeauclass syntax_plugin_combo_label extends DokuWiki_Syntax_Plugin
20*5f891b7eSNickeau{
21*5f891b7eSNickeau
22*5f891b7eSNickeau
23*5f891b7eSNickeau    const TAG = "label";
24*5f891b7eSNickeau
25*5f891b7eSNickeau    /**
26*5f891b7eSNickeau     * The id of the heading element for a accordion label
27*5f891b7eSNickeau     */
28*5f891b7eSNickeau    const HEADING_ID = "headingId";
29*5f891b7eSNickeau    /**
30*5f891b7eSNickeau     * The id of the collapsable target
31*5f891b7eSNickeau     */
32*5f891b7eSNickeau    const TARGET_ID = "targetId";
33*5f891b7eSNickeau
34*5f891b7eSNickeau    /**
35*5f891b7eSNickeau     * An indicator attribute that tells if the accordion is collpased or not
36*5f891b7eSNickeau     */
37*5f891b7eSNickeau    const COLLAPSED = "collapsed";
38*5f891b7eSNickeau
39*5f891b7eSNickeau    function getType()
40*5f891b7eSNickeau    {
41*5f891b7eSNickeau        return 'formatting';
42*5f891b7eSNickeau    }
43*5f891b7eSNickeau
44*5f891b7eSNickeau    /**
45*5f891b7eSNickeau     * How Dokuwiki will add P element
46*5f891b7eSNickeau     *
47*5f891b7eSNickeau     *  * 'normal' - The plugin can be used inside paragraphs (inline)
48*5f891b7eSNickeau     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
49*5f891b7eSNickeau     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
50*5f891b7eSNickeau     *
51*5f891b7eSNickeau     * @see DokuWiki_Syntax_Plugin::getPType()
52*5f891b7eSNickeau     */
53*5f891b7eSNickeau    function getPType()
54*5f891b7eSNickeau    {
55*5f891b7eSNickeau        return 'normal';
56*5f891b7eSNickeau    }
57*5f891b7eSNickeau
58*5f891b7eSNickeau    function getAllowedTypes()
59*5f891b7eSNickeau    {
60*5f891b7eSNickeau        return array('substition', 'formatting', 'disabled');
61*5f891b7eSNickeau    }
62*5f891b7eSNickeau
63*5f891b7eSNickeau    function getSort()
64*5f891b7eSNickeau    {
65*5f891b7eSNickeau        return 201;
66*5f891b7eSNickeau    }
67*5f891b7eSNickeau
68*5f891b7eSNickeau
69*5f891b7eSNickeau    function connectTo($mode)
70*5f891b7eSNickeau    {
71*5f891b7eSNickeau
72*5f891b7eSNickeau        $this->Lexer->addEntryPattern(PluginUtility::getContainerTagPattern(self::TAG), $mode, PluginUtility::getModeForComponent($this->getPluginComponent()));
73*5f891b7eSNickeau    }
74*5f891b7eSNickeau
75*5f891b7eSNickeau    public function postConnect()
76*5f891b7eSNickeau    {
77*5f891b7eSNickeau        $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent()));
78*5f891b7eSNickeau    }
79*5f891b7eSNickeau
80*5f891b7eSNickeau    function handle($match, $state, $pos, Doku_Handler $handler)
81*5f891b7eSNickeau    {
82*5f891b7eSNickeau
83*5f891b7eSNickeau        switch ($state) {
84*5f891b7eSNickeau
85*5f891b7eSNickeau            case DOKU_LEXER_ENTER:
86*5f891b7eSNickeau                $tagAttributes = PluginUtility::getTagAttributes($match);
87*5f891b7eSNickeau
88*5f891b7eSNickeau                $tag = new Tag(self::TAG, $tagAttributes, $state, $handler);
89*5f891b7eSNickeau                $parentTag = $tag->getParent();
90*5f891b7eSNickeau                $context = null;
91*5f891b7eSNickeau                if ($parentTag != null) {
92*5f891b7eSNickeau                    $grandfather = $parentTag->getParent();
93*5f891b7eSNickeau                    if ($grandfather != null) {
94*5f891b7eSNickeau                        $grandFatherName = $grandfather->getName();
95*5f891b7eSNickeau                        switch ($grandFatherName) {
96*5f891b7eSNickeau                            case syntax_plugin_combo_accordion::TAG:
97*5f891b7eSNickeau                                $id = $parentTag->getAttribute("id");
98*5f891b7eSNickeau                                $tagAttributes["id"] = $id;
99*5f891b7eSNickeau                                $tagAttributes[self::HEADING_ID] = "heading" . ucfirst($id);
100*5f891b7eSNickeau                                $tagAttributes[self::TARGET_ID] = "collapse" . ucfirst($id);
101*5f891b7eSNickeau                                $parentAttribute = $parentTag->getAttributes();
102*5f891b7eSNickeau                                if (!key_exists(self::COLLAPSED, $parentAttribute)) {
103*5f891b7eSNickeau                                    // Accordion are collapsed by default
104*5f891b7eSNickeau                                    $tagAttributes[self::COLLAPSED] = "true";
105*5f891b7eSNickeau                                } else {
106*5f891b7eSNickeau                                    $tagAttributes[self::COLLAPSED] = $parentAttribute[self::COLLAPSED];
107*5f891b7eSNickeau                                }
108*5f891b7eSNickeau                                $context = syntax_plugin_combo_accordion::TAG;
109*5f891b7eSNickeau                                break;
110*5f891b7eSNickeau                            case  syntax_plugin_combo_tabs::TAG:
111*5f891b7eSNickeau                                $context = syntax_plugin_combo_tabs::TAG;
112*5f891b7eSNickeau                                $tagAttributes = $parentTag->getAttributes();
113*5f891b7eSNickeau                                break;
114*5f891b7eSNickeau                            default:
115*5f891b7eSNickeau                                LogUtility::log2FrontEnd("The label is included in the $grandFatherName component and this is unexpected", LogUtility::LVL_MSG_WARNING, self::TAG);
116*5f891b7eSNickeau                        }
117*5f891b7eSNickeau                    }
118*5f891b7eSNickeau                }
119*5f891b7eSNickeau
120*5f891b7eSNickeau                return array(
121*5f891b7eSNickeau                    PluginUtility::STATE => $state,
122*5f891b7eSNickeau                    PluginUtility::ATTRIBUTES => $tagAttributes,
123*5f891b7eSNickeau                    PluginUtility::CONTEXT => $context
124*5f891b7eSNickeau                );
125*5f891b7eSNickeau
126*5f891b7eSNickeau            case DOKU_LEXER_UNMATCHED :
127*5f891b7eSNickeau                return array(
128*5f891b7eSNickeau                    PluginUtility::STATE => $state,
129*5f891b7eSNickeau                    PluginUtility::PAYLOAD => $match
130*5f891b7eSNickeau                );
131*5f891b7eSNickeau
132*5f891b7eSNickeau            case DOKU_LEXER_EXIT :
133*5f891b7eSNickeau                $tag = new Tag(self::TAG, array(), $state, $handler);
134*5f891b7eSNickeau                $openingTag = $tag->getOpeningTag();
135*5f891b7eSNickeau                $context = $openingTag->getContext();
136*5f891b7eSNickeau                return array(
137*5f891b7eSNickeau                    PluginUtility::STATE => $state,
138*5f891b7eSNickeau                    PluginUtility::CONTEXT => $context,
139*5f891b7eSNickeau                    PluginUtility::ATTRIBUTES => $openingTag->getAttributes()
140*5f891b7eSNickeau                );
141*5f891b7eSNickeau
142*5f891b7eSNickeau
143*5f891b7eSNickeau        }
144*5f891b7eSNickeau        return array();
145*5f891b7eSNickeau
146*5f891b7eSNickeau    }
147*5f891b7eSNickeau
148*5f891b7eSNickeau    /**
149*5f891b7eSNickeau     * Render the output
150*5f891b7eSNickeau     * @param string $format
151*5f891b7eSNickeau     * @param Doku_Renderer $renderer
152*5f891b7eSNickeau     * @param array $data - what the function handle() return'ed
153*5f891b7eSNickeau     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
154*5f891b7eSNickeau     * @see DokuWiki_Syntax_Plugin::render()
155*5f891b7eSNickeau     *
156*5f891b7eSNickeau     *
157*5f891b7eSNickeau     */
158*5f891b7eSNickeau    function render($format, Doku_Renderer $renderer, $data)
159*5f891b7eSNickeau    {
160*5f891b7eSNickeau
161*5f891b7eSNickeau        if ($format == 'xhtml') {
162*5f891b7eSNickeau
163*5f891b7eSNickeau            /** @var Doku_Renderer_xhtml $renderer */
164*5f891b7eSNickeau            $state = $data[PluginUtility::STATE];
165*5f891b7eSNickeau            switch ($state) {
166*5f891b7eSNickeau
167*5f891b7eSNickeau                case DOKU_LEXER_ENTER:
168*5f891b7eSNickeau
169*5f891b7eSNickeau                    $context = $data[PluginUtility::CONTEXT];
170*5f891b7eSNickeau                    switch ($context) {
171*5f891b7eSNickeau                        case syntax_plugin_combo_accordion::TAG:
172*5f891b7eSNickeau                            $attribute = $data[PluginUtility::ATTRIBUTES];
173*5f891b7eSNickeau                            $headingId = $attribute[self::HEADING_ID];
174*5f891b7eSNickeau                            $collapseId = $attribute[self::TARGET_ID];
175*5f891b7eSNickeau                            $collapsed = $attribute[self::COLLAPSED];
176*5f891b7eSNickeau                            if ($collapsed == "false") {
177*5f891b7eSNickeau                                $collapsedClass = "collapsed";
178*5f891b7eSNickeau                            } else {
179*5f891b7eSNickeau                                $collapsedClass = "";
180*5f891b7eSNickeau                            }
181*5f891b7eSNickeau                            $renderer->doc .= "<div class=\"card-header\" id=\"$headingId\">" . DOKU_LF;
182*5f891b7eSNickeau                            $renderer->doc .= "<h2 class=\"mb-0\">";
183*5f891b7eSNickeau                            $renderer->doc .= "<button class=\"btn btn-link btn-block text-left $collapsedClass\" type=\"button\" data-toggle=\"collapse\" data-target=\"#$collapseId\" aria-expanded=\"true\" aria-controls=\"$collapseId\">";
184*5f891b7eSNickeau                            break;
185*5f891b7eSNickeau                        case  syntax_plugin_combo_tabs::TAG:
186*5f891b7eSNickeau                            $attributes = $data[PluginUtility::ATTRIBUTES];
187*5f891b7eSNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::openNavigationalTabElement($attributes);
188*5f891b7eSNickeau                            break;
189*5f891b7eSNickeau                        default:
190*5f891b7eSNickeau                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in exit", LogUtility::LVL_MSG_WARNING, self::TAG);
191*5f891b7eSNickeau                    }
192*5f891b7eSNickeau                    break;
193*5f891b7eSNickeau
194*5f891b7eSNickeau                case DOKU_LEXER_UNMATCHED :
195*5f891b7eSNickeau                    $renderer->doc .= PluginUtility::escape($data[PluginUtility::PAYLOAD]);
196*5f891b7eSNickeau                    break;
197*5f891b7eSNickeau
198*5f891b7eSNickeau                case DOKU_LEXER_EXIT:
199*5f891b7eSNickeau                    $context = $data[PluginUtility::CONTEXT];
200*5f891b7eSNickeau                    switch ($context) {
201*5f891b7eSNickeau                        case syntax_plugin_combo_accordion::TAG:
202*5f891b7eSNickeau                            $attribute = $data[PluginUtility::ATTRIBUTES];
203*5f891b7eSNickeau                            $collapseId = $attribute[self::TARGET_ID];
204*5f891b7eSNickeau                            $headingId = $attribute[self::HEADING_ID];
205*5f891b7eSNickeau                            $collapsed = $attribute[self::COLLAPSED];
206*5f891b7eSNickeau                            if ($collapsed == "false") {
207*5f891b7eSNickeau                                $showClass = "show";
208*5f891b7eSNickeau                            } else {
209*5f891b7eSNickeau                                $showClass = "";
210*5f891b7eSNickeau                            }
211*5f891b7eSNickeau                            $renderer->doc .= "</button></h2></div>";
212*5f891b7eSNickeau                            $renderer->doc .= "<div id=\"$collapseId\" class=\"collapse $showClass\" aria-labelledby=\"$headingId\" data-parent=\"#$headingId\">";
213*5f891b7eSNickeau                            $renderer->doc .= "<div class=\"card-body\">" . DOKU_LF;
214*5f891b7eSNickeau                            break;
215*5f891b7eSNickeau                        case  syntax_plugin_combo_tabs::TAG:
216*5f891b7eSNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::closeNavigationalTabElement();
217*5f891b7eSNickeau                            break;
218*5f891b7eSNickeau                        default:
219*5f891b7eSNickeau                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in exit", LogUtility::LVL_MSG_WARNING, self::TAG);
220*5f891b7eSNickeau
221*5f891b7eSNickeau                    }
222*5f891b7eSNickeau                    break;
223*5f891b7eSNickeau
224*5f891b7eSNickeau
225*5f891b7eSNickeau            }
226*5f891b7eSNickeau        }
227*5f891b7eSNickeau        // unsupported $mode
228*5f891b7eSNickeau        return false;
229*5f891b7eSNickeau    }
230*5f891b7eSNickeau
231*5f891b7eSNickeau
232*5f891b7eSNickeau}
233*5f891b7eSNickeau
234