1<?php
2/**
3 * DokuWiki Plugin structodt (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Szymon Olewniczak <it@rid.pl>
7 */
8
9use dokuwiki\plugin\struct\meta\Schema;
10use dokuwiki\plugin\struct\meta\Value;
11
12// must be run within Dokuwiki
13if(!defined('DOKU_INC')) die();
14
15class action_plugin_structodt extends DokuWiki_Action_Plugin {
16    /**
17     * Registers a callback function for a given event
18     *
19     * @param Doku_Event_Handler $controller DokuWiki's event controller object
20     * @return void
21     */
22    public function register(Doku_Event_Handler $controller) {
23        $controller->register_hook('PLUGIN_STRUCT_CONFIGPARSER_UNKNOWNKEY', 'BEFORE', $this, 'handle_strut_configparser');
24        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_prerpocess');
25    }
26
27    /**
28     * Add "template" config key
29     *
30     * @param Doku_Event $event  event object by reference
31     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
32     *                           handler was registered]
33     * @return void
34     */
35
36    public function handle_strut_configparser(Doku_Event &$event, $param) {
37        /* delete will be removed in future relases */
38        $keys = array('template', 'delete', 'pdf');
39        $data = $event->data;
40
41        $key = $data['key'];
42        $val = trim($data['val']);
43
44        if (!in_array($key, $keys)) return;
45
46        $event->preventDefault();
47        $event->stopPropagation();
48
49        switch ($key) {
50            case 'template':
51                $data['config'][$key] = $val;
52                break;
53            case 'pdf':
54                if (!$val) {
55                    $data['config'][$key] = false;
56                } else {
57                    //check for "unoconv"
58                    $val = shell_exec('command -v unoconv');
59                    if (empty($val)) {
60                        msg('Cannot locate "unoconv". Falling back to ODT mode.', 0);
61                        $data['config'][$key] = false;
62                        break;
63                    }
64                    //check for "ghostscript"
65                    $val = shell_exec('command -v ghostscript');
66                    if (empty($val)) {
67                        msg('Cannot locate "ghostscript". Falling back to ODT mode.', 0);
68                        $data['config'][$key] = false;
69                        break;
70                    }
71                    $data['config'][$key] = true;
72                }
73                break;
74        }
75    }
76
77    /**
78     * Handle odt export
79     *
80     * @param Doku_Event $event event object by reference
81     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
82     *                           handler was registered]
83     * @return void
84     * @throws \splitbrain\PHPArchive\ArchiveIOException
85     * @throws \splitbrain\PHPArchive\FileInfoException
86     */
87
88    public function handle_action_act_prerpocess(Doku_Event &$event, $param) {
89        global $INPUT;
90        if ($event->data != 'structodt') return;
91
92        $method = 'action_' . $INPUT->str('action');
93        if (method_exists($this, $method)) {
94            call_user_func(array($this, $method));
95        }
96    }
97
98    /**
99     * Render file
100     */
101    public function action_render() {
102        global $INPUT;
103
104        /**
105         * @var \helper_plugin_structodt
106         */
107        $helper = plugin_load('helper', 'structodt');
108
109        $template = $INPUT->str('template');
110        $ext = $INPUT->str('filetype');
111        $schema = $INPUT->str('schema');
112        $pid = $INPUT->str('pid');
113        $rev = $INPUT->str('rev');
114        $rid = $INPUT->str('rid');
115
116        $row = $helper->getRow($schema, $pid, $rev, $rid);
117        $template = $helper->rowTemplate($row, $template);
118
119        if (is_null($row)) {
120            msg("Row with id: $pid doesn't exists", -1);
121            return false;
122        }
123
124        $method = 'render' . strtoupper($ext);
125        $tmp_file = $helper->$method($template, $row);
126        if (!$tmp_file) return;
127
128        if ($pid) {
129            $filename = noNS($pid);
130        } else {
131            $filename = $rid;
132        }
133
134        $helper->sendFile($tmp_file, $filename, $ext);
135        unlink($tmp_file);
136        exit();
137    }
138
139    /**
140     * Render all files as single PDF
141     */
142    public function action_renderAll() {
143        global $INPUT;
144
145        /**
146         * @var \helper_plugin_structodt
147         */
148        $helper = plugin_load('helper', 'structodt');
149
150        $template_string = $INPUT->str('template_string');
151        $schemas = $INPUT->arr('schema');
152        $filter = $INPUT->arr('filter');
153
154        /** @var Schema $first_schema */
155        $rows = $helper->getRows($schemas, $first_schema, $filter);
156        $files = [];
157        /** @var Value $row */
158        foreach ($rows as $pid => $row) {
159            $template = $helper->rowTemplate($row, $template_string);
160            $tmp_file = $helper->renderPDF($template, $row);
161            if (!$tmp_file) {
162                array_map('unlink', $files);
163                msg('Cannot render bulk pdf', -1);
164                return;
165            }
166            $files[] = $tmp_file;
167        }
168
169        //join files
170        $tmp_file = $helper->tmpFileName('pdf');
171        $cmd = "ghostscript -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$tmp_file ";
172        $cmd .= implode(' ', $files);
173        $cmd .= ' 2>&1';
174        exec($cmd, $output, $return_var);
175        array_map('unlink', $files);
176        if ($return_var != 0) {
177            msg("PDF merge error($return_var): " . implode('<br>', $output), -1);
178            @unlink($tmp_file);
179            return;
180        }
181
182        $helper->sendFile($tmp_file, $first_schema->getTranslatedLabel(), 'pdf');
183        unlink($tmp_file);
184        exit();
185    }
186}
187
188// vim:ts=4:sw=4:et:
189