tr('Diagram'), 'documentation' => 'PluginDiagram', 'description' => tr('Display diagrams.net/mxGraph/Draw.io diagrams'), 'prefs' => ['wikiplugin_diagram'], 'iconname' => 'sitemap', 'tags' => ['basic'], 'introduced' => 19, 'packages_required' => [ 'tikiwiki/diagram' => VendorHelper::getAvailableVendorPath('diagram', 'tikiwiki/diagram/js/app.min.js') ], 'params' => [ 'fileId' => [ 'required' => false, 'name' => tr('fileId'), 'description' => tr('Id of the file in the file gallery. A xml file containing the graph model. Leave empty for more options.'), 'since' => '19.0', 'filter' => 'int', ], 'page' => [ 'required' => false, 'name' => tr('page'), 'description' => tr('Page of the diagram that should be displayed.'), 'since' => '', 'filter' => 'text', ], 'annotate' => [ 'required' => false, 'name' => tr('annotate'), 'description' => tr('Id of the file in the file gallery. A image file to include in the diagram.'), 'since' => '20.0', 'filter' => 'int', ], 'align' => [ 'required' => false, 'name' => tr('Image alignment when exporting a PDF'), 'description' => tr('Alignment of the diagrams during PDF export. Accepted values: "left", "right" and "center"'), 'default' => 'left', 'since' => '21.0', ], 'wikiparse' => [ 'required' => false, 'name' => tr('Parse wiki markup language inside the diagram'), 'description' => tr('Parameter that will allow to parse wiki markup language inside the diagram if the value is "1"'), 'since' => '21.0', ], 'compressXml' => [ 'required' => false, 'name' => tr('Compress XML'), 'description' => tr('Parameter that will allow inline diagram data be saved compressed.'), 'since' => '21.0', ], 'template' => [ 'required' => false, 'name' => tr('template'), 'description' => tr('Diagram\'s file id to use as a template to new the diagram. This parameter will be skipped if the fileId parameter is present.'), 'since' => '23.0', 'filter' => 'int', ], 'galleryId' => [ 'required' => false, 'name' => tr('Gallery Id'), 'description' => tr('File Gallery id where the new diagram file will be stored. If this parameter is not present the content of the file will be placed in the body of the plugin.'), 'since' => '23.0', 'filter' => 'int', ], 'fileName' => [ 'required' => false, 'name' => tr('File Name'), 'description' => tr('The name used for the diagram file. Acceptable replacements are \'%page%\' and \'%date%\'. The default pattern is “Diagram %page% %date%.drawio”.'), 'since' => '23.0', 'filter' => 'text', ] ], ]; return $info; } /** * @param $data * @param $params * @return string * @throws Exception */ function wikiplugin_diagram($data, $params) { global $tikilib, $user, $page, $wikiplugin_included_page, $prefs, $tiki_p_upload_files; $template = $params['template']; $galleryId = $params['galleryId'] ?? ($params['fileName'] ? 1 : ''); $fileName = $params['fileName'] ?? 'Diagram %page% %date%.drawio' ; $fileName = preg_replace('/\%page\%/', $page, $fileName); $fileName = preg_replace('/\%date\%/', date('Y-m-d'), $fileName); $compressXml = ($prefs['fgal_use_diagram_compression_by_default'] !== 'y') ? false : true; $compressXmlParam = false; if (empty($params['fileId']) && empty(trim($data)) && ! empty($params['template'])) { $params['fileId'] = $template; } if ( empty($params['fileId']) && isset($params['compressXml']) && in_array($params['compressXml'], ['false', '0']) ) { $compressXml = false; $compressXmlParam = true; } $diagramIdentifier = ! empty($params['fileId']) ? $params['fileId'] : $data; $info = wikiplugin_diagram_info(); $pageName = isset($params['page']) ? $params['page'] : ''; $diagrams = DiagramHelper::getDiagramsFromIdentifier($diagramIdentifier, $pageName); if (! empty($params['align']) && in_array($params['align'], ['left', 'center', 'right'])) { $alignment = $params['align']; } else { $alignment = $info['params']['align']['default']; } if (! empty($_GET['display']) && $_GET['display'] == 'pdf') { $html = ''; foreach ($diagrams as $diagram) { $html .= ! empty($html) ? '
' : ''; $html .= '
' . '
'; } return $html; } $filegallib = TikiLib::lib('filegal'); $errorMessageToAppend = ''; $oldVendorPath = VendorHelper::getAvailableVendorPath('mxgraph', 'xorti/mxgraph-editor/drawio/webapp/js/app.min.js', false); if ($oldVendorPath) { $errorMessageToAppend = tr('Previous xorti/mxgraph-editor package has been deprecated.
'); } $vendorPath = VendorHelper::getAvailableVendorPath('diagram', 'tikiwiki/diagram/js/app.min.js', false); if (! $vendorPath) { $message = $errorMessageToAppend; $message .= tr('To view diagrams Tiki needs the tikiwiki/diagram package. If you do not have permission to install this package, ask the site administrator.'); Feedback::error($message); return; } $headerlib = $tikilib::lib('header'); $headerlib->add_js_config("var diagramVendorPath = '{$vendorPath}';"); $headerlib->add_jsfile('lib/jquery_tiki/tiki-mxgraph.js', true); $headerlib->add_jsfile($vendorPath . '/tikiwiki/diagram/js/app.min.js'); $headerlib->add_css('.diagram hr {margin-top:0.5em;margin-bottom:0.5em}'); $fileId = isset($params['fileId']) ? intval($params['fileId']) : 0; $annotate = isset($params['annotate']) ? intval($params['annotate']) : 0; if ($fileId) { $file = \Tiki\FileGallery\File::id($fileId); $data = $file->getContents(); if ($data === false) { Feedback::error(tr("Tiki wasn't able to find the file with id %0.", $fileId)); return; } } $data = DiagramHelper::parseData($data); static $diagramIndex = 0; ++$diagramIndex; if (function_exists('simplexml_load_string')) { $doc = simplexml_load_string($data); if ($doc !== false && ($doc->getName() != 'mxGraphModel' && $doc->getName() != 'mxfile')) { Feedback::error(tr("Tiki wasn't able to parse the Diagram. Please check the diagram XML data and structure.")); return; } elseif (empty($data) || $doc === false) { if ($tiki_p_upload_files != 'y') { return; } $label = tra('Create New Diagram'); $page = htmlentities($page); $in = tr(" in "); $gals = $filegallib->list_file_galleries(0, -1, 'name_desc', $user); $galHtml = ""; if (! isset($params['fileName']) && ! isset($params['galleryId'])) { $galHtml = ""; } usort($gals['data'], function ($a, $b) { return strcmp(strtolower($a['name']), strtolower($b['name'])); }); if (! isset($params['galleryId'])) { foreach ($gals['data'] as $gal) { if ($gal['name'] != "Wiki Attachments" && $gal['name'] != "Users File Galleries") { if ($gal['parentId'] == -1) { // If the current user has permission to access the gallery, then add gallery to the hierarchy. if ($gal['perms']['tiki_p_view_file_gallery'] == 'y') { $galHtml .= ""; } } } } if ($annotate && $infoImg = loadImageAnnotate($annotate)) { $data = << XML; $data = DiagramHelper::parseData($data); $data = base64_encode($data); } if (! empty($galHtml)) { $galHtml = << $galHtml EOF; } else { $galHtml = << EOF; } return <<

$galHtml

~/np~ EOF; } } //checking if user can see edit button if (! empty($wikiplugin_included_page)) { $sourcepage = $wikiplugin_included_page; } else { $sourcepage = $page; } //checking if user has edit permissions on the wiki page/file using the current permission library to obey global/categ/object perms if ($fileId) { $objectperms = Perms::get(['type' => 'file', 'object' => $fileId]); } else { $objectperms = Perms::get([ 'type' => 'wiki page', 'object' => $sourcepage ]); } if ($objectperms->edit) { $allowEdit = true; } else { $allowEdit = false; } $base_64_diagram = base64_encode($data); if (isset($params['wikiparse']) && $params['wikiparse'] == 1) { $parsedDiagrams = []; $XMLDiagrams = simplexml_load_string($data); if ($XMLDiagrams->getName() == 'mxGraphModel') { $parsedDiagrams = ['' . DiagramHelper::parseDiagramWikiSyntax($XMLDiagrams) . '']; } else { if (! empty($XMLDiagrams)) { foreach ($XMLDiagrams as $diagram) { $parsedDiagram = DiagramHelper::parseDiagramWikiSyntax((string) $diagram); $diagram[0] = $parsedDiagram; $test = $diagram->saveXML(); $parsedDiagrams[] = $diagram->saveXML(); } } } $diagrams = $parsedDiagrams; $data = '' . implode('', $diagrams) . ''; } $slidePage=explode("/",$_SERVER['PHP_SELF']); $slidePage=end($slidePage); $smarty = TikiLib::lib('smarty'); $smarty->assign('index', $diagramIndex); $smarty->assign('data', $diagrams); $smarty->assign('graph_data_base64', $base_64_diagram); $smarty->assign('sourcepage', $sourcepage); $smarty->assign('allow_edit', $allowEdit); $smarty->assign('file_id', $fileId); $smarty->assign('template', $template); $smarty->assign('gallery_id', $galleryId); $smarty->assign('file_name', ($fileId == $template) ? $fileName : $file->name); $smarty->assign('alignment', $alignment); $smarty->assign('mxgraph_prefix', $vendorPath); $smarty->assign('page_name', $pageName); $smarty->assign('compressXml', $compressXml); $smarty->assign('compressXmlParam', $compressXmlParam); $smarty->assign('slide_psge', $slidePage); return '~np~' . $smarty->fetch('wiki-plugins/wikiplugin_diagram.tpl') . '~/np~'; } /** * Get info of the image to annotate on * * @param number $annotate * @return array | false * @throws SmartyException */ function loadImageAnnotate($annotate) { global $user; $userLib = TikiLib::lib('user'); $file = \Tiki\FileGallery\File::id($annotate); $smarty = TikiLib::lib('smarty'); $smarty->loadPlugin('smarty_modifier_sefurl'); $url = smarty_modifier_sefurl($annotate, 'display'); if (! $file->exists() || ! $userLib->user_has_perm_on_object($user, $file->fileId, 'file', 'tiki_p_download_files')) { Feedback::error(tr("Tiki wasn't able to find the file with id %0.", $annotate)); return false; } if (! preg_match('/^image\//', $file->filetype)) { Feedback::error(tr("Selected file to annotate must be an image.")); return false; } if ($file->getWrapper()->isFileLocal()) { $imageSize = getimagesize($file->getWrapper()->getReadableFile()); } else { $data = $file->getContents(); $imageSize = getimagesize('data://text/plain;base64,' . base64_encode($data)); } if (empty($imageSize)) { Feedback::error(tr("Can not retrieve size from file %0", $annotate)); return false; } return [ 'url' => $url, 'imageSize' => $imageSize ]; }