1<?php
2
3namespace ComboStrap\Tag;
4
5
6use ComboStrap\Call;
7use ComboStrap\CallStack;
8use ComboStrap\Dimension;
9use ComboStrap\LogUtility;
10use ComboStrap\PluginUtility;
11use ComboStrap\TagAttribute\Align;
12use ComboStrap\TagAttributes;
13use Doku_Handler;
14
15/**
16 * Class syntax_plugin_combo_box
17 * Implementation of a div
18 * It permits also to dynamically add html element from other component
19 * via the {@link Call::createComboCall()}
20 *
21 */
22class BoxTag
23{
24
25    const TAG = "box";
26
27
28    // the logical tag applied (class)
29    const LOGICAL_TAG_ATTRIBUTE = "logical-tag";
30    const LOGICAL_TAG_DEFAUT = self::TAG;
31    // the html tag
32    const HTML_TAG_ATTRIBUTE = "html-tag";
33    const DEFAULT_HTML_TAG = "div";
34    // Tag that may make external http requests are not authorized
35    const NON_AUTHORIZED_HTML_TAG = ["script", "style", "img", "video"];
36
37    public static function handleEnter(TagAttributes $attributes)
38    {
39        $tag = $attributes->getValue(self::HTML_TAG_ATTRIBUTE);
40        if (in_array($tag, self::NON_AUTHORIZED_HTML_TAG)) {
41            LogUtility::error("The html tag ($tag) is not authorized.");
42            $attributes->setComponentAttributeValue(self::HTML_TAG_ATTRIBUTE, self::DEFAULT_HTML_TAG);
43        }
44    }
45
46
47    static function handleExit(Doku_Handler $handler): array
48    {
49
50        $callStack = CallStack::createFromHandler($handler);
51
52        /**
53         * Check children align
54         */
55        $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
56        $align = $openingTag->getAttribute(Align::ALIGN_ATTRIBUTE);
57        if ($align !== null && strpos($align, "children") !== false) {
58
59            /**
60             * Scan to see the type of content
61             * children can be use against one inline element or more block element
62             * Not against more than one inline children element
63             *
64             * Retrieve the number of inline element
65             * ie enter, special and box unmatched
66             */
67            $inlineTagFounds = [];
68            while ($actual = $callStack->next()) {
69
70                switch ($actual->getState()) {
71                    case DOKU_LEXER_EXIT:
72                        continue 2;
73                    case DOKU_LEXER_UNMATCHED:
74                        if ($actual->getTagName() !== self::TAG) {
75                            continue 2;
76                        } else {
77                            // Not a problem is the text are only space
78                            if (trim($actual->getCapturedContent()) === "") {
79                                continue 2;
80                            }
81                        }
82                }
83                if ($actual->getDisplay() == Call::INLINE_DISPLAY) {
84                    $tagName = $actual->getTagName();
85                    if ($actual->getTagName() === self::TAG && $actual->getState() === DOKU_LEXER_UNMATCHED) {
86                        $tagName = "$tagName text";
87                    }
88                    $inlineTagFounds[] = $tagName;
89                }
90            }
91            if (count($inlineTagFounds) > 1) {
92                // You can't use children align value against inline
93                LogUtility::warning("The `children` align attribute ($align) on the box component was apply against more than one inline elements (ie " . implode(", ", $inlineTagFounds) . "). If you don't get what you want use a text align value such as `text-center`");
94            }
95        }
96
97        /**
98         * Add a scroll toggle if the
99         * box is constrained by height
100         */
101        Dimension::addScrollToggleOnClickIfNoControl($callStack);
102
103        /**
104         *
105         */
106        return array(
107            PluginUtility::ATTRIBUTES => $openingTag->getAttributes()
108        );
109
110
111    }
112
113    static public function renderEnterXhtml(TagAttributes $tagAttributes): string
114    {
115        $htmlTagName = $tagAttributes->getValueAndRemove(self::HTML_TAG_ATTRIBUTE, self::DEFAULT_HTML_TAG);
116        $logicalTag = $tagAttributes->getValueAndRemove(self::LOGICAL_TAG_ATTRIBUTE);
117        if ($logicalTag !== null) {
118            $tagAttributes->setLogicalTag($logicalTag);
119        }
120        return $tagAttributes->toHtmlEnterTag($htmlTagName);
121    }
122
123
124    static function renderExitXhtml(TagAttributes $tagAttributes): string
125    {
126        $tagName = $tagAttributes->getValueAndRemove(self::HTML_TAG_ATTRIBUTE, self::DEFAULT_HTML_TAG);
127        return "</$tagName>";
128    }
129
130
131}
132
133