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