">
//
// ... base64 encoded xml
//
//
//
... rendered herein
//
//
class syntax_plugin_bpmnio_bpmnio extends SyntaxPlugin
{
protected string $type = ''; // 'bpmn' or 'dmn'
protected string $src = ''; // media file
protected string $zoom = ''; // optional scaling factor
private function loadLinkProcessor(): void
{
require_once __DIR__ . '/../inc/link_processor.php';
}
public function getPType(): string
{
return 'block';
}
public function getType(): string
{
return 'protected';
}
public function getSort(): int
{
return 0;
}
public function connectTo($mode): void
{
$this->Lexer->addEntryPattern('(?=.*?)', $mode, 'plugin_bpmnio_bpmnio');
}
public function postConnect(): void
{
$this->Lexer->addExitPattern('', 'plugin_bpmnio_bpmnio');
}
public function handle($match, $state, $pos, Doku_Handler $handler): array
{
switch ($state) {
case DOKU_LEXER_ENTER:
$matched = [];
preg_match('/]+)>/', $match, $matched);
$attrs = [];
if (!empty($matched[1])) {
$attrs = $this->buildAttributes($matched[1]);
}
$this->type = $attrs['type'] ?? 'bpmn';
$this->src = $attrs['src'] ?? '';
$this->zoom = $this->normalizeZoom($attrs['zoom'] ?? null) ?? '';
return [$state, $this->type, '', $pos, '', false, $this->zoom];
case DOKU_LEXER_UNMATCHED:
$posStart = $pos;
$posEnd = $pos + strlen($match);
$inline = empty($this->src);
if (!$inline) {
$match = $this->getMedia($this->src);
}
return [$state, $this->type, base64_encode($match), $posStart, $posEnd, $inline, $this->zoom];
case DOKU_LEXER_EXIT:
$this->type = '';
$this->src = '';
$this->zoom = '';
return [$state, '', '', '', '', '', false, ''];
}
return [];
}
private function buildAttributes($string)
{
$attrs = [];
preg_match_all('/(\w+)=["\'](.*?)["\']/', $string, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$attrs[$match[1]] = $match[2];
}
return $attrs;
}
private function normalizeZoom($zoom): ?string
{
if ($zoom === null || $zoom === '') {
return null;
}
if (!is_numeric($zoom)) {
return null;
}
$zoom = (float) $zoom;
if ($zoom <= 0) {
return null;
}
return rtrim(rtrim(number_format($zoom, 4, '.', ''), '0'), '.');
}
private function getMedia($src)
{
global $ID;
$id = (new MediaResolver($ID))->resolveId($src);
if (auth_quickaclcheck($id) < AUTH_READ) {
return "Error: Access denied for file $src";
}
$file = mediaFN($id);
if (!file_exists($file) || !is_readable($file)) {
return "Error: Cannot load file $src";
}
return file_get_contents($file);
}
public function render($mode, Doku_Renderer $renderer, $data): bool
{
[$state, $type, $match, $posStart, $posEnd, $inline, $zoom] = array_pad($data, 7, '');
if (is_a($renderer, 'renderer_plugin_dw2pdf')) {
if ($state == DOKU_LEXER_EXIT) {
$renderer->doc .= <<
DW2PDF support missing: Help wanted
HTML;
}
return true;
}
if ($mode == 'xhtml' || $mode == 'odt') {
switch ($state) {
case DOKU_LEXER_ENTER:
$bpmnid = "__{$type}_js_{$posStart}";
$renderer->doc .= <<
HTML;
break;
case DOKU_LEXER_UNMATCHED:
$xml = base64_decode($match, true);
if ($xml === false) {
$xml = $match;
}
$this->loadLinkProcessor();
$payload = plugin_bpmnio_link_processor::buildPayload($xml);
$encodedXml = base64_encode($payload['xml']);
$encodedLinks = base64_encode(json_encode($payload['links']));
$renderer->doc .= <<
{$encodedXml}
{$encodedLinks}
HTML;
if ($inline) {
$target = "plugin_bpmnio_{$type}";
$sectionEditData = ['target' => $target];
$class = $renderer->startSectionEdit($posStart, $sectionEditData);
} else {
$class = '';
}
$zoomAttr = $zoom !== '' ? " data-zoom=\"{$zoom}\"" : '';
$renderer->doc .= <<
HTML;
if ($inline) {
$renderer->finishSectionEdit($posEnd);
}
break;
case DOKU_LEXER_EXIT:
$renderer->doc .= <<
HTML;
break;
}
return true;
}
return false;
}
}