xref: /plugin/combo/syntax/media.php (revision a6bf47aa01c4ea7d24944b0e48eb1943151e3c25)
1<?php
2
3
4use ComboStrap\DokuPath;
5use ComboStrap\LogUtility;
6use ComboStrap\MediaLink;
7use ComboStrap\PluginUtility;
8use ComboStrap\Tag;
9
10
11if (!defined('DOKU_INC')) die();
12
13
14/**
15 * Media
16 *
17 * Takes over the {@link \dokuwiki\Parsing\ParserMode\Media media mode}
18 * that is processed by {@link Doku_Handler_Parse_Media}
19 *
20 *
21 *
22 * It can be a internal / external media
23 */
24class syntax_plugin_combo_media extends DokuWiki_Syntax_Plugin
25{
26
27
28    const TAG = "media";
29
30    /**
31     * Used in the move plugin
32     * !!! The two last word of the plugin class !!!
33     */
34    const COMPONENT = 'combo_' . self::TAG;
35
36    /**
37     * The attribute that defines if the image is the first image in
38     * the component
39     *
40     */
41    const IS_FIRST_IMAGE_KEY = "isFirstImage";
42
43    /**
44     * Found at {@link \dokuwiki\Parsing\ParserMode\Media}
45     */
46    const MEDIA_PATTERN = "\{\{(?:[^>\}]|(?:\}[^\}]))+\}\}";
47
48    /**
49     * Enable or disable the image
50     */
51    const CONF_IMAGE_ENABLE = "imageEnable";
52
53
54    function getType()
55    {
56        return 'formatting';
57    }
58
59    /**
60     * How Dokuwiki will add P element
61     *
62     *  * 'normal' - The plugin can be used inside paragraphs (inline)
63     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
64     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
65     *
66     * @see DokuWiki_Syntax_Plugin::getPType()
67     */
68    function getPType()
69    {
70        /**
71         * An image is not a block (it can be inside paragraph)
72         */
73        return 'normal';
74    }
75
76    function getAllowedTypes()
77    {
78        return array('substition', 'formatting', 'disabled');
79    }
80
81    /**
82     * It should be less than {@link \dokuwiki\Parsing\ParserMode\Media::getSort()}
83     * (It was 320 at the time of writing this code)
84     * @return int
85     *
86     */
87    function getSort()
88    {
89        return 319;
90    }
91
92
93    function connectTo($mode)
94    {
95        $enable = $this->getConf(self::CONF_IMAGE_ENABLE, 1);
96        if (!$enable) {
97
98            // Inside a card, we need to take over and enable it
99            $modes = [
100                PluginUtility::getModeForComponent(syntax_plugin_combo_card::TAG),
101            ];
102            $enable = in_array($mode, $modes);
103        }
104
105        if ($enable) {
106            $this->Lexer->addSpecialPattern(self::MEDIA_PATTERN, $mode, PluginUtility::getModeForComponent($this->getPluginComponent()));
107        }
108    }
109
110
111    function handle($match, $state, $pos, Doku_Handler $handler)
112    {
113
114        switch ($state) {
115
116
117            // As this is a container, this cannot happens but yeah, now, you know
118            case DOKU_LEXER_SPECIAL :
119                $media = MediaLink::createFromRenderMatch($match);
120                $attributes = $media->toCallStackArray();
121                $tag = new Tag(self::TAG, $attributes, $state, $handler);
122                $parent = $tag->getParent();
123                $parentTag = "";
124                if (!empty($parent)) {
125                    $parentTag = $parent->getName();
126                    if ($parentTag == syntax_plugin_combo_link::TAG) {
127                        /**
128                         * The image is in a link, we don't want another link
129                         * to the image
130                         */
131                        $attributes[MediaLink::LINKING_KEY] = MediaLink::LINKING_NOLINK_VALUE;
132                    }
133                }
134                $isFirstSibling = $tag->isFirstMeaningFullSibling();
135                return array(
136                    PluginUtility::STATE => $state,
137                    PluginUtility::ATTRIBUTES => $attributes,
138                    PluginUtility::CONTEXT => $parentTag,
139                    self::IS_FIRST_IMAGE_KEY => $isFirstSibling
140                );
141
142
143        }
144        return array();
145
146    }
147
148    /**
149     * Render the output
150     * @param string $format
151     * @param Doku_Renderer $renderer
152     * @param array $data - what the function handle() return'ed
153     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
154     * @see DokuWiki_Syntax_Plugin::render()
155     *
156     *
157     */
158    function render($format, Doku_Renderer $renderer, $data)
159    {
160
161        $attributes = $data[PluginUtility::ATTRIBUTES];
162        switch ($format) {
163
164            case 'xhtml':
165
166                /** @var Doku_Renderer_xhtml $renderer */
167                $attributes = $data[PluginUtility::ATTRIBUTES];
168                $media = MediaLink::createFromCallStackArray($attributes);
169                if ($media->getScheme() == DokuPath::LOCAL_SCHEME) {
170                    $media = MediaLink::createFromCallStackArray($attributes, $renderer->date_at);
171                    if ($media->isImage()) {
172                        $renderer->doc .= $media->renderMediaTagWithLink();
173                        return true;
174                    }
175                }
176
177                /**
178                 * This is not an local internal media image (a video or an url image)
179                 * Dokuwiki takes over
180                 */
181                $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
182                $src = $attributes['src'];
183                $title = $attributes['title'];
184                $align = $attributes['align'];
185                $width = $attributes['width'];
186                $height = $attributes['height'];
187                $cache = $attributes['cache'];
188                if ($cache == null) {
189                    // Dokuwiki needs a value
190                    // If their is no value it will output it without any value
191                    // in the query string.
192                    $cache = "cache";
193                }
194                $linking = $attributes['linking'];
195                switch ($type) {
196                    case MediaLink::INTERNAL_MEDIA_CALL_NAME:
197                        $renderer->doc .= $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
198                        break;
199                    case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
200                        $renderer->doc .= $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
201                        break;
202                    default:
203                        LogUtility::msg("The dokuwiki media type ($type) is unknown");
204                        break;
205                }
206
207                return true;
208
209            case "metadata":
210
211                /**
212                 * Keep track of the metadata
213                 * @var Doku_Renderer_metadata $renderer
214                 */
215                self::registerImageMeta($attributes, $renderer);
216                return true;
217
218        }
219        // unsupported $mode
220        return false;
221    }
222
223    /**
224     * @param array $attributes
225     * @param Doku_Renderer_metadata $renderer
226     */
227    static public function registerImageMeta($attributes, $renderer)
228    {
229        $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
230        $src = $attributes['src'];
231        if ($src == null) {
232            $src = $attributes[DokuPath::PATH_ATTRIBUTE];
233        }
234        $title = $attributes['title'];
235        $align = $attributes['align'];
236        $width = $attributes['width'];
237        $height = $attributes['height'];
238        $cache = $attributes['cache']; // Cache: https://www.dokuwiki.org/images#caching
239        $linking = $attributes['linking'];
240
241        switch ($type) {
242            case MediaLink::INTERNAL_MEDIA_CALL_NAME:
243                $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking);
244                break;
245            case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
246                $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking);
247                break;
248            default:
249                LogUtility::msg("The dokuwiki media type ($type)  for metadata registration is unknown");
250                break;
251        }
252
253    }
254
255
256}
257
258