*/ use dokuwiki\File\MediaResolver; use dokuwiki\plugin\struct\meta\Schema; use dokuwiki\plugin\struct\meta\Value; use splitbrain\PHPArchive\Zip; // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); class action_plugin_structodt extends DokuWiki_Action_Plugin { /** * Registers a callback function for a given event * * @param Doku_Event_Handler $controller DokuWiki's event controller object * @return void */ public function register(Doku_Event_Handler $controller) { $controller->register_hook('PLUGIN_STRUCT_CONFIGPARSER_UNKNOWNKEY', 'BEFORE', $this, 'handle_struct_configparser'); $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_prerpocess'); } /** * Add "template" config key * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return void */ public function handle_struct_configparser(Doku_Event &$event, $param) { $keys = ['template', 'pdf', 'hideform', 'filename']; $key = $event->data['key']; $val = trim($event->data['val']); if (!in_array($key, $keys)) return; $event->preventDefault(); $event->stopPropagation(); switch ($key) { case 'template': $event->data['config'][$key] = array_map('trim', explode(',', $val)); break; case 'pdf': $event->data['config'][$key] = (bool) $val; if ($event->data['config']) { //check for "unoconv" $val = shell_exec('command -v unoconv'); if (empty($val)) { msg('Cannot locate "unoconv". Falling back to ODT mode.', 0); $event->data['config'][$key] = false; break; } //check for "ghostscript" $val = shell_exec('command -v ghostscript'); if (empty($val)) { msg('Cannot locate "ghostscript". Falling back to ODT mode.', 0); $event->data['config'][$key] = false; break; } } break; case 'hideform': $event->data['config'][$key] = (bool) $val; break; case 'filename': $event->data['config'][$key] = trim($val); break; } } /** * Handle odt export * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * @return void * @throws \splitbrain\PHPArchive\ArchiveIOException * @throws \splitbrain\PHPArchive\FileInfoException */ public function handle_action_act_prerpocess(Doku_Event &$event, $param) { global $INPUT; if ($event->data != 'structodt') return; $method = 'action_' . $INPUT->str('action'); if (method_exists($this, $method)) { call_user_func([$this, $method]); } } protected function render_single($row, $templates, $ext='pdf') { global $ID; /** * @var \helper_plugin_structodt */ $helper = plugin_load('helper', 'structodt'); $rendered_pages = []; try { foreach ($templates as $template) { $template = $helper->rowTemplate($row, $template); $resolver = new MediaResolver($ID); $template = $resolver->resolveId($template); if ($template != '' && media_exists($template, '', false)) { $mimetype = mimetype($template); // pdf templates are available only in pdf output format if ($mimetype[0] == 'pdf' && $ext == 'pdf') { $rendered_page = $helper->tmpFileName('pdf'); copy(mediaFN($template), $rendered_page); $rendered_pages[] = $rendered_page; } elseif ($mimetype[0] == 'odt') { $method = 'render' . strtoupper($ext); $rendered_pages[] = $helper->$method($template, $row); } else { throw new \Exception('unknown template file format'); } } } if (count($rendered_pages) > 1) { $tmp_file = $helper->concatenate($rendered_pages); foreach ($rendered_pages as $page) { @unlink($page); } } else { $tmp_file = $rendered_pages[0]; } } catch (\Exception $e) { foreach ($rendered_pages as $page) { @unlink($page); } msg($e->getMessage(), -1); } return $tmp_file; } /** * Render file */ public function action_render() { global $INPUT; $extensions = ['pdf', 'odt']; /** * @var \helper_plugin_structodt */ $helper = plugin_load('helper', 'structodt'); $templates = json_decode($INPUT->str('template')); $ext = $INPUT->str('filetype'); if (!in_array($ext, $extensions)) { msg("Unknown file extension: $ext. Avaliable extensions: " . implode(', ', $extensions), -1); return false; } if (count($templates) > 1 && $ext != 'pdf') { msg("Multiple templates are available only for pdf format.", -1); return false; } $schema = $INPUT->str('schema'); $pid = $INPUT->str('pid'); $rev = $INPUT->str('rev'); $rid = $INPUT->str('rid'); $filename = $INPUT->str('filename'); try { $row = $helper->getRow($schema, $pid, $rev, $rid); if (is_null($row)) { throw new \Exception("Row with id: $pid doesn't exists"); } $tmp_file = $this->render_single($row, $templates, $ext); if (empty($filename)) { $filename = empty($pid) ? $rid : noNS($pid); } else { $filename = $helper->rowTemplate($row, $filename); } } catch (\Exception $e) { msg($e->getMessage(), -1); return false; } $helper->sendFile($tmp_file, $filename, $ext); @unlink($tmp_file); exit(); } /** * Render all files as single PDF or ZIP archive */ public function action_renderAll() { global $INPUT; /** * @var \helper_plugin_structodt */ $helper = plugin_load('helper', 'structodt'); $template_string = htmlspecialchars_decode($INPUT->str('template_string')); $templates = json_decode($template_string); $schemas = $INPUT->arr('schema'); $filter = $INPUT->arr('filter'); $format = $INPUT->str('format', 'zip'); $filename = $INPUT->str('filename'); /** @var Schema $first_schema */ $rows = $helper->getRows($schemas, $first_schema, $filter); $files = []; /** @var Value $row */ $i = 1; foreach ($rows as $row) { $tmp_file = $this->render_single($row, $templates); $tmp_filename = empty($filename) ? $i++ : $helper->rowTemplate($row, $filename); $files[$tmp_filename] = $tmp_file; } //join files try { if ($format == 'pdf') { $tmp_file = $helper->concatenate($files); } elseif ($format == 'zip') { $tmp_file = $helper->tmpFileName('zip'); $archive = new Zip(); $archive->create($tmp_file); foreach ($files as $filename => $file) { $archive->addFile($file, $filename . '.pdf'); } $archive->close(); } } catch (\Exception $e) { msg($e->getMessage(), -1); return false; } finally { foreach ($files as $file) { @unlink($file); } } $filename = $first_schema->getTranslatedLabel(); $helper->sendFile($tmp_file, $filename, $format); @unlink($tmp_file); exit(); } } // vim:ts=4:sw=4:et: