xref: /plugin/combo/syntax/media.php (revision 9337a630db122fdba0294f47d72bdf5433c2bf10)
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::getModeFromTag(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::getModeFromTag($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                        /**
173                         * We don't support crop
174                         */
175                        $crop = false;
176                        if ($media->getRequestedWidth() != null && $media->getRequestedHeight() != null) {
177                            /**
178                             * Width of 0 = resizing by height (supported)
179                             */
180                            if ($media->getRequestedWidth() != "0") {
181                                $crop = true;
182                            }
183                        }
184                        if (!$crop) {
185                            $renderer->doc .= $media->renderMediaTagWithLink();
186                            return true;
187                        }
188                    }
189                }
190
191                /**
192                 * This is not an local internal media image (a video or an url image)
193                 * Dokuwiki takes over
194                 */
195                $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
196                $src = $attributes['src'];
197                $title = $attributes['title'];
198                $align = $attributes['align'];
199                $width = $attributes['width'];
200                $height = $attributes['height'];
201                $cache = $attributes['cache'];
202                if ($cache == null) {
203                    // Dokuwiki needs a value
204                    // If their is no value it will output it without any value
205                    // in the query string.
206                    $cache = "cache";
207                }
208                $linking = $attributes['linking'];
209                switch ($type) {
210                    case MediaLink::INTERNAL_MEDIA_CALL_NAME:
211                        $renderer->doc .= $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
212                        break;
213                    case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
214                        $renderer->doc .= $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
215                        break;
216                    default:
217                        LogUtility::msg("The dokuwiki media type ($type) is unknown");
218                        break;
219                }
220
221                return true;
222
223            case
224            "metadata":
225
226                /**
227                 * Keep track of the metadata
228                 * @var Doku_Renderer_metadata $renderer
229                 */
230                self::registerImageMeta($attributes, $renderer);
231                return true;
232
233        }
234        // unsupported $mode
235        return false;
236    }
237
238    /**
239     * @param array $attributes
240     * @param Doku_Renderer_metadata $renderer
241     */
242    static public function registerImageMeta($attributes, $renderer)
243    {
244        $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
245        $src = $attributes['src'];
246        if ($src == null) {
247            $src = $attributes[DokuPath::PATH_ATTRIBUTE];
248        }
249        $title = $attributes['title'];
250        $align = $attributes['align'];
251        $width = $attributes['width'];
252        $height = $attributes['height'];
253        $cache = $attributes['cache']; // Cache: https://www.dokuwiki.org/images#caching
254        $linking = $attributes['linking'];
255
256        switch ($type) {
257            case MediaLink::INTERNAL_MEDIA_CALL_NAME:
258                $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking);
259                break;
260            case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
261                $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking);
262                break;
263            default:
264                LogUtility::msg("The dokuwiki media type ($type)  for metadata registration is unknown");
265                break;
266        }
267
268    }
269
270
271}
272
273