xref: /plugin/combo/syntax/label.php (revision 531e725cdb5a652164f2d97f556304e31f720033)
15f891b7eSNickeau<?php
25f891b7eSNickeau
35f891b7eSNickeau// implementation of
45f891b7eSNickeau// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite
55f891b7eSNickeau
65f891b7eSNickeau// must be run within Dokuwiki
721913ab3SNickeauuse ComboStrap\Bootstrap;
821913ab3SNickeauuse ComboStrap\CallStack;
923723136Sgerardnicouse ComboStrap\MediaLink;
105f891b7eSNickeauuse ComboStrap\LogUtility;
115f891b7eSNickeauuse ComboStrap\PluginUtility;
125f891b7eSNickeauuse ComboStrap\Tag;
1321913ab3SNickeauuse ComboStrap\TagAttributes;
1421913ab3SNickeau
155f891b7eSNickeau
165f891b7eSNickeaurequire_once(__DIR__ . '/../class/HeaderUtility.php');
175f891b7eSNickeau
185f891b7eSNickeauif (!defined('DOKU_INC')) die();
195f891b7eSNickeau
205f891b7eSNickeau
215f891b7eSNickeauclass syntax_plugin_combo_label extends DokuWiki_Syntax_Plugin
225f891b7eSNickeau{
235f891b7eSNickeau
245f891b7eSNickeau
255f891b7eSNickeau    const TAG = "label";
265f891b7eSNickeau
275f891b7eSNickeau    /**
285f891b7eSNickeau     * The id of the heading element for a accordion label
295f891b7eSNickeau     */
305f891b7eSNickeau    const HEADING_ID = "headingId";
315f891b7eSNickeau    /**
325f891b7eSNickeau     * The id of the collapsable target
335f891b7eSNickeau     */
345f891b7eSNickeau    const TARGET_ID = "targetId";
355f891b7eSNickeau
365f891b7eSNickeau    /**
375f891b7eSNickeau     * An indicator attribute that tells if the accordion is collpased or not
385f891b7eSNickeau     */
395f891b7eSNickeau    const COLLAPSED = "collapsed";
405f891b7eSNickeau
415f891b7eSNickeau    function getType()
425f891b7eSNickeau    {
435f891b7eSNickeau        return 'formatting';
445f891b7eSNickeau    }
455f891b7eSNickeau
465f891b7eSNickeau    /**
475f891b7eSNickeau     * How Dokuwiki will add P element
485f891b7eSNickeau     *
495f891b7eSNickeau     *  * 'normal' - The plugin can be used inside paragraphs (inline)
505f891b7eSNickeau     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
515f891b7eSNickeau     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
525f891b7eSNickeau     *
535f891b7eSNickeau     * @see DokuWiki_Syntax_Plugin::getPType()
545f891b7eSNickeau     */
555f891b7eSNickeau    function getPType()
565f891b7eSNickeau    {
5721913ab3SNickeau        return 'block';
585f891b7eSNickeau    }
595f891b7eSNickeau
605f891b7eSNickeau    function getAllowedTypes()
615f891b7eSNickeau    {
625f891b7eSNickeau        return array('substition', 'formatting', 'disabled');
635f891b7eSNickeau    }
645f891b7eSNickeau
655f891b7eSNickeau    function getSort()
665f891b7eSNickeau    {
675f891b7eSNickeau        return 201;
685f891b7eSNickeau    }
695f891b7eSNickeau
705f891b7eSNickeau
715f891b7eSNickeau    function connectTo($mode)
725f891b7eSNickeau    {
735f891b7eSNickeau
745f891b7eSNickeau        $this->Lexer->addEntryPattern(PluginUtility::getContainerTagPattern(self::TAG), $mode, PluginUtility::getModeForComponent($this->getPluginComponent()));
755f891b7eSNickeau    }
765f891b7eSNickeau
775f891b7eSNickeau    public function postConnect()
785f891b7eSNickeau    {
795f891b7eSNickeau        $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent()));
805f891b7eSNickeau    }
815f891b7eSNickeau
825f891b7eSNickeau    function handle($match, $state, $pos, Doku_Handler $handler)
835f891b7eSNickeau    {
845f891b7eSNickeau
855f891b7eSNickeau        switch ($state) {
865f891b7eSNickeau
875f891b7eSNickeau            case DOKU_LEXER_ENTER:
885f891b7eSNickeau                $tagAttributes = PluginUtility::getTagAttributes($match);
895f891b7eSNickeau
905f891b7eSNickeau                $tag = new Tag(self::TAG, $tagAttributes, $state, $handler);
915f891b7eSNickeau                $parentTag = $tag->getParent();
925f891b7eSNickeau                $context = null;
935f891b7eSNickeau                if ($parentTag != null) {
945f891b7eSNickeau                    $grandfather = $parentTag->getParent();
955f891b7eSNickeau                    if ($grandfather != null) {
965f891b7eSNickeau                        $grandFatherName = $grandfather->getName();
975f891b7eSNickeau                        switch ($grandFatherName) {
985f891b7eSNickeau                            case syntax_plugin_combo_accordion::TAG:
995f891b7eSNickeau                                $id = $parentTag->getAttribute("id");
1005f891b7eSNickeau                                $tagAttributes["id"] = $id;
1015f891b7eSNickeau                                $tagAttributes[self::HEADING_ID] = "heading" . ucfirst($id);
1025f891b7eSNickeau                                $tagAttributes[self::TARGET_ID] = "collapse" . ucfirst($id);
1035f891b7eSNickeau                                $parentAttribute = $parentTag->getAttributes();
1045f891b7eSNickeau                                if (!key_exists(self::COLLAPSED, $parentAttribute)) {
1055f891b7eSNickeau                                    // Accordion are collapsed by default
1065f891b7eSNickeau                                    $tagAttributes[self::COLLAPSED] = "true";
1075f891b7eSNickeau                                } else {
1085f891b7eSNickeau                                    $tagAttributes[self::COLLAPSED] = $parentAttribute[self::COLLAPSED];
1095f891b7eSNickeau                                }
1105f891b7eSNickeau                                $context = syntax_plugin_combo_accordion::TAG;
1115f891b7eSNickeau                                break;
1125f891b7eSNickeau                            case  syntax_plugin_combo_tabs::TAG:
1135f891b7eSNickeau                                $context = syntax_plugin_combo_tabs::TAG;
1145f891b7eSNickeau                                $tagAttributes = $parentTag->getAttributes();
1155f891b7eSNickeau                                break;
1165f891b7eSNickeau                            default:
1175f891b7eSNickeau                                LogUtility::log2FrontEnd("The label is included in the $grandFatherName component and this is unexpected", LogUtility::LVL_MSG_WARNING, self::TAG);
1185f891b7eSNickeau                        }
11921913ab3SNickeau                    } else {
12021913ab3SNickeau                        /**
12121913ab3SNickeau                         * An panel may render alone in preview
12221913ab3SNickeau                         */
12321913ab3SNickeau                        if ($parentTag->getContext() == syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE) {
12421913ab3SNickeau                            $context = syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE;
12521913ab3SNickeau                        }
1265f891b7eSNickeau                    }
1275f891b7eSNickeau                }
1285f891b7eSNickeau
1295f891b7eSNickeau                return array(
1305f891b7eSNickeau                    PluginUtility::STATE => $state,
1315f891b7eSNickeau                    PluginUtility::ATTRIBUTES => $tagAttributes,
1325f891b7eSNickeau                    PluginUtility::CONTEXT => $context
1335f891b7eSNickeau                );
1345f891b7eSNickeau
1355f891b7eSNickeau            case DOKU_LEXER_UNMATCHED :
13632b85071SNickeau                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
1375f891b7eSNickeau
1385f891b7eSNickeau            case DOKU_LEXER_EXIT :
13921913ab3SNickeau                $callStack = CallStack::createFromHandler($handler);
14021913ab3SNickeau                $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
1415f891b7eSNickeau                $context = $openingTag->getContext();
14221913ab3SNickeau
14321913ab3SNickeau                /**
14421913ab3SNickeau                 * An image in a label should have no link (ie no anchor)
14521913ab3SNickeau                 * because a anchor is used for navigation
14621913ab3SNickeau                 */
147*531e725cSNickeau                $callStack->processNoLinkOnImageToEndStack();
14821913ab3SNickeau
14921913ab3SNickeau                $callStack->closeAndResetPointer();
15021913ab3SNickeau
151*531e725cSNickeau
1525f891b7eSNickeau                return array(
1535f891b7eSNickeau                    PluginUtility::STATE => $state,
1545f891b7eSNickeau                    PluginUtility::CONTEXT => $context,
1555f891b7eSNickeau                    PluginUtility::ATTRIBUTES => $openingTag->getAttributes()
1565f891b7eSNickeau                );
1575f891b7eSNickeau
1585f891b7eSNickeau
1595f891b7eSNickeau        }
1605f891b7eSNickeau        return array();
1615f891b7eSNickeau
1625f891b7eSNickeau    }
1635f891b7eSNickeau
1645f891b7eSNickeau    /**
1655f891b7eSNickeau     * Render the output
1665f891b7eSNickeau     * @param string $format
1675f891b7eSNickeau     * @param Doku_Renderer $renderer
1685f891b7eSNickeau     * @param array $data - what the function handle() return'ed
1695f891b7eSNickeau     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
1705f891b7eSNickeau     * @see DokuWiki_Syntax_Plugin::render()
1715f891b7eSNickeau     *
1725f891b7eSNickeau     *
1735f891b7eSNickeau     */
1745f891b7eSNickeau    function render($format, Doku_Renderer $renderer, $data)
1755f891b7eSNickeau    {
1765f891b7eSNickeau
1775f891b7eSNickeau        if ($format == 'xhtml') {
1785f891b7eSNickeau
1795f891b7eSNickeau            /** @var Doku_Renderer_xhtml $renderer */
1805f891b7eSNickeau            $state = $data[PluginUtility::STATE];
1815f891b7eSNickeau            switch ($state) {
1825f891b7eSNickeau
1835f891b7eSNickeau                case DOKU_LEXER_ENTER:
1845f891b7eSNickeau
1855f891b7eSNickeau                    $context = $data[PluginUtility::CONTEXT];
1865f891b7eSNickeau                    switch ($context) {
1875f891b7eSNickeau                        case syntax_plugin_combo_accordion::TAG:
1885f891b7eSNickeau                            $attribute = $data[PluginUtility::ATTRIBUTES];
1895f891b7eSNickeau                            $headingId = $attribute[self::HEADING_ID];
1905f891b7eSNickeau                            $collapseId = $attribute[self::TARGET_ID];
1915f891b7eSNickeau                            $collapsed = $attribute[self::COLLAPSED];
1925f891b7eSNickeau                            if ($collapsed == "false") {
1935f891b7eSNickeau                                $collapsedClass = "collapsed";
1945f891b7eSNickeau                            } else {
1955f891b7eSNickeau                                $collapsedClass = "";
1965f891b7eSNickeau                            }
1975f891b7eSNickeau                            $renderer->doc .= "<div class=\"card-header\" id=\"$headingId\">" . DOKU_LF;
1985f891b7eSNickeau                            $renderer->doc .= "<h2 class=\"mb-0\">";
19921913ab3SNickeau                            $dataNamespace = Bootstrap::getDataNamespace();
20021913ab3SNickeau                            $renderer->doc .= "<button class=\"btn btn-link btn-block text-left $collapsedClass\" type=\"button\" data{$dataNamespace}-toggle=\"collapse\" data{$dataNamespace}-target=\"#$collapseId\" aria-expanded=\"true\" aria-controls=\"$collapseId\">";
2015f891b7eSNickeau                            break;
2025f891b7eSNickeau                        case syntax_plugin_combo_tabs::TAG:
2035f891b7eSNickeau                            $attributes = $data[PluginUtility::ATTRIBUTES];
2045f891b7eSNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::openNavigationalTabElement($attributes);
2055f891b7eSNickeau                            break;
20621913ab3SNickeau                        case syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE:
20721913ab3SNickeau                            $attributes = syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE_ATTRIBUTES;
20821913ab3SNickeau                            $renderer->doc .= "<ul style=\"list-style-type: none;padding-inline-start: 0;\">";
20921913ab3SNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::openNavigationalTabElement($attributes);
21021913ab3SNickeau                            break;
2115f891b7eSNickeau                        default:
21221913ab3SNickeau                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in enter", LogUtility::LVL_MSG_WARNING, self::TAG);
21321913ab3SNickeau
2145f891b7eSNickeau                    }
2155f891b7eSNickeau                    break;
2165f891b7eSNickeau
2175f891b7eSNickeau                case DOKU_LEXER_UNMATCHED :
21832b85071SNickeau                    $renderer->doc .= PluginUtility::renderUnmatched($data);
2195f891b7eSNickeau                    break;
2205f891b7eSNickeau
2215f891b7eSNickeau                case DOKU_LEXER_EXIT:
2225f891b7eSNickeau                    $context = $data[PluginUtility::CONTEXT];
2235f891b7eSNickeau                    switch ($context) {
2245f891b7eSNickeau                        case syntax_plugin_combo_accordion::TAG:
2255f891b7eSNickeau                            $attribute = $data[PluginUtility::ATTRIBUTES];
2265f891b7eSNickeau                            $collapseId = $attribute[self::TARGET_ID];
2275f891b7eSNickeau                            $headingId = $attribute[self::HEADING_ID];
2285f891b7eSNickeau                            $collapsed = $attribute[self::COLLAPSED];
2295f891b7eSNickeau                            if ($collapsed == "false") {
2305f891b7eSNickeau                                $showClass = "show";
2315f891b7eSNickeau                            } else {
2325f891b7eSNickeau                                $showClass = "";
2335f891b7eSNickeau                            }
2345f891b7eSNickeau                            $renderer->doc .= "</button></h2></div>";
23521913ab3SNickeau                            $dataNamespace = Bootstrap::getDataNamespace();
23621913ab3SNickeau                            $renderer->doc .= "<div id=\"$collapseId\" class=\"collapse $showClass\" aria-labelledby=\"$headingId\" data-{$dataNamespace}parent=\"#$headingId\">";
2375f891b7eSNickeau                            $renderer->doc .= "<div class=\"card-body\">" . DOKU_LF;
2385f891b7eSNickeau                            break;
2395f891b7eSNickeau                        case syntax_plugin_combo_tabs::TAG:
2405f891b7eSNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::closeNavigationalTabElement();
2415f891b7eSNickeau                            break;
24221913ab3SNickeau                        case syntax_plugin_combo_panel::CONTEXT_PREVIEW_ALONE:
24321913ab3SNickeau                            $renderer->doc .= syntax_plugin_combo_tabs::closeNavigationalTabElement();
24421913ab3SNickeau                            $renderer->doc .= "</ul>";
24521913ab3SNickeau                            break;
2465f891b7eSNickeau                        default:
2475f891b7eSNickeau                            LogUtility::log2FrontEnd("The context ($context) of the label is unknown in exit", LogUtility::LVL_MSG_WARNING, self::TAG);
2485f891b7eSNickeau
24921913ab3SNickeau
2505f891b7eSNickeau                    }
2515f891b7eSNickeau                    break;
2525f891b7eSNickeau
2535f891b7eSNickeau
2545f891b7eSNickeau            }
2555f891b7eSNickeau        }
2565f891b7eSNickeau        // unsupported $mode
2575f891b7eSNickeau        return false;
2585f891b7eSNickeau    }
2595f891b7eSNickeau
2605f891b7eSNickeau
2615f891b7eSNickeau}
2625f891b7eSNickeau
263