1<?php
2
3namespace dokuwiki\plugin\struct\types;
4
5use dokuwiki\plugin\struct\meta\ValidationException;
6
7class Media extends AbstractBaseType
8{
9    protected $config = [
10        'mime' => 'image/',
11        'width' => 90,
12        'height' => 90,
13        'agg_width' => '',
14        'agg_height' => ''
15    ];
16
17    /**
18     * Checks against the allowed mime types
19     *
20     * @param string $rawvalue
21     * @return int|string
22     */
23    public function validate($rawvalue)
24    {
25        $rawvalue = parent::validate($rawvalue);
26
27        if (!trim($this->config['mime'])) return $rawvalue;
28        $allows = explode(',', $this->config['mime']);
29        $allows = array_map('trim', $allows);
30        $allows = array_filter($allows);
31
32        [, $mime, ] = mimetype($rawvalue, false);
33        foreach ($allows as $allow) {
34            if (strpos($mime, $allow) === 0) return $rawvalue;
35        }
36
37        throw new ValidationException('Media mime type', $mime, $this->config['mime']);
38    }
39
40    /**
41     * Output the stored data
42     *
43     * If outputted in an aggregation we collect the images into a gallery.
44     *
45     * @param string|int $value the value stored in the database
46     * @param \Doku_Renderer $R the renderer currently used to render the data
47     * @param string $mode The mode the output is rendered in (eg. XHTML)
48     * @return bool true if $mode could be satisfied
49     */
50    public function renderValue($value, \Doku_Renderer $R, $mode)
51    {
52        // get width and height from config
53        $width = null;
54        $height = null;
55        if ($this->config['width']) $width = $this->config['width'];
56        if ($this->config['height']) $height = $this->config['height'];
57        if (!empty($R->info['struct_table_hash'])) {
58            // this is an aggregation, check for special values
59            if ($this->config['agg_width']) $width = $this->config['agg_width'];
60            if ($this->config['agg_height']) $height = $this->config['agg_height'];
61        }
62        $html = '';
63        if (!media_isexternal($value)) {
64            if (is_a($R, '\Doku_Renderer_xhtml')) {
65                /** @var \Doku_Renderer_xhtml $R */
66                $html = $R->internalmedia($value, null, null, $width, $height, null, 'direct', true);
67            } else {
68                $R->internalmedia($value, null, null, $width, $height, null, 'direct');
69            }
70        } elseif (is_a($R, '\Doku_Renderer_xhtml')) {
71            /** @var \Doku_Renderer_xhtml $R */
72            $html = $R->externalmedia($value, null, null, $width, $height, null, 'direct', true);
73        } else {
74            $R->externalmedia($value, null, null, $width, $height, null, 'direct');
75        }
76
77        // add gallery meta data in XHTML
78        if ($mode == 'xhtml') {
79            [, $mime, ] = mimetype($value, false);
80            if (substr($mime, 0, 6) == 'image/') {
81                $hash = empty($R->info['struct_table_hash']) ? '' : "[gal-" . $R->info['struct_table_hash'] . "]";
82                $html = str_replace('href', "rel=\"lightbox$hash\" href", $html);
83            }
84            $R->doc .= $html;
85        }
86
87        return true;
88    }
89
90    /**
91     * Return the editor to edit a single value
92     *
93     * @param string $name the form name where this has to be stored
94     * @param string $rawvalue the current value
95     *
96     * @param string $htmlID
97     *
98     * @return string html
99     */
100    public function valueEditor($name, $rawvalue, $htmlID)
101    {
102        static $count = 0;
103        $count++;
104
105        $id = $htmlID ?: 'struct__' . md5($name . $count);
106
107        $params = [
108            'name' => $name,
109            'value' => $rawvalue,
110            'class' => 'struct_media',
111            'id' => $id
112        ];
113        $attributes = buildAttributes($params, true);
114        $html = "<input $attributes />";
115        $html .= "<button type=\"button\" class=\"struct_media\">";
116        $html .= "<img src=\"" . DOKU_BASE . "lib/images/toolbar/image.png\" height=\"16\" width=\"16\">";
117        $html .= "</button>";
118        return $html;
119    }
120
121    /**
122     * @inheritDoc
123     */
124    public function renderTagCloudLink($value, \Doku_Renderer $R, $mode, $page, $filter, $weight, $showCount = null)
125    {
126        $media = $this->displayValue($value);
127        if ($mode == 'xhtml' && $this->getConfig()['mime'] == 'image/') {
128            $url = wl($page, $filter);
129            $image = ml($media, ['h' => $weight, 'w' => $weight]);
130            $media_escaped = hsc($media);
131            $R->doc .= "<div style=\"height:{$weight}px; width:{$weight}px\">";
132            $R->doc .= "<a href='$url' class='struct_image' style='background-image:url(\"$image\")'
133                        title='$media_escaped'>";
134            $R->doc .= "<span class='a11y'>$media_escaped</span>";
135            $R->doc .= "</a>";
136            $R->doc .= "</div>";
137            return;
138        }
139        $R->internallink("$page?$filter", $media);
140    }
141}
142