xref: /plugin/diagrams/syntax/mediafile.php (revision 37a5d4110ff9b85c8f14c9d7b2faecb6d5da93ce)
18c8c7007SAndreas Gohr<?php
28c8c7007SAndreas Gohr
359e7180eSAndreas Gohruse dokuwiki\plugin\diagrams\Diagrams;
459e7180eSAndreas Gohr
58c8c7007SAndreas Gohr/**
68c8c7007SAndreas Gohr * Class syntax_plugin_diagrams
78c8c7007SAndreas Gohr */
8fa6a636cSAndreas Gohrclass syntax_plugin_diagrams_mediafile extends DokuWiki_Syntax_Plugin
9fa6a636cSAndreas Gohr{
108c8c7007SAndreas Gohr
118c8c7007SAndreas Gohr    /**
128c8c7007SAndreas Gohr     * @inheritdoc
138c8c7007SAndreas Gohr     */
148c8c7007SAndreas Gohr    public function getType()
158c8c7007SAndreas Gohr    {
168c8c7007SAndreas Gohr        return 'substition';
178c8c7007SAndreas Gohr    }
188c8c7007SAndreas Gohr
198c8c7007SAndreas Gohr    /**
208c8c7007SAndreas Gohr     * @inheritdoc
218c8c7007SAndreas Gohr     */
228c8c7007SAndreas Gohr    public function getSort()
238c8c7007SAndreas Gohr    {
248c8c7007SAndreas Gohr        return 319;
258c8c7007SAndreas Gohr    }
268c8c7007SAndreas Gohr
278c8c7007SAndreas Gohr    /**
288c8c7007SAndreas Gohr     * @inheritdoc
298c8c7007SAndreas Gohr     */
308c8c7007SAndreas Gohr    public function connectTo($mode)
318c8c7007SAndreas Gohr    {
3259e7180eSAndreas Gohr        // only register if mediafile mode is enabled
3359e7180eSAndreas Gohr        if (!($this->getConf('mode') & Diagrams::MODE_MEDIA)) return;
3459e7180eSAndreas Gohr
35fa6a636cSAndreas Gohr        // grab all SVG images
368c8c7007SAndreas Gohr        $this->Lexer->addSpecialPattern('\{\{[^\}]+(?:\.svg)[^\}]*?\}\}', $mode, 'plugin_diagrams_mediafile');
378c8c7007SAndreas Gohr    }
388c8c7007SAndreas Gohr
398c8c7007SAndreas Gohr    /**
408c8c7007SAndreas Gohr     * Parse SVG syntax into media data
418c8c7007SAndreas Gohr     *
428c8c7007SAndreas Gohr     * @param string $match
438c8c7007SAndreas Gohr     * @param int $state
448c8c7007SAndreas Gohr     * @param int $pos
458c8c7007SAndreas Gohr     * @param Doku_Handler $handler
468c8c7007SAndreas Gohr     * @return array|bool
478c8c7007SAndreas Gohr     */
488c8c7007SAndreas Gohr    public function handle($match, $state, $pos, Doku_Handler $handler)
498c8c7007SAndreas Gohr    {
50046ca144SAndreas Gohr        $data = Doku_Handler_Parse_Media($match);
51fa6a636cSAndreas Gohr
52fa6a636cSAndreas Gohr        /** @var helper_plugin_diagrams $helper */
53fa6a636cSAndreas Gohr        $helper = plugin_load('helper', 'diagrams');
54fa6a636cSAndreas Gohr        if (!$data['type'] == 'internalmedia' || !$helper->isDiagramFile(mediaFN($data['src']))) {
55fa6a636cSAndreas Gohr            // This is not a local diagrams file, but some other SVG media file
56e831c5ccSAnna Dabrowska            $handler->media($match, $state, $pos);
57e831c5ccSAnna Dabrowska            return false;
58fa6a636cSAndreas Gohr        }
59fa6a636cSAndreas Gohr
60046ca144SAndreas Gohr        $data['url'] = ml($data['src'], ['cache' => 'nocache'], true, '&');
61046ca144SAndreas Gohr        return $data;
628c8c7007SAndreas Gohr    }
638c8c7007SAndreas Gohr
648c8c7007SAndreas Gohr    /**
65ddc20d75SAnna Dabrowska     * Handle rewrites made by the move plugin
66ddc20d75SAnna Dabrowska     *
67ddc20d75SAnna Dabrowska     * @param string $match
68ddc20d75SAnna Dabrowska     * @param int $state
69ddc20d75SAnna Dabrowska     * @param int $pos
70ddc20d75SAnna Dabrowska     * @param string $plugin
71ddc20d75SAnna Dabrowska     * @param helper_plugin_move_handler $handler
72ddc20d75SAnna Dabrowska     * @return void
73ddc20d75SAnna Dabrowska     */
74ddc20d75SAnna Dabrowska    public function handleMove($match, $state, $pos, $plugin, $handler)
75ddc20d75SAnna Dabrowska    {
76ddc20d75SAnna Dabrowska        if ($plugin !== 'diagrams_mediafile') return;
77ddc20d75SAnna Dabrowska
78ddc20d75SAnna Dabrowska        $handler->media($match, $state, $pos);
79ddc20d75SAnna Dabrowska    }
80ddc20d75SAnna Dabrowska
81ddc20d75SAnna Dabrowska    /**
828c8c7007SAndreas Gohr     * Render the diagram SVG as <object> instead of <img> to allow links,
838c8c7007SAndreas Gohr     * except when rendering to a PDF
848c8c7007SAndreas Gohr     *
858c8c7007SAndreas Gohr     * @param string $format
868c8c7007SAndreas Gohr     * @param Doku_Renderer $renderer
878c8c7007SAndreas Gohr     * @param array $data
888c8c7007SAndreas Gohr     * @return bool
898c8c7007SAndreas Gohr     */
908c8c7007SAndreas Gohr    public function render($format, Doku_Renderer $renderer, $data)
918c8c7007SAndreas Gohr    {
92a5199261SAnna Dabrowska        global $conf;
93a5199261SAnna Dabrowska
94ddc20d75SAnna Dabrowska        if ($format === 'metadata') {
95ddc20d75SAnna Dabrowska            $renderer->internalmedia($data['src']);
96ddc20d75SAnna Dabrowska            return true;
97ddc20d75SAnna Dabrowska        }
98ddc20d75SAnna Dabrowska        if ($format !== 'xhtml') {
99ddc20d75SAnna Dabrowska            return false;
100ddc20d75SAnna Dabrowska        }
1018c8c7007SAndreas Gohr
102baaaacc0SAnna Dabrowska        // check for cached PNG
103baaaacc0SAnna Dabrowska        $cachefile = $this->getCachedPNG($data);
104baaaacc0SAnna Dabrowska
105c3c3f4cfSAndreas Gohr        if (is_a($renderer, 'renderer_plugin_dw2pdf')) {
106c3c3f4cfSAndreas Gohr            $imageAttributes = [
1078c8c7007SAndreas Gohr                'class' => 'media',
10891ed8429SAndreas Gohr                'width' => empty($data['width']) ? '' : $data['width'],
10991ed8429SAndreas Gohr                'height' => empty($data['height']) ? '' : $data['height'],
11091ed8429SAndreas Gohr                'title' => $data['title'] ?? '',
11144b3af04SAnna Dabrowska                'alt' => $data['title'] ?? '',
112c3c3f4cfSAndreas Gohr                'align' => $data['align'],
113c3c3f4cfSAndreas Gohr                'src' => $data['url'],
114dce55f69SAndreas Gohr            ];
1155f757686SAndreas Gohr
116c3c3f4cfSAndreas Gohr            // if a PNG cache exists, use it instead of the real URL
117*37a5d411SAnna Dabrowska            // or display error if PNG of embedded diagram is missing
118baaaacc0SAnna Dabrowska            if ($cachefile) {
119baaaacc0SAnna Dabrowska                $imageAttributes['src'] = 'dw2pdf://' . $cachefile;
120*37a5d411SAnna Dabrowska            } elseif ($this->getConf('pngcache') && is_a($this, 'syntax_plugin_diagrams_embed')) {
121*37a5d411SAnna Dabrowska                $renderer->doc .= $this->getLang('errorMissingPNG');
122*37a5d411SAnna Dabrowska                return false;
1233039104bSAndreas Gohr            }
1242bec1a22SAndreas Gohr
1258c8c7007SAndreas Gohr            $renderer->doc .= '<img ' . buildAttributes($imageAttributes) . '/>';
1268c8c7007SAndreas Gohr        } else {
127c3c3f4cfSAndreas Gohr            $wrapperAttributes = [];
12879809d5dSAndreas Gohr            $wrapperAttributes['title'] = $data['title'] ?? '';
129c3c3f4cfSAndreas Gohr            $wrapperAttributes['class'] = 'media diagrams-svg-wrapper media' . $data['align'];
130dce55f69SAndreas Gohr
131dce55f69SAndreas Gohr            $imageAttributes = [];
132dce55f69SAndreas Gohr            $imageAttributes['class'] = 'diagrams-svg';
133046ca144SAndreas Gohr            $imageAttributes['data'] = $data['url'];
13479809d5dSAndreas Gohr            $imageAttributes['data-id'] = cleanID($data['src'] ?? '');
135046ca144SAndreas Gohr            $imageAttributes['type'] = 'image/svg+xml';
13691ed8429SAndreas Gohr            $imageAttributes['data-pos'] = $data['pos'] ?? '';
13791ed8429SAndreas Gohr            $imageAttributes['data-len'] = $data['len'] ?? '';
13891ed8429SAndreas Gohr            $imageAttributes['width'] = empty($data['width']) ? '' : $data['width'];
13991ed8429SAndreas Gohr            $imageAttributes['height'] = empty($data['height']) ? '' : $data['height'];
1405f757686SAndreas Gohr
141baaaacc0SAnna Dabrowska            if ($cachefile) {
142e0dfc516SAnna Dabrowska                // strip cache dir and our cache extension from data attribute
143e0dfc516SAnna Dabrowska                $imageAttributes['data-pngcache'] = str_replace([$conf['cachedir'], Diagrams::CACHE_EXT], '', $cachefile);
144baaaacc0SAnna Dabrowska            }
145a5199261SAnna Dabrowska
14620761fcfSAnna Dabrowska            $image = sprintf('<object %s><span class="diagrams-alt">' . hsc($wrapperAttributes['title']) . '</span></object>', buildAttributes($imageAttributes, true));
147a5199261SAnna Dabrowska            // wrapper for action buttons
1480d9707b1SAnna Dabrowska            $actionButtons = '<div class="diagrams-buttons"></div>';
1490d9707b1SAnna Dabrowska            $wrapper = sprintf('<div %s>%s%s</div>', buildAttributes($wrapperAttributes, true), $image, $actionButtons);
150dce55f69SAndreas Gohr            $renderer->doc .= $wrapper;
1518c8c7007SAndreas Gohr        }
1528c8c7007SAndreas Gohr
1538c8c7007SAndreas Gohr        return true;
1548c8c7007SAndreas Gohr    }
155baaaacc0SAnna Dabrowska
156baaaacc0SAnna Dabrowska    /**
157e0dfc516SAnna Dabrowska     * PNG cache file without extension, if caching is enabled and file exists.
1588893185bSAnna Dabrowska     * Returns an empty string on older revisions (checking $REV), because
1598893185bSAnna Dabrowska     * PNG caching does not support versioning.
160baaaacc0SAnna Dabrowska     *
161baaaacc0SAnna Dabrowska     * @param array $data
162baaaacc0SAnna Dabrowska     * @return string
163baaaacc0SAnna Dabrowska     */
164baaaacc0SAnna Dabrowska    protected function getCachedPNG($data)
165baaaacc0SAnna Dabrowska    {
1668893185bSAnna Dabrowska        global $REV;
1678893185bSAnna Dabrowska
1688893185bSAnna Dabrowska        if (!$this->getConf('pngcache') || $REV) return '';
169baaaacc0SAnna Dabrowska
17050de7869SAnna Dabrowska        if (empty($data['svg'])) {
17150de7869SAnna Dabrowska            $data['svg'] = file_get_contents(mediaFN($data['src']));
17250de7869SAnna Dabrowska        }
173e0dfc516SAnna Dabrowska        $cachefile = getCacheName($data['svg'], Diagrams::CACHE_EXT);
174baaaacc0SAnna Dabrowska        if (file_exists($cachefile)) return $cachefile;
175baaaacc0SAnna Dabrowska
176baaaacc0SAnna Dabrowska        return '';
177baaaacc0SAnna Dabrowska    }
1788c8c7007SAndreas Gohr}
179