xref: /plugin/bpmnio/syntax/bpmnio.php (revision 36b712d809a9afeda77eb7dba8abf621818208c9)
1fc2e1131SJaap de Haan<?php
2fc2e1131SJaap de Haan
3a494ddccSgithub-actions[bot]use dokuwiki\Extension\SyntaxPlugin;
44c812427SJaap de Haanuse dokuwiki\File\MediaResolver;
5a494ddccSgithub-actions[bot]
6fc2e1131SJaap de Haan/**
7fc2e1131SJaap de Haan * @license    See LICENSE file
8fc2e1131SJaap de Haan */
9fc2e1131SJaap de Haan// See help: https://www.dokuwiki.org/devel:syntax_plugins
10242f4056SJaap de Haan// The HTML structure generated by this syntax plugin is:
11242f4056SJaap de Haan//
12242f4056SJaap de Haan// <div class="plugin-bpmnio" id="__(bpmn|dmn)_js_<hash>">
13242f4056SJaap de Haan//   <div class="bpmn_js_data">
14242f4056SJaap de Haan//      ... base64 encoded xml
15242f4056SJaap de Haan//   </div>
16242f4056SJaap de Haan//   <div class="bpmn_js_canvas {$class}">
17242f4056SJaap de Haan//     <div class="bpmn_js_container">... rendered herein</div>
18242f4056SJaap de Haan//   </div>
19242f4056SJaap de Haan// </div>
20a494ddccSgithub-actions[bot]class syntax_plugin_bpmnio_bpmnio extends SyntaxPlugin
21fc2e1131SJaap de Haan{
224c812427SJaap de Haan    protected string $type = ''; // 'bpmn' or 'dmn'
234c812427SJaap de Haan    protected string $src = ''; // media file
2494260a7fSJaap de Haan    protected string $zoom = ''; // optional scaling factor
25f0ae282cSJaap de Haan
26*36b712d8SJaap de Haan    private function loadLinkProcessor(): void
27*36b712d8SJaap de Haan    {
28*36b712d8SJaap de Haan        require_once __DIR__ . '/../inc/link_processor.php';
29*36b712d8SJaap de Haan    }
30*36b712d8SJaap de Haan
319ff8d41cSJaap de Haan    public function getPType(): string
32fc2e1131SJaap de Haan    {
33fc2e1131SJaap de Haan        return 'block';
34fc2e1131SJaap de Haan    }
35fc2e1131SJaap de Haan
369ff8d41cSJaap de Haan    public function getType(): string
37fc2e1131SJaap de Haan    {
38fc2e1131SJaap de Haan        return 'protected';
39fc2e1131SJaap de Haan    }
40fc2e1131SJaap de Haan
419ff8d41cSJaap de Haan    public function getSort(): int
42fc2e1131SJaap de Haan    {
43fc2e1131SJaap de Haan        return 0;
44fc2e1131SJaap de Haan    }
45fc2e1131SJaap de Haan
469ff8d41cSJaap de Haan    public function connectTo($mode): void
47fc2e1131SJaap de Haan    {
48fc2e1131SJaap de Haan        $this->Lexer->addEntryPattern('<bpmnio.*?>(?=.*?</bpmnio>)', $mode, 'plugin_bpmnio_bpmnio');
49fc2e1131SJaap de Haan    }
50fc2e1131SJaap de Haan
519ff8d41cSJaap de Haan    public function postConnect(): void
52fc2e1131SJaap de Haan    {
53fc2e1131SJaap de Haan        $this->Lexer->addExitPattern('</bpmnio>', 'plugin_bpmnio_bpmnio');
54fc2e1131SJaap de Haan    }
55fc2e1131SJaap de Haan
569ff8d41cSJaap de Haan    public function handle($match, $state, $pos, Doku_Handler $handler): array
57fc2e1131SJaap de Haan    {
58f0ae282cSJaap de Haan        switch ($state) {
59f0ae282cSJaap de Haan            case DOKU_LEXER_ENTER:
604c812427SJaap de Haan                $matched = [];
614c812427SJaap de Haan                preg_match('/<bpmnio\s+([^>]+)>/', $match, $matched);
624c812427SJaap de Haan
634c812427SJaap de Haan                $attrs = [];
644c812427SJaap de Haan                if (!empty($matched[1])) {
654c812427SJaap de Haan                    $attrs = $this->buildAttributes($matched[1]);
664c812427SJaap de Haan                }
674c812427SJaap de Haan
684c812427SJaap de Haan                $this->type = $attrs['type'] ?? 'bpmn';
694c812427SJaap de Haan                $this->src = $attrs['src'] ?? '';
7094260a7fSJaap de Haan                $this->zoom = $this->normalizeZoom($attrs['zoom'] ?? null) ?? '';
714c812427SJaap de Haan
7294260a7fSJaap de Haan                return [$state, $this->type, '', $pos, '', false, $this->zoom];
73f0ae282cSJaap de Haan
74f0ae282cSJaap de Haan            case DOKU_LEXER_UNMATCHED:
75c4f02a6eSJaap de Haan                $posStart = $pos;
76c4f02a6eSJaap de Haan                $posEnd = $pos + strlen($match);
774c812427SJaap de Haan
784c812427SJaap de Haan                $inline = empty($this->src);
794c812427SJaap de Haan                if (!$inline) {
804c812427SJaap de Haan                    $match = $this->getMedia($this->src);
814c812427SJaap de Haan                }
8294260a7fSJaap de Haan                return [$state, $this->type, base64_encode($match), $posStart, $posEnd, $inline, $this->zoom];
83f0ae282cSJaap de Haan
84f0ae282cSJaap de Haan            case DOKU_LEXER_EXIT:
85ae85f1faSJaap de Haan                $this->type = '';
864c812427SJaap de Haan                $this->src = '';
8794260a7fSJaap de Haan                $this->zoom = '';
8894260a7fSJaap de Haan                return [$state, '', '', '', '', '', false, ''];
89fc2e1131SJaap de Haan        }
90a494ddccSgithub-actions[bot]        return [];
91fc2e1131SJaap de Haan    }
92fc2e1131SJaap de Haan
934c812427SJaap de Haan    private function buildAttributes($string)
944c812427SJaap de Haan    {
954c812427SJaap de Haan        $attrs = [];
964c812427SJaap de Haan        preg_match_all('/(\w+)=["\'](.*?)["\']/', $string, $matches, PREG_SET_ORDER);
974c812427SJaap de Haan        foreach ($matches as $match) {
984c812427SJaap de Haan            $attrs[$match[1]] = $match[2];
994c812427SJaap de Haan        }
1004c812427SJaap de Haan        return $attrs;
1014c812427SJaap de Haan    }
1024c812427SJaap de Haan
10394260a7fSJaap de Haan    private function normalizeZoom($zoom): ?string
10494260a7fSJaap de Haan    {
10594260a7fSJaap de Haan        if ($zoom === null || $zoom === '') {
10694260a7fSJaap de Haan            return null;
10794260a7fSJaap de Haan        }
10894260a7fSJaap de Haan
10994260a7fSJaap de Haan        if (!is_numeric($zoom)) {
11094260a7fSJaap de Haan            return null;
11194260a7fSJaap de Haan        }
11294260a7fSJaap de Haan
11394260a7fSJaap de Haan        $zoom = (float) $zoom;
11494260a7fSJaap de Haan        if ($zoom <= 0) {
11594260a7fSJaap de Haan            return null;
11694260a7fSJaap de Haan        }
11794260a7fSJaap de Haan
11894260a7fSJaap de Haan        return rtrim(rtrim(number_format($zoom, 4, '.', ''), '0'), '.');
11994260a7fSJaap de Haan    }
12094260a7fSJaap de Haan
1214c812427SJaap de Haan    private function getMedia($src)
1224c812427SJaap de Haan    {
1234c812427SJaap de Haan        global $ID;
1244c812427SJaap de Haan
1254c812427SJaap de Haan        $id = (new MediaResolver($ID))->resolveId($src);
1264c812427SJaap de Haan        if (auth_quickaclcheck($id) < AUTH_READ) {
1274c812427SJaap de Haan            return "Error: Access denied for file $src";
1284c812427SJaap de Haan        }
1294c812427SJaap de Haan
1304c812427SJaap de Haan        $file = mediaFN($id);
1314c812427SJaap de Haan        if (!file_exists($file) || !is_readable($file)) {
1324c812427SJaap de Haan            return "Error: Cannot load file $src";
1334c812427SJaap de Haan        }
1344c812427SJaap de Haan
1354c812427SJaap de Haan        return file_get_contents($file);
1364c812427SJaap de Haan    }
1374c812427SJaap de Haan
1389ff8d41cSJaap de Haan    public function render($mode, Doku_Renderer $renderer, $data): bool
139fc2e1131SJaap de Haan    {
14094260a7fSJaap de Haan        [$state, $type, $match, $posStart, $posEnd, $inline, $zoom] = array_pad($data, 7, '');
14134515d89SJaap de Haan
14234515d89SJaap de Haan        if (is_a($renderer, 'renderer_plugin_dw2pdf')) {
14334515d89SJaap de Haan            if ($state == DOKU_LEXER_EXIT) {
14434515d89SJaap de Haan                $renderer->doc .= <<<HTML
14534515d89SJaap de Haan                    <div class="plugin-bpmnio">
146962d7b81SJaap de Haan                        <a href="https://github.com/Color-Of-Code/dokuwiki-plugin-bpmnio/issues/4">
147962d7b81SJaap de Haan                            DW2PDF support missing: Help wanted
148962d7b81SJaap de Haan                        </a>
14934515d89SJaap de Haan                    </div>
15034515d89SJaap de Haan                    HTML;
15134515d89SJaap de Haan            }
15234515d89SJaap de Haan            return true;
15334515d89SJaap de Haan        }
15434515d89SJaap de Haan
15534515d89SJaap de Haan        if ($mode == 'xhtml' || $mode == 'odt') {
156fc2e1131SJaap de Haan            switch ($state) {
157fc2e1131SJaap de Haan                case DOKU_LEXER_ENTER:
158ae85f1faSJaap de Haan                    $bpmnid = "__{$type}_js_{$posStart}";
1598428abe8SJaap de Haan                    $renderer->doc .= <<<HTML
1608428abe8SJaap de Haan                        <div class="plugin-bpmnio" id="{$bpmnid}">
1618428abe8SJaap de Haan                        HTML;
162fc2e1131SJaap de Haan                    break;
163fc2e1131SJaap de Haan
164fc2e1131SJaap de Haan                case DOKU_LEXER_UNMATCHED:
165*36b712d8SJaap de Haan                    $xml = base64_decode($match, true);
166*36b712d8SJaap de Haan                    if ($xml === false) {
167*36b712d8SJaap de Haan                        $xml = $match;
168*36b712d8SJaap de Haan                    }
169*36b712d8SJaap de Haan
170*36b712d8SJaap de Haan                    $this->loadLinkProcessor();
171*36b712d8SJaap de Haan                    $payload = plugin_bpmnio_link_processor::buildPayload($xml);
172*36b712d8SJaap de Haan                    $encodedXml = base64_encode($payload['xml']);
173*36b712d8SJaap de Haan                    $encodedLinks = base64_encode(json_encode($payload['links']));
1748428abe8SJaap de Haan                    $renderer->doc .= <<<HTML
175f0ae282cSJaap de Haan                        <div class="{$type}_js_data">
176*36b712d8SJaap de Haan                            {$encodedXml}
177*36b712d8SJaap de Haan                        </div>
178*36b712d8SJaap de Haan                        <div class="{$type}_js_links">
179*36b712d8SJaap de Haan                            {$encodedLinks}
1808428abe8SJaap de Haan                        </div>
1818428abe8SJaap de Haan                        HTML;
1824c812427SJaap de Haan                    if ($inline) {
183962d7b81SJaap de Haan                        $target = "plugin_bpmnio_{$type}";
184962d7b81SJaap de Haan                        $sectionEditData = ['target' => $target];
185962d7b81SJaap de Haan                        $class = $renderer->startSectionEdit($posStart, $sectionEditData);
1864c812427SJaap de Haan                    } else {
1874c812427SJaap de Haan                        $class = '';
1884c812427SJaap de Haan                    }
18994260a7fSJaap de Haan                    $zoomAttr = $zoom !== '' ? " data-zoom=\"{$zoom}\"" : '';
190c4f02a6eSJaap de Haan                    $renderer->doc .= <<<HTML
191f0ae282cSJaap de Haan                        <div class="{$type}_js_canvas {$class}">
19294260a7fSJaap de Haan                            <div class="{$type}_js_container"{$zoomAttr}></div>
193c4f02a6eSJaap de Haan                        </div>
194c4f02a6eSJaap de Haan                        HTML;
1954c812427SJaap de Haan                    if ($inline) {
196962d7b81SJaap de Haan                        $renderer->finishSectionEdit($posEnd);
1974c812427SJaap de Haan                    }
198c4f02a6eSJaap de Haan                    break;
199c4f02a6eSJaap de Haan
200c4f02a6eSJaap de Haan                case DOKU_LEXER_EXIT:
201f0ae282cSJaap de Haan                    $renderer->doc .= <<<HTML
202f0ae282cSJaap de Haan                        </div>
203f0ae282cSJaap de Haan                        HTML;
204fc2e1131SJaap de Haan                    break;
205fc2e1131SJaap de Haan            }
206fc2e1131SJaap de Haan            return true;
207fc2e1131SJaap de Haan        }
208fc2e1131SJaap de Haan        return false;
209fc2e1131SJaap de Haan    }
210fc2e1131SJaap de Haan}
211