xref: /plugin/diagrams/syntax/embed.php (revision 44b3af047f3968d6462bc1e2ab63b998e09b5eef)
18a822cc1SAndreas Gohr<?php
28a822cc1SAndreas Gohr
3bc39777fSAndreas Gohruse dokuwiki\plugin\diagrams\Diagrams;
4bc39777fSAndreas Gohr
58a822cc1SAndreas Gohr/**
68c8c7007SAndreas Gohr * DokuWiki Plugin diagrams (Syntax Component)
78c8c7007SAndreas Gohr *
88c8c7007SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
98c8c7007SAndreas Gohr * @author  Innovakom + CosmoCode <dokuwiki@cosmocode.de>
108a822cc1SAndreas Gohr */
11046ca144SAndreas Gohrclass syntax_plugin_diagrams_embed extends syntax_plugin_diagrams_mediafile
128c8c7007SAndreas Gohr{
13046ca144SAndreas Gohr    /** @var int count the current embedded diagram */
14046ca144SAndreas Gohr    protected $count = 0;
158a822cc1SAndreas Gohr
168c8c7007SAndreas Gohr    /** @inheritDoc */
178a822cc1SAndreas Gohr    public function connectTo($mode)
188a822cc1SAndreas Gohr    {
19bc39777fSAndreas Gohr        // only register if embed mode is enabled
2059e7180eSAndreas Gohr        if (!($this->getConf('mode') & Diagrams::MODE_EMBED)) return;
21baa90558SAnna Dabrowska        $this->Lexer->addSpecialPattern('<diagram(?: .*?)?>.*?(?:</diagram>)', $mode, 'plugin_diagrams_embed');
228a822cc1SAndreas Gohr    }
238a822cc1SAndreas Gohr
248c8c7007SAndreas Gohr    /** @inheritDoc */
258a822cc1SAndreas Gohr    public function handle($match, $state, $pos, Doku_Handler $handler)
268a822cc1SAndreas Gohr    {
278c8c7007SAndreas Gohr        [$open, $rest] = sexplode('>', $match, 2);
288c8c7007SAndreas Gohr        $params = substr($open, 9);
298c8c7007SAndreas Gohr        $svg = substr($rest, 0, -10);
308c8c7007SAndreas Gohr
31317bdfc2SAndreas Gohr        // embed positions
32317bdfc2SAndreas Gohr        $svglen = strlen($svg);
33317bdfc2SAndreas Gohr        $svgpos = $pos + strpos($match, '>');
34317bdfc2SAndreas Gohr
3595ed8ca0SAndreas Gohr        /** @var helper_plugin_diagrams $helper */
3695ed8ca0SAndreas Gohr        $helper = plugin_load('helper', 'diagrams');
3795ed8ca0SAndreas Gohr        if (!$helper->isDiagram($svg)) return false;
3895ed8ca0SAndreas Gohr
398c8c7007SAndreas Gohr        $data = [
408c8c7007SAndreas Gohr            'svg' => $svg,
41*44b3af04SAnna Dabrowska            'title' => '',
428c8c7007SAndreas Gohr            'align' => '',
438c8c7007SAndreas Gohr            'width' => '',
448c8c7007SAndreas Gohr            'height' => '',
45317bdfc2SAndreas Gohr            'pos' => $svgpos,
46317bdfc2SAndreas Gohr            'len' => $svglen,
478c8c7007SAndreas Gohr        ];
488c8c7007SAndreas Gohr
498c8c7007SAndreas Gohr        if (preg_match('/\b(left|right|center)\b/', $params, $matches)) {
508c8c7007SAndreas Gohr            $data['align'] = $matches[1];
518c8c7007SAndreas Gohr        }
52*44b3af04SAnna Dabrowska        if (preg_match('/\|(.*)/', $params, $matches)) {
53*44b3af04SAnna Dabrowska            $data['title'] = $matches[1];
54*44b3af04SAnna Dabrowska        }
558c8c7007SAndreas Gohr        if (preg_match('/\b(\d+)x(\d+)\b/', $params, $matches)) {
568c8c7007SAndreas Gohr            $data['width'] = (int)$matches[1];
578c8c7007SAndreas Gohr            $data['height'] = (int)$matches[2];
588a822cc1SAndreas Gohr        }
598a822cc1SAndreas Gohr
608c8c7007SAndreas Gohr        return $data;
618c8c7007SAndreas Gohr    }
628c8c7007SAndreas Gohr
638c8c7007SAndreas Gohr    /** @inheritDoc */
648a822cc1SAndreas Gohr    public function render($format, Doku_Renderer $renderer, $data)
658a822cc1SAndreas Gohr    {
66100ff2a5SAndreas Gohr        if (!$data) return false;
6798c89536SAndreas Gohr        global $ID;
6898c89536SAndreas Gohr        global $ACT;
69046ca144SAndreas Gohr        global $INPUT;
70750b9665SAnna Dabrowska        global $REV;
718c8c7007SAndreas Gohr
72046ca144SAndreas Gohr        switch ($format) {
73046ca144SAndreas Gohr            case 'xhtml':
7498c89536SAndreas Gohr                if (act_clean($ACT) !== 'preview' && page_exists($ID)) {
7598c89536SAndreas Gohr                    // this is "normal" rendering, we reference the diagram through the export
7698c89536SAndreas Gohr                    // this applies the same CSP as media files and will also show the exact behaviours
77750b9665SAnna Dabrowska                    $data['url'] = wl($ID, ['do' => 'export_diagrams', 'svg' => $this->count++, 'rev' => $REV], true, '&');
7898c89536SAndreas Gohr                } else {
7998c89536SAndreas Gohr                    // we're in preview and the diagram may not have been saved, yet. So we
8098c89536SAndreas Gohr                    // reference it as data uri to prevent cross-origin access XSS
812aa4335dSAndreas Gohr                    $data['url'] = 'data:image/svg+xml;base64,' . base64_encode($data['svg']);
8298c89536SAndreas Gohr                }
8398c89536SAndreas Gohr
84046ca144SAndreas Gohr                parent::render($format, $renderer, $data);
85046ca144SAndreas Gohr                return true;
86046ca144SAndreas Gohr            case 'diagrams':
87046ca144SAndreas Gohr                // This exports a single SVG during the export_diagrams action
88046ca144SAndreas Gohr                if ($INPUT->int('svg') === $this->count++) {
89046ca144SAndreas Gohr                    $renderer->doc = $data['svg'];
90100ff2a5SAndreas Gohr                }
918a822cc1SAndreas Gohr                return true;
928a822cc1SAndreas Gohr        }
93046ca144SAndreas Gohr        return false;
94046ca144SAndreas Gohr    }
95046ca144SAndreas Gohr
96046ca144SAndreas Gohr
978a822cc1SAndreas Gohr}
988c8c7007SAndreas Gohr
99