1<?php
2/**
3 * DokuWiki Plugin structtemplating (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Frieder Schrempf <dev@fris.de>
7 */
8
9use Twig\Environment;
10use Twig\Loader\FilesystemLoader;
11
12use dokuwiki\plugin\struct\meta\AggregationTable;
13
14require_once __DIR__ . '/vendor/autoload.php';
15
16// must be run within Dokuwiki
17if (!defined('DOKU_INC')) {
18    die();
19}
20
21class action_plugin_structtemplating extends DokuWiki_Action_Plugin
22{
23
24    /**
25     * Registers a callback function for a given event
26     *
27     * @param Doku_Event_Handler $controller DokuWiki's event controller object
28     *
29     * @return void
30     */
31    public function register(Doku_Event_Handler $controller)
32    {
33        $controller->register_hook('PLUGIN_STRUCT_RENDER_SCHEMA_DATA', 'BEFORE',
34                                   $this, 'handle_struct_render_schema_data');
35        $controller->register_hook('PLUGIN_STRUCT_RENDER_AGGREGATION_TABLE', 'BEFORE',
36                                   $this, 'handle_struct_render_aggregation_table');
37    }
38
39    /**
40     * [Custom event handler which performs action]
41     *
42     * Called for event: PLUGIN_STRUCT_RENDER_SCHEMA_DATA
43     *
44     * @param Doku_Event $event  event object by reference
45     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
46     *                           handler was registered]
47     *
48     * @return void
49     */
50    public function handle_struct_render_schema_data(Doku_Event $event, $param)
51    {
52        $schemadata = $event->data['schemadata'];
53        $meta = $event->data['meta'];
54        $renderer = $event->data['renderer'];
55        $format = $event->data['format'];
56
57        $schemadata->optionSkipEmpty(true);
58        $data = $schemadata->getData();
59        if (!count($data))
60            return;
61
62        $event->data['hasdata'] = true;
63
64        $path = array(
65            __DIR__ . '/assets/templates/schema',
66            __DIR__ . '/assets/templates/common',
67        );
68
69        try {
70            $loader = new FilesystemLoader($path);
71        } catch (Exception $e) {
72            return;
73        }
74
75        $twig = new Environment($loader, [
76            'debug' => true,
77        ]);
78        $twig->addExtension(new \Twig\Extension\DebugExtension());
79        $twig->addExtension(new \MikeAlmond\TwigColorExtension\ColorExtension());
80
81        foreach ($data as $field) {
82            $idx = strlen($renderer->doc);
83            $field->render($renderer, $format);
84            $field->rendered = substr($renderer->doc, $idx);
85            $renderer->doc = substr($renderer->doc, 0, $idx);
86        }
87
88        try {
89            $twigmarkup = $twig->render(
90                $schemadata->getSchema()->getTable() . '.twig',
91                [
92                    'schema' => $schemadata->getSchema(),
93                    'data' => $data,
94                    'meta' => $meta
95                ]
96            );
97            $renderer->doc .= $twigmarkup;
98        } catch (Exception $e) {
99            return;
100        }
101
102        $event->preventDefault();
103    }
104
105    /**
106     * [Custom event handler which performs action]
107     *
108     * Called for event: PLUGIN_STRUCT_RENDER_AGGREGATION_TABLE
109     *
110     * @param Doku_Event $event  event object by reference
111     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
112     *                           handler was registered]
113     *
114     * @return void
115     */
116    public function handle_struct_render_aggregation_table(Doku_Event $event, $param)
117    {
118        $renderer = $event->data['renderer'];
119        $columns= $event->data['columns'];
120        $table = $event->data['table'];
121        $search = $event->data['search'];
122        $data = $event->data['data'];
123        $format = $event->data['format'];
124
125        $path = array(
126            __DIR__ . '/assets/templates/aggregation',
127            __DIR__ . '/assets/templates/common',
128        );
129
130        try {
131            $loader = new FilesystemLoader($path);
132        } catch (Exception $e) {
133            return;
134        }
135
136        $twig = new Environment($loader, [
137            'debug' => true,
138        ]);
139        $twig->addExtension(new \Twig\Extension\DebugExtension());
140        $twig->addExtension(new \MikeAlmond\TwigColorExtension\ColorExtension());
141
142        /*
143         * If the data covers a single schema, we look for a matching
144         * aggregation template, if none is found or the data spans
145         * over multiple schemas, we use the page id to lookup a template
146         * file.
147         */
148        $templates = array();
149        if (count($search->getSchemas()) === 1)
150            $templates[] = $search->getSchemas()[0]->getTable() . '.twig';
151
152        $templates[] = $table->getID() . '.twig';
153
154        /*
155         * For each field in the table we want to make sure that we
156         * have the rendered value available in the template.
157         */
158        foreach ($data as $row) {
159            foreach ($row as $field) {
160                $idx = strlen($renderer->doc);
161                $field->render($renderer, $format);
162                $field->rendered = substr($renderer->doc, $idx);
163                $renderer->doc = substr($renderer->doc, 0, $idx);
164            }
165        }
166
167        foreach ($templates as $template) {
168            try {
169                $twigmarkup = $twig->render(
170                    $template,
171                    [
172                        'columns' => $columns,
173                        'data' => $data
174                    ]
175                );
176                $renderer->doc .= $twigmarkup;
177                $event->preventDefault();
178                return;
179            } catch (Exception $e) {
180            }
181        }
182    }
183}
184
185