1<?php
2/**
3 * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved.
4 *
5 * This source code is licensed under the GPL license found in the
6 * COPYING  file in the root directory of this source tree.
7 *
8 * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
9 * @author   ComboStrap <support@combostrap.com>
10 *
11 */
12
13use ComboStrap\Call;
14use ComboStrap\CallStack;
15use ComboStrap\Dimension;
16use ComboStrap\GridTag;
17use ComboStrap\LogUtility;
18use ComboStrap\PluginUtility;
19use ComboStrap\Tag\BoxTag;
20use ComboStrap\TagAttributes;
21use ComboStrap\XmlTagProcessing;
22
23
24require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
25
26/**
27 *
28 *
29 *
30 * @deprecated - flex item are created now with the {@link \ComboStrap\TagAttribute\Align} attribute
31 * and the col class is set now on the row class.
32 */
33class syntax_plugin_combo_cell extends DokuWiki_Syntax_Plugin
34{
35
36    const TAG = "cell";
37
38    const WIDTH_ATTRIBUTE = Dimension::WIDTH_KEY;
39    const FLEX_CLASS = "d-flex";
40
41
42    static function getTags(): array
43    {
44        return [self::TAG, "col", "column"];
45    }
46
47    /**
48     * Syntax Type.
49     *
50     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
51     * @see DokuWiki_Syntax_Plugin::getType()
52     */
53    function getType(): string
54    {
55        return 'container';
56    }
57
58    /**
59     * @return array
60     * Allow which kind of plugin inside
61     * All
62     */
63    public function getAllowedTypes(): array
64    {
65        return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs');
66    }
67
68    public function accepts($mode): bool
69    {
70
71        /**
72         * header mode is disable to take over
73         * and replace it with {@link syntax_plugin_combo_heading}
74         */
75        if ($mode == "header") {
76            return false;
77        }
78
79
80        return syntax_plugin_combo_preformatted::disablePreformatted($mode);
81
82    }
83
84    /**
85     * How Dokuwiki will add P element
86     *
87     *  * 'normal' - The plugin can be used inside paragraphs
88     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
89     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
90     *
91     * @see DokuWiki_Syntax_Plugin::getPType()
92     */
93    function getPType()
94    {
95        return 'stack';
96    }
97
98    /**
99     * @see Doku_Parser_Mode::getSort()
100     *
101     * the mode with the lowest sort number will win out
102     * the container (parent) must then have a lower number than the child
103     */
104    function getSort()
105    {
106        return 100;
107    }
108
109    /**
110     * Create a pattern that will called this plugin
111     *
112     * @param string $mode
113     * @see Doku_Parser_Mode::connectTo()
114     */
115    function connectTo($mode)
116    {
117
118        // A cell can be anywhere
119        foreach (self::getTags() as $tag) {
120            $pattern = XmlTagProcessing::getContainerTagPattern($tag);
121            $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
122        }
123
124
125    }
126
127    public function postConnect()
128    {
129
130        foreach (self::getTags() as $tag) {
131            $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeFromTag($this->getPluginComponent()));
132        }
133
134    }
135
136    /**
137     *
138     * The handle function goal is to parse the matched syntax through the pattern function
139     * and to return the result for use in the renderer
140     * This result is always cached until the page is modified.
141     * @param string $match
142     * @param int $state
143     * @param int $pos
144     * @param Doku_Handler $handler
145     * @return array|bool
146     * @see DokuWiki_Syntax_Plugin::handle()
147     *
148     */
149    function handle($match, $state, $pos, Doku_Handler $handler)
150    {
151
152        switch ($state) {
153
154            case DOKU_LEXER_ENTER:
155
156                $knownTypes = [];
157                $defaultAttributes = [];
158                $attributes = TagAttributes::createFromTagMatch($match, $defaultAttributes, $knownTypes)->toCallStackArray();
159
160                LogUtility::warning("Cell (Col) has been deprecated for box (You can use now any component in a grid or row).", GridTag::TAG);
161                return array(
162                    PluginUtility::STATE => $state,
163                    PluginUtility::ATTRIBUTES => $attributes);
164
165            case DOKU_LEXER_UNMATCHED:
166                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
167
168            case DOKU_LEXER_EXIT :
169
170                $callStack = CallStack::createFromHandler($handler);
171                $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
172                $firstChild = $callStack->moveToFirstChildTag();
173
174                /**
175                 * A cell is a flex container that helps place its children
176                 * It should contain one or more container
177                 * It should have at minimum one
178                 */
179                $addChildContainer = true;
180                if ($firstChild !== false) {
181                    if (in_array($firstChild->getTagName(), TagAttributes::CONTAINER_LOGICAL_ELEMENTS)) {
182                        $addChildContainer = false;
183                    }
184                }
185                if ($addChildContainer === true) {
186                    /**
187                     * A cell should have one or more container as child
188                     * If the container is not in the markup, we add it
189                     */
190                    $callStack->moveToCall($openingTag);
191                    $callStack->insertAfter(
192                        Call::createComboCall(
193                            BoxTag::TAG,
194                            DOKU_LEXER_ENTER,
195                            [],
196                            null,
197                            null,
198                            null,
199                            null,
200                            \syntax_plugin_combo_xmlblocktag::TAG
201                        ));
202                    $callStack->moveToEnd();
203                    $callStack->insertBefore(
204                        Call::createComboCall(
205                            BoxTag::TAG,
206                            DOKU_LEXER_EXIT,
207                            [],
208                            null,
209                            null,
210                            null,
211                            null,
212                            \syntax_plugin_combo_xmlblocktag::TAG
213                        ));
214                }
215
216
217                return array(
218                    PluginUtility::STATE => $state
219                );
220
221
222        }
223
224        return array();
225
226    }
227
228    /**
229     * Render the output
230     * @param string $format
231     * @param Doku_Renderer $renderer
232     * @param array $data - what the function handle() return'ed
233     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
234     * @see DokuWiki_Syntax_Plugin::render()
235     *
236     *
237     */
238    function render($format, Doku_Renderer $renderer, $data): bool
239    {
240
241        if ($format == 'xhtml') {
242
243            /** @var Doku_Renderer_xhtml $renderer */
244            $state = $data[PluginUtility::STATE];
245            switch ($state) {
246
247                case DOKU_LEXER_ENTER :
248
249                    PluginUtility::getSnippetManager()->attachCssInternalStyleSheet(self::TAG);
250                    $callStackArray = $data[PluginUtility::ATTRIBUTES];
251                    $attributes = TagAttributes::createFromCallStackArray($callStackArray, self::TAG);
252                    /**
253                     * A flex to be able to align the children (horizontal/vertical)
254                     * if they are constraint in width
255                     */
256                    $attributes->addClassName(self::FLEX_CLASS);
257                    /**
258                     * Horizontal (center)
259                     */
260                    $attributes->addClassName("justify-content-center");
261
262                    $renderer->doc .= $attributes->toHtmlEnterTag("div");
263                    break;
264
265                case DOKU_LEXER_UNMATCHED :
266
267                    $renderer->doc .= PluginUtility::renderUnmatched($data);
268                    break;
269
270                case DOKU_LEXER_EXIT :
271
272                    $renderer->doc .= '</div>';
273                    break;
274            }
275            return true;
276        }
277        return false;
278    }
279
280
281}
282