1<?php
2
3namespace ComboStrap;
4
5use ComboStrap\TagAttribute\Shadow;
6use DokuWiki_Syntax_Plugin;
7use syntax_plugin_combo_link;
8use syntax_plugin_combo_menubar;
9
10/**
11 * ===== For the Geek =====
12 * This is not the [[https://www.w3.org/TR/wai-aria-practices/#button|Button as describe by the Web Specification]]
13 * but a styling over a [[https://www.w3.org/TR/wai-aria-practices/#link|link]]
14 *
15 * ===== Documentation / Reference =====
16 * https://material.io/components/buttons
17 * https://getbootstrap.com/docs/4.5/components/buttons/
18 */
19class ButtonTag
20{
21
22    public const TYPES = [
23        ColorRgb::PRIMARY_VALUE,
24        ColorRgb::SECONDARY_VALUE,
25        "success",
26        "danger",
27        "warning",
28        "info",
29        "light",
30        "dark",
31        "link"
32    ];
33    public const MARKUP_LONG = "button";
34    public const MARKUP_SHORT = "btn";
35    const LOGICAL_TAG = self::MARKUP_LONG;
36
37    /**
38     * @param TagAttributes $tagAttributes
39     */
40    public static function processButtonAttributesToHtmlAttributes(TagAttributes &$tagAttributes)
41    {
42        # A button
43        $btn = "btn";
44        $tagAttributes->addClassName($btn);
45
46        $type = $tagAttributes->getValue(TagAttributes::TYPE_KEY, "primary");
47        $skin = $tagAttributes->getValue(Skin::SKIN_ATTRIBUTE, Skin::FILLED_VALUE);
48        switch ($skin) {
49            case "contained":
50            {
51                $tagAttributes->addClassName("$btn-$type");
52                $tagAttributes->addComponentAttributeValue(Shadow::CANONICAL, true);
53                break;
54            }
55            case "filled":
56            {
57                $tagAttributes->addClassName("$btn-$type");
58                break;
59            }
60            case "outline":
61            {
62                $tagAttributes->addClassName("$btn-outline-$type");
63                break;
64            }
65            case "text":
66            {
67                $tagAttributes->addClassName("$btn-link");
68                $tagAttributes->addComponentAttributeValue(TextColor::TEXT_COLOR_ATTRIBUTE, $type);
69                break;
70            }
71        }
72
73
74        $sizeAttribute = "size";
75        if ($tagAttributes->hasComponentAttribute($sizeAttribute)) {
76            $size = $tagAttributes->getValueAndRemove($sizeAttribute);
77            switch ($size) {
78                case "lg":
79                case "large":
80                    $tagAttributes->addClassName("btn-lg");
81                    break;
82                case "sm":
83                case "small":
84                    $tagAttributes->addClassName("btn-sm");
85                    break;
86            }
87        }
88    }
89
90    public static function getTags(): array
91    {
92        $elements[] = ButtonTag::MARKUP_LONG;
93        $elements[] = ButtonTag::MARKUP_SHORT;
94        return $elements;
95    }
96
97    public static function handleEnter(TagAttributes $attributes, \Doku_Handler $handler): array
98    {
99        /**
100         * Note: Branding color (primary and secondary)
101         * are set with the {@link Skin}
102         */
103
104        /**
105         * The parent
106         * to apply automatically styling in a bar
107         */
108        $callStack = CallStack::createFromHandler($handler);
109        $isInMenuBar = false;
110        while ($parent = $callStack->moveToParent()) {
111            if ($parent->getTagName() === syntax_plugin_combo_menubar::TAG) {
112                $isInMenuBar = true;
113                break;
114            }
115        }
116        if ($isInMenuBar) {
117            if (!$attributes->hasAttribute("class") && !$attributes->hasAttribute("spacing")) {
118                $attributes->addComponentAttributeValue("spacing", "mr-2 mb-2 mt-2 mb-lg-0 mt-lg-0");
119            }
120        }
121
122        /**
123         * The context give set if this is a button
124         * or a link button
125         * The context is checked in the `exit` state
126         * Default context: This is not a link button
127         */
128        $context = ButtonTag::MARKUP_LONG;
129
130
131        return array(
132            PluginUtility::CONTEXT => $context
133        );
134    }
135
136    public static function handleExit(\Doku_Handler $handler): array
137    {
138        $callStack = CallStack::createFromHandler($handler);
139        $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
140        /**
141         * Button or link button
142         */
143        $context = ButtonTag::MARKUP_LONG;
144        $descendant = $callStack->moveToFirstChildTag();
145        if ($descendant !== false) {
146            if ($descendant->getTagName() === syntax_plugin_combo_link::TAG) {
147                $context = syntax_plugin_combo_link::TAG;
148            }
149        }
150        $openingTag->setContext($context);
151
152        return array(
153            PluginUtility::CONTEXT => $context
154        );
155    }
156
157    public static function renderEnterXhtml(TagAttributes $tagAttributes, DokuWiki_Syntax_Plugin $plugin, array $data): string
158    {
159        /**
160         * CSS if dokuwiki class name for link
161         */
162        if ($plugin->getConf(LinkMarkup::CONF_USE_DOKUWIKI_CLASS_NAME, false)) {
163            PluginUtility::getSnippetManager()->attachCssInternalStyleSheet(ButtonTag::MARKUP_LONG);
164        }
165
166        /**
167         * If this not a link button
168         * The context is set on the handle exit
169         */
170        $context = $data[PluginUtility::CONTEXT];
171        if ($context == ButtonTag::LOGICAL_TAG) {
172            $tagAttributes->setDefaultStyleClassShouldBeAdded(false);
173            ButtonTag::processButtonAttributesToHtmlAttributes($tagAttributes);
174            $tagAttributes->addOutputAttributeValue("type", "button");
175            return $tagAttributes->toHtmlEnterTag('button');
176        }
177        return "";
178
179    }
180
181    public static function renderExitXhtml($data): string
182    {
183        $context = $data[PluginUtility::CONTEXT];
184        /**
185         * If this is a button and not a link button
186         */
187        if ($context === ButtonTag::MARKUP_LONG) {
188            return '</button>';
189        }
190        return "";
191    }
192}
193