xref: /dokuwiki/inc/Parsing/ParserMode/Media.php (revision 504c13e8df88563c11b3720b317991bc38835a35)
1<?php
2
3namespace dokuwiki\Parsing\ParserMode;
4
5use dokuwiki\Parsing\Handler;
6
7class Media extends AbstractMode
8{
9    /** @inheritdoc */
10    public function getSort()
11    {
12        return 320;
13    }
14
15    /** @inheritdoc */
16    public function connectTo($mode)
17    {
18        // Word boundaries?
19        $this->Lexer->addSpecialPattern("\{\{(?:[^\}]|(?:\}[^\}]))+\}\}", $mode, 'media');
20    }
21
22    /** @inheritdoc */
23    public function handle($match, $state, $pos, Handler $handler)
24    {
25        $p = self::parseMedia($match);
26
27        $handler->addCall(
28            $p['type'],
29            [$p['src'], $p['title'], $p['align'], $p['width'], $p['height'], $p['cache'], $p['linking']],
30            $pos
31        );
32        return true;
33    }
34
35    /**
36     * Parse media syntax into its components
37     *
38     * @param string $match The full media syntax (e.g. {{image.png?200|title}})
39     * @return array Parsed media parameters (type, src, title, align, width, height, cache, linking)
40     */
41    public static function parseMedia($match)
42    {
43        // Strip the opening and closing markup
44        $link = preg_replace(['/^\{\{/', '/\}\}$/u'], '', $match);
45
46        // Split title from URL
47        $link = sexplode('|', $link, 2);
48
49        // Check alignment
50        $ralign = (bool)preg_match('/^ /', $link[0]);
51        $lalign = (bool)preg_match('/ $/', $link[0]);
52
53        // Logic = what's that ;)...
54        if ($lalign & $ralign) {
55            $align = 'center';
56        } elseif ($ralign) {
57            $align = 'right';
58        } elseif ($lalign) {
59            $align = 'left';
60        } else {
61            $align = null;
62        }
63
64        // The title...
65        if (!isset($link[1])) {
66            $link[1] = null;
67        }
68
69        //remove aligning spaces
70        $link[0] = trim($link[0]);
71
72        //split into src and parameters (using the very last questionmark)
73        $pos = strrpos($link[0], '?');
74        if ($pos !== false) {
75            $src = substr($link[0], 0, $pos);
76            $param = substr($link[0], $pos + 1);
77        } else {
78            $src = $link[0];
79            $param = '';
80        }
81
82        //parse width and height
83        if (preg_match('#(\d+)(x(\d+))?#i', $param, $size)) {
84            $w = empty($size[1]) ? null : $size[1];
85            $h = empty($size[3]) ? null : $size[3];
86        } else {
87            $w = null;
88            $h = null;
89        }
90
91        //get linking command
92        if (preg_match('/nolink/i', $param)) {
93            $linking = 'nolink';
94        } elseif (preg_match('/direct/i', $param)) {
95            $linking = 'direct';
96        } elseif (preg_match('/linkonly/i', $param)) {
97            $linking = 'linkonly';
98        } else {
99            $linking = 'details';
100        }
101
102        //get caching command
103        if (preg_match('/(nocache|recache)/i', $param, $cachemode)) {
104            $cache = $cachemode[1];
105        } else {
106            $cache = 'cache';
107        }
108
109        // Check whether this is a local or remote image or interwiki
110        if (media_isexternal($src) || link_isinterwiki($src)) {
111            $call = 'externalmedia';
112        } else {
113            $call = 'internalmedia';
114        }
115
116        return [
117            'type' => $call,
118            'src' => $src,
119            'title' => $link[1],
120            'align' => $align,
121            'width' => $w,
122            'height' => $h,
123            'cache' => $cache,
124            'linking' => $linking
125        ];
126    }
127}
128