xref: /plugin/combo/syntax/cell.php (revision 531e725cdb5a652164f2d97f556304e31f720033)
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\ConditionalValue;
14use ComboStrap\PluginUtility;
15use ComboStrap\TagAttributes;
16
17
18require_once(__DIR__ . '/../class/PluginUtility.php');
19
20/**
21 * The {@link https://combostrap.com/column column} of a {@link https://combostrap.com/grid grid}
22 *
23 *
24 * Note: The name of the class must follow this pattern ie syntax_plugin_PluginName_ComponentName
25 */
26class syntax_plugin_combo_cell extends DokuWiki_Syntax_Plugin
27{
28
29    const TAG = "cell";
30
31    const WIDTH_ATTRIBUTE = TagAttributes::WIDTH_KEY;
32    const VERTICAL_ATTRIBUTE = "vertical";
33
34    static function getTags()
35    {
36        return [self::TAG, "col", "column"];
37    }
38
39    /**
40     * Syntax Type.
41     *
42     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
43     * @see DokuWiki_Syntax_Plugin::getType()
44     */
45    function getType()
46    {
47        return 'container';
48    }
49
50    /**
51     * @return array
52     * Allow which kind of plugin inside
53     * All
54     */
55    public function getAllowedTypes()
56    {
57        return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs');
58    }
59
60    public function accepts($mode)
61    {
62
63        /**
64         * header mode is disable to take over
65         * and replace it with {@link syntax_plugin_combo_heading}
66         */
67        if ($mode == "header") {
68            return false;
69        }
70
71
72        return syntax_plugin_combo_preformatted::disablePreformatted($mode);
73
74    }
75
76    /**
77     * How Dokuwiki will add P element
78     *
79     *  * 'normal' - The plugin can be used inside paragraphs
80     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
81     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
82     *
83     * @see DokuWiki_Syntax_Plugin::getPType()
84     */
85    function getPType()
86    {
87        return 'stack';
88    }
89
90    /**
91     * @see Doku_Parser_Mode::getSort()
92     *
93     * the mode with the lowest sort number will win out
94     * the container (parent) must then have a lower number than the child
95     */
96    function getSort()
97    {
98        return 100;
99    }
100
101    /**
102     * Create a pattern that will called this plugin
103     *
104     * @param string $mode
105     * @see Doku_Parser_Mode::connectTo()
106     */
107    function connectTo($mode)
108    {
109
110        // A cell can be anywhere
111        foreach (self::getTags() as $tag) {
112            $pattern = PluginUtility::getContainerTagPattern($tag);
113            $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent()));
114        }
115
116
117    }
118
119    public function postConnect()
120    {
121
122        foreach (self::getTags() as $tag) {
123            $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeForComponent($this->getPluginComponent()));
124        }
125
126    }
127
128    /**
129     *
130     * The handle function goal is to parse the matched syntax through the pattern function
131     * and to return the result for use in the renderer
132     * This result is always cached until the page is modified.
133     * @param string $match
134     * @param int $state
135     * @param int $pos
136     * @param Doku_Handler $handler
137     * @return array|bool
138     * @see DokuWiki_Syntax_Plugin::handle()
139     *
140     */
141    function handle($match, $state, $pos, Doku_Handler $handler)
142    {
143
144        switch ($state) {
145
146            case DOKU_LEXER_ENTER:
147
148                $attributes = TagAttributes::createFromTagMatch($match)->toCallStackArray();
149                return array(
150                    PluginUtility::STATE => $state,
151                    PluginUtility::ATTRIBUTES => $attributes);
152
153            case DOKU_LEXER_UNMATCHED:
154                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
155
156            case DOKU_LEXER_EXIT :
157
158                return array(
159                    PluginUtility::STATE => $state
160                );
161
162
163        }
164
165        return array();
166
167    }
168
169    /**
170     * Render the output
171     * @param string $format
172     * @param Doku_Renderer $renderer
173     * @param array $data - what the function handle() return'ed
174     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
175     * @see DokuWiki_Syntax_Plugin::render()
176     *
177     *
178     */
179    function render($format, Doku_Renderer $renderer, $data)
180    {
181
182        if ($format == 'xhtml') {
183
184            /** @var Doku_Renderer_xhtml $renderer */
185            $state = $data[PluginUtility::STATE];
186            switch ($state) {
187
188                case DOKU_LEXER_ENTER :
189
190                    PluginUtility::getSnippetManager()->attachCssSnippetForBar(self::TAG);
191                    $callStackArray = $data[PluginUtility::ATTRIBUTES];
192                    $attributes = TagAttributes::createFromCallStackArray($callStackArray, self::TAG);
193                    $attributes->addClassName("col");
194                    if ($attributes->hasComponentAttribute(self::VERTICAL_ATTRIBUTE)) {
195                        $value = $attributes->getValue(self::VERTICAL_ATTRIBUTE);
196                        if ($value == "center") {
197                            //$attributes->addClassName("d-inline-flex");
198                            $attributes->addClassName("align-self-center");
199                        }
200                    }
201                    if ($attributes->hasComponentAttribute(syntax_plugin_combo_cell::WIDTH_ATTRIBUTE)) {
202                        $sizeValues = $attributes->getValuesAndRemove(syntax_plugin_combo_cell::WIDTH_ATTRIBUTE);
203                        foreach ($sizeValues as $sizeValue) {
204                            $conditionalValue = ConditionalValue::createFrom($sizeValue);
205                            if ($conditionalValue->getBreakpoint() == "xs") {
206                                $attributes->addClassName("col-" . $conditionalValue->getValue());
207                            } else {
208                                if ($conditionalValue->getBreakpoint() != null) {
209                                    $attributes->addClassName("col-$sizeValue");
210                                } else {
211                                    /**
212                                     * No breakpoint given
213                                     * If this is a number between 1 and 12,
214                                     * we take the assumption that this is a ratio
215                                     * otherwise, this a width in CSS length
216                                     */
217                                    if ($sizeValue >= 1 && $sizeValue <= syntax_plugin_combo_row::GRID_TOTAL_COLUMNS) {
218                                        $attributes->addClassName("col-$sizeValue");
219                                    } else {
220                                        $attributes->addComponentAttributeValue(TagAttributes::WIDTH_KEY, $sizeValue);
221                                    }
222                                }
223                            }
224                        }
225                    }
226                    $renderer->doc .= $attributes->toHtmlEnterTag("div") . DOKU_LF;
227                    break;
228
229                case DOKU_LEXER_UNMATCHED :
230
231                    $renderer->doc .= PluginUtility::renderUnmatched($data);
232                    break;
233
234                case DOKU_LEXER_EXIT :
235
236                    $renderer->doc .= '</div>' . DOKU_LF;
237                    break;
238            }
239            return true;
240        }
241        return false;
242    }
243
244
245}
246