1<?php
2
3
4use ComboStrap\Tag;
5use ComboStrap\PluginUtility;
6
7require_once(__DIR__ . '/../ComboStrap/Tag.php');
8
9/**
10 * Just a node to test the {@link Tag} context
11 * This is not public
12 *
13 * TODO: Move this in the test class
14 */
15class syntax_plugin_combo_tag extends DokuWiki_Syntax_Plugin
16{
17
18    const TAG = "tag";
19
20
21    /**
22     * Syntax Type.
23     *
24     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php
25     * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types
26     * @see DokuWiki_Syntax_Plugin::getType()
27     */
28    function getType()
29    {
30        return 'container';
31    }
32
33    /**
34     * How Dokuwiki will add P element
35     *
36     *  * 'normal' - The plugin can be used inside paragraphs (inline)
37     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
38     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
39     *
40     * @see DokuWiki_Syntax_Plugin::getPType()
41     * @see https://www.dokuwiki.org/devel:syntax_plugins#ptype
42     */
43    function getPType()
44    {
45        return 'block';
46    }
47
48    /**
49     * @return array
50     * Allow which kind of plugin inside
51     *
52     * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
53     * because we manage self the content and we call self the parser
54     *
55     * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php
56     */
57    function getAllowedTypes()
58    {
59        return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs');
60    }
61
62    function getSort()
63    {
64        return 201;
65    }
66
67
68    function connectTo($mode)
69    {
70
71        $pattern = PluginUtility::getContainerTagPattern(self::TAG);
72        $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
73        $this->Lexer->addSpecialPattern(PluginUtility::getEmptyTagPattern(self::TAG), $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
74
75    }
76
77    function postConnect()
78    {
79
80        $this->Lexer->addExitPattern('</' . self::TAG . '>', PluginUtility::getModeFromTag($this->getPluginComponent()));
81
82    }
83
84    /**
85     *
86     * The handle function goal is to parse the matched syntax through the pattern function
87     * and to return the result for use in the renderer
88     * This result is always cached until the page is modified.
89     * @param string $match
90     * @param int $state
91     * @param int $pos - byte position in the original source file
92     * @param Doku_Handler $handler
93     * @return array|bool
94     * @throws Exception
95     * @see DokuWiki_Syntax_Plugin::handle()
96     *
97     */
98    function handle($match, $state, $pos, Doku_Handler $handler)
99    {
100
101        switch ($state) {
102
103            case DOKU_LEXER_ENTER :
104                $attributes = PluginUtility::getTagAttributes($match);
105                $tag = new Tag(self::TAG, $attributes, $state, $handler);
106                $attributes['name'] = $tag->getName();
107                $attributes['type'] = $tag->getType();
108                $attributes['parent'] = $tag->getParent()->getName();;
109                $attributes['parent-type'] = $tag->getParent()->getType();;
110                $attributes['child-of-blockquote'] = $tag->isChildOf("blockquote");
111                $attributes['descendant-of-card'] = $tag->isDescendantOf("card");
112                $attributes['has-siblings'] = $tag->hasSiblings();
113                $attributes['first-sibling'] = $tag->getPreviousSibling() !== null ? $tag->getPreviousSibling()->getName() : false;
114
115                $payload = '<tag-enter type="' . $attributes['type'] . '" ' . PluginUtility::array2HTMLAttributesAsString($attributes) . '></tag-enter>';
116
117                /**
118                 * Attributes needs to be given
119                 * in order to save it in the call stack
120                 */
121                return array(
122                    PluginUtility::STATE => $state,
123                    PluginUtility::PAYLOAD => $payload,
124                    PluginUtility::ATTRIBUTES => $attributes
125                );
126
127            case DOKU_LEXER_UNMATCHED :
128                $tag = new Tag(self::TAG, array(), $state, $handler);
129                $attributes['name'] = $tag->getName();
130                $attributes['type'] = $tag->getParent()->getType();
131                $attributes['parent'] = $tag->getParent()->getName();;
132                $attributes['parent-type'] = $tag->getParent()->getType();
133                $attributes['child-of-blockquote'] = $tag->isChildOf("blockquote");
134                $attributes['descendant-of-card'] = $tag->isDescendantOf("card");
135                $attributes['has-siblings'] = $tag->hasSiblings();
136                $attributes['first-sibling'] = $tag->getPreviousSibling() !== null ? $tag->getPreviousSibling() : false;
137                $payload = '<tag-unmatched type="' . $attributes['type'] . '" ' . PluginUtility::array2HTMLAttributesAsString($attributes) . '></tag-unmatched>';
138                return array(
139                    PluginUtility::STATE => $state,
140                    PluginUtility::PAYLOAD => $payload
141                );
142
143            case DOKU_LEXER_SPECIAL :
144
145                $tag = new Tag(self::TAG, PluginUtility::getTagAttributes($match), $state, $handler);
146                $attributes['name'] = $tag->getName();
147                $attributes['type'] = $tag->getType();
148                $attributes['parent'] = $tag->getParent()->getName();;
149                $attributes['parent-type'] = $tag->getParent()->getType();;
150                $attributes['child-of-blockquote'] = $tag->isChildOf("blockquote");
151                $attributes['descendant-of-card'] = $tag->isDescendantOf("card");
152                $attributes['has-siblings'] = $tag->hasSiblings();
153                $attributes['first-sibling'] = $tag->getPreviousSibling()->getName();
154                $payload = '<tag-special type="' . $attributes['type'] . '" ' . PluginUtility::array2HTMLAttributesAsString($attributes) . '></tag-special>';
155                return array(
156                    PluginUtility::STATE => $state,
157                    PluginUtility::PAYLOAD => $payload
158                );
159
160            case DOKU_LEXER_EXIT :
161
162                $tag = new Tag(self::TAG, array(), $state, $handler);
163                $attributes['name'] = $tag->getName();
164                $attributes['type'] = $tag->getType();
165                $attributes['parent'] = $tag->getParent()->getName();;
166                $attributes['parent-type'] = $tag->getParent()->getType();;
167                $attributes['child-of-blockquote'] = $tag->isChildOf("blockquote");
168                $attributes['descendant-of-card'] = $tag->isDescendantOf("card");
169                $attributes['has-siblings'] = $tag->hasSiblings();
170                $attributes['first-sibling'] = $tag->getPreviousSibling() !== null ? $tag->getPreviousSibling()->getName() : false;
171                $openingTag = $tag->getOpeningTag();
172                $attributes['has-descendants'] = $openingTag->hasDescendants();
173                $attributes['descendants-count'] = sizeof($openingTag->getDescendants());
174                $badgeTag = $openingTag->getDescendant("badge");
175                $attributes['has-badge-descendant'] = $badgeTag !== null;
176                $attributes['badge-content'] = $badgeTag !== null ? $badgeTag->getContentRecursively() : "";
177                $payload = '<tag-exit type="' . $attributes['type'] . '" ' . PluginUtility::array2HTMLAttributesAsString($attributes) . '></tag-exit>';
178                return array(
179                    PluginUtility::STATE => $state,
180                    PluginUtility::PAYLOAD => $payload
181                );
182
183
184        }
185        return array();
186
187    }
188
189    /**
190     * Render the output
191     * @param string $format
192     * @param Doku_Renderer $renderer
193     * @param array $data - what the function handle() return'ed
194     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
195     * @see DokuWiki_Syntax_Plugin::render()
196     *
197     *
198     */
199    function render($format, Doku_Renderer $renderer, $data)
200    {
201        if ($format == 'xhtml') {
202
203            /** @var Doku_Renderer_xhtml $renderer */
204            $state = $data["state"];
205            switch ($state) {
206                case DOKU_LEXER_UNMATCHED:
207                case DOKU_LEXER_ENTER :
208                case DOKU_LEXER_SPECIAL:
209                case DOKU_LEXER_EXIT :
210                    $renderer->doc .= $data[PluginUtility::PAYLOAD];
211                    break;
212
213            }
214            return true;
215        }
216
217        // unsupported $mode
218        return false;
219    }
220
221
222}
223
224