1<?php
2
3/**
4 * @license    See LICENSE file
5 * @author     Jaap de Haan <jaap.dehaan@color-of-code.de>
6 */
7
8// See help: https://www.dokuwiki.org/devel:syntax_plugins
9
10// The HTML structure generated by this syntax plugin is:
11//
12// <div class="plugin-bpmnio" id="__(bpmn|dmn)_js_<hash>">
13//   <div class="bpmn_js_data">
14//      ... base64 encoded xml
15//   </div>
16//   <div class="bpmn_js_canvas {$class}">
17//     <div class="bpmn_js_container">... rendered herein</div>
18//   </div>
19// </div>
20
21
22class syntax_plugin_bpmnio_bpmnio extends DokuWiki_Syntax_Plugin
23{
24    public string $type = ''; // 'bpmn' or 'dmn'
25
26    public function getPType()
27    {
28        return 'block';
29    }
30
31    public function getType()
32    {
33        return 'protected';
34    }
35
36    public function getSort()
37    {
38        return 0;
39    }
40
41    public function connectTo($mode)
42    {
43        $this->Lexer->addEntryPattern('<bpmnio.*?>(?=.*?</bpmnio>)', $mode, 'plugin_bpmnio_bpmnio');
44    }
45
46    public function postConnect()
47    {
48        $this->Lexer->addExitPattern('</bpmnio>', 'plugin_bpmnio_bpmnio');
49    }
50
51    public function handle($match, $state, $pos, Doku_Handler $handler)
52    {
53        switch ($state) {
54            case DOKU_LEXER_ENTER :
55                $matched = '';
56                preg_match('/<bpmnio type="(\w+)">/', $match, $matched);
57                $this->type = $matched[1] ?? 'bpmn';
58                return array($state, $this->type, '', $pos, '');
59
60            case DOKU_LEXER_UNMATCHED:
61                $posStart = $pos;
62                $posEnd = $pos + strlen($match);
63                $match = base64_encode($match);
64                return array($state, $this->type, $match, $posStart, $posEnd);
65
66            case DOKU_LEXER_EXIT:
67                $this->type = '';
68                return array($state, '', '', '', '');
69        }
70        return array();
71    }
72
73    public function render($mode, Doku_Renderer $renderer, $data)
74    {
75        list($state, $type, $match, $posStart, $posEnd) = $data;
76
77        if (is_a($renderer, 'renderer_plugin_dw2pdf')) {
78            if ($state == DOKU_LEXER_EXIT) {
79                $renderer->doc .= <<<HTML
80                    <div class="plugin-bpmnio">
81                        <a href="https://github.com/Color-Of-Code/dokuwiki-plugin-bpmnio/issues/4">DW2PDF support missing: Help wanted</a>
82                    </div>
83                    HTML;
84            }
85            return true;
86        }
87
88        if ($mode == 'xhtml' || $mode == 'odt') {
89            switch ($state) {
90                case DOKU_LEXER_ENTER:
91                    $bpmnid = "__{$type}_js_{$posStart}";
92                    $renderer->doc .= <<<HTML
93                        <div class="plugin-bpmnio" id="{$bpmnid}">
94                        HTML;
95                    break;
96
97                case DOKU_LEXER_UNMATCHED:
98                    $renderer->doc .= <<<HTML
99                        <div class="{$type}_js_data">
100                            {$match}
101                        </div>
102                        HTML;
103
104                    $class = $this->_startSectionEdit($renderer, $posStart, $type);
105                    $renderer->doc .= <<<HTML
106                        <div class="{$type}_js_canvas {$class}">
107                            <div class="{$type}_js_container"></div>
108                        </div>
109                        HTML;
110                    $this->_finishSectionEdit($renderer, $posEnd);
111                    break;
112
113                case DOKU_LEXER_EXIT:
114                    $renderer->doc .= <<<HTML
115                        </div>
116                        HTML;
117                    break;
118            }
119            return true;
120        }
121        return false;
122    }
123
124    private function _startSectionEdit(Doku_Renderer $renderer, $pos, $type)
125    {
126        $target = "plugin_bpmnio_{$type}";
127        $sectionEditData = ['target' => $target];
128        if (!defined('SEC_EDIT_PATTERN')) {
129            // backwards-compatibility for Frusterick Manners (2017-02-19)
130            $sectionEditData = $target;
131        }
132        return $renderer->startSectionEdit($pos, $sectionEditData);
133    }
134
135    private function _finishSectionEdit(Doku_Renderer $renderer, $pos)
136    {
137        $renderer->finishSectionEdit($pos);
138    }
139}
140