1<?php 2 3use dokuwiki\Extension\SyntaxPlugin; 4use dokuwiki\File\MediaResolver; 5 6/** 7 * @license See LICENSE file 8 */ 9// See help: https://www.dokuwiki.org/devel:syntax_plugins 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> 20class syntax_plugin_bpmnio_bpmnio extends SyntaxPlugin 21{ 22 protected string $type = ''; // 'bpmn' or 'dmn' 23 protected string $src = ''; // media file 24 25 public function getPType() 26 { 27 return 'block'; 28 } 29 30 public function getType() 31 { 32 return 'protected'; 33 } 34 35 public function getSort() 36 { 37 return 0; 38 } 39 40 public function connectTo($mode) 41 { 42 $this->Lexer->addEntryPattern('<bpmnio.*?>(?=.*?</bpmnio>)', $mode, 'plugin_bpmnio_bpmnio'); 43 } 44 45 public function postConnect() 46 { 47 $this->Lexer->addExitPattern('</bpmnio>', 'plugin_bpmnio_bpmnio'); 48 } 49 50 public function handle($match, $state, $pos, Doku_Handler $handler) 51 { 52 switch ($state) { 53 case DOKU_LEXER_ENTER: 54 $matched = []; 55 preg_match('/<bpmnio\s+([^>]+)>/', $match, $matched); 56 57 $attrs = []; 58 if (!empty($matched[1])) { 59 $attrs = $this->buildAttributes($matched[1]); 60 } 61 62 $this->type = $attrs['type'] ?? 'bpmn'; 63 $this->src = $attrs['src'] ?? ''; 64 65 return [$state, $this->type, '', $pos, '', false]; 66 67 case DOKU_LEXER_UNMATCHED: 68 $posStart = $pos; 69 $posEnd = $pos + strlen($match); 70 71 $inline = empty($this->src); 72 if (!$inline) { 73 $match = $this->getMedia($this->src); 74 } 75 return [$state, $this->type, base64_encode($match), $posStart, $posEnd, $inline]; 76 77 case DOKU_LEXER_EXIT: 78 $this->type = ''; 79 $this->src = ''; 80 return [$state, '', '', '', '', '', false]; 81 } 82 return []; 83 } 84 85 private function buildAttributes($string) 86 { 87 $attrs = []; 88 preg_match_all('/(\w+)=["\'](.*?)["\']/', $string, $matches, PREG_SET_ORDER); 89 foreach ($matches as $match) { 90 $attrs[$match[1]] = $match[2]; 91 } 92 return $attrs; 93 } 94 95 private function getMedia($src) 96 { 97 global $ID; 98 99 $id = (new MediaResolver($ID))->resolveId($src); 100 if (auth_quickaclcheck($id) < AUTH_READ) { 101 return "Error: Access denied for file $src"; 102 } 103 104 $file = mediaFN($id); 105 if (!file_exists($file) || !is_readable($file)) { 106 return "Error: Cannot load file $src"; 107 } 108 109 return file_get_contents($file); 110 } 111 112 public function render($mode, Doku_Renderer $renderer, $data) 113 { 114 [$state, $type, $match, $posStart, $posEnd, $inline] = $data; 115 116 if (is_a($renderer, 'renderer_plugin_dw2pdf')) { 117 if ($state == DOKU_LEXER_EXIT) { 118 $renderer->doc .= <<<HTML 119 <div class="plugin-bpmnio"> 120 <a href="https://github.com/Color-Of-Code/dokuwiki-plugin-bpmnio/issues/4"> 121 DW2PDF support missing: Help wanted 122 </a> 123 </div> 124 HTML; 125 } 126 return true; 127 } 128 129 if ($mode == 'xhtml' || $mode == 'odt') { 130 switch ($state) { 131 case DOKU_LEXER_ENTER: 132 $bpmnid = "__{$type}_js_{$posStart}"; 133 $renderer->doc .= <<<HTML 134 <div class="plugin-bpmnio" id="{$bpmnid}"> 135 HTML; 136 break; 137 138 case DOKU_LEXER_UNMATCHED: 139 $renderer->doc .= <<<HTML 140 <div class="{$type}_js_data"> 141 {$match} 142 </div> 143 HTML; 144 if ($inline) { 145 $target = "plugin_bpmnio_{$type}"; 146 $sectionEditData = ['target' => $target]; 147 $class = $renderer->startSectionEdit($posStart, $sectionEditData); 148 } else { 149 $class = ''; 150 } 151 $renderer->doc .= <<<HTML 152 <div class="{$type}_js_canvas {$class}"> 153 <div class="{$type}_js_container"></div> 154 </div> 155 HTML; 156 if ($inline) { 157 $renderer->finishSectionEdit($posEnd); 158 } 159 break; 160 161 case DOKU_LEXER_EXIT: 162 $renderer->doc .= <<<HTML 163 </div> 164 HTML; 165 break; 166 } 167 return true; 168 } 169 return false; 170 } 171} 172