1<?php
2
3namespace ComboStrap\Tag;
4
5use action_plugin_combo_instructionspostprocessing;
6use ComboStrap\CallStack;
7use ComboStrap\ContainerTag;
8use ComboStrap\DataType;
9use ComboStrap\EditButton;
10use ComboStrap\ExceptionBadArgument;
11use ComboStrap\ExceptionNotFound;
12use ComboStrap\ExecutionContext;
13use ComboStrap\TagAttribute\Hero;
14use ComboStrap\LogUtility;
15use ComboStrap\PluginUtility;
16use ComboStrap\SiteConfig;
17use ComboStrap\TagAttributes;
18
19/**
20 * Separator: See: https://getwaves.io/
21 *
22 * * horizontal block are known as section in mjml
23 */
24class BarTag
25{
26
27
28    public const SIZE_ATTRIBUTE = "size";
29    public const HTML_TAG_ATTRIBUTES = "html_tag";
30    public const CANONICAL = BarTag::SLIDE_TAG;
31    public const CONF_ENABLE_BAR_EDITING = "enableBarEditing";
32    public const SLIDE_TAG = "slide";
33    public const BAR_TAG = "bar";
34    public const HTML_SECTION_TAG = "section";
35    const LOGICAL_TAG = self::BAR_TAG;
36    public static $tags = [BarTag::BAR_TAG, BarTag::SLIDE_TAG];
37
38    public static function getHtmlTag(): string
39    {
40        $tag = "div";
41        try {
42            $isFragmentExecution = ExecutionContext::getActualOrCreateFromEnv()
43                ->getExecutingMarkupHandler()
44                ->isFragment();
45            if (!$isFragmentExecution) {
46                $tag = self::HTML_SECTION_TAG;
47            }
48            return $tag;
49        } catch (ExceptionNotFound $e) {
50            return $tag;
51        }
52    }
53
54    public static function handleEnter(TagAttributes $tagAttributes): array
55    {
56
57        $htmlTag = BarTag::getHtmlTag();
58
59        /**
60         * Deprecation
61         */
62        $size = $tagAttributes->getValueAndRemoveIfPresent(BarTag::SIZE_ATTRIBUTE);
63        if ($size !== null) {
64            LogUtility::warning("The size attribute on bar/slide has been deprecated for the hero attribute");
65            $tagAttributes->setComponentAttributeValue(Hero::ATTRIBUTE, $size);
66        }
67
68        return array(BarTag::HTML_TAG_ATTRIBUTES => $htmlTag);
69    }
70
71    public static function handleExit(\Doku_Handler $handler, int $pos, string $match): array
72    {
73        $callStack = CallStack::createFromHandler($handler);
74        $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
75
76        /**
77         * Section heading control
78         */
79        $htmlTag = $openingTag->getPluginData(BarTag::HTML_TAG_ATTRIBUTES);
80        $message = null;
81        if ($htmlTag === BarTag::HTML_SECTION_TAG) {
82            $headingFound = false;
83            while ($actualCall = $callStack->next()) {
84                if (in_array($actualCall->getTagName(), action_plugin_combo_instructionspostprocessing::HEADING_TAGS)) {
85                    $headingFound = true;
86                    break;
87                }
88            }
89            if (!$headingFound) {
90                $id = $openingTag->getIdOrDefault();
91                $message = "No heading was found in the section bar ($id). An heading is mandatory for navigation within device.";
92            }
93        }
94
95        if (SiteConfig::getConfValue(BarTag::CONF_ENABLE_BAR_EDITING, 1)) {
96
97            $position = $openingTag->getFirstMatchedCharacterPosition();
98            try {
99                $startPosition = DataType::toInteger($position);
100            } catch (ExceptionBadArgument $e) {
101                LogUtility::error("The position of the slide is not an integer", BarTag::CANONICAL);
102                $startPosition = null;
103            }
104            $id = $openingTag->getIdOrDefault();
105            // +1 to go at the line
106            $endPosition = $pos + strlen($match) + 1;
107            $tag = BarTag::BAR_TAG;
108            $editButtonCall = EditButton::create("Edit $tag $id")
109                ->setStartPosition($startPosition)
110                ->setEndPosition($endPosition)
111                ->toComboCallComboFormat();
112            $callStack->moveToEnd();
113            $callStack->insertBefore($editButtonCall);
114        }
115
116
117        return array(
118            BarTag::HTML_TAG_ATTRIBUTES => $htmlTag,
119            PluginUtility::EXIT_MESSAGE => $message
120        );
121    }
122
123    public static function renderEnterXhtml(TagAttributes $attributes, array $data): string
124    {
125        $barTag = BarTag::BAR_TAG;
126        $attributes->addClassName($barTag);
127
128        PluginUtility::getSnippetManager()->attachCssInternalStyleSheet($barTag);
129
130        $htmlTag = $data[BarTag::HTML_TAG_ATTRIBUTES];
131        $html = $attributes->toHtmlEnterTag($htmlTag);
132
133        $layoutContainer = SiteConfig::getConfValue(ContainerTag::DEFAULT_LAYOUT_CONTAINER_CONF, ContainerTag::DEFAULT_LAYOUT_CONTAINER_DEFAULT_VALUE);
134        $containerClass = ContainerTag::getClassName($layoutContainer);
135
136        $html .= "<div class=\"$barTag-body position-relative $containerClass\">";
137        return $html;
138    }
139
140    public static function renderExitXhtml(array $data): string
141    {
142        /**
143         * End body
144         */
145        $html = '</div>';
146
147        /**
148         * End component
149         */
150        $htmlTag = $data[BarTag::HTML_TAG_ATTRIBUTES];
151        $html .= "</$htmlTag>";
152        return $html;
153    }
154}
155