xref: /plugin/dbquery/syntax/query.php (revision 1b7b5e661908b8d7ad42f44f453d6eceae4a998d)
1<?php
2
3/**
4 * DokuWiki Plugin dbquery (Syntax Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Andreas Gohr <dokuwiki@cosmocode.de>
8 */
9class syntax_plugin_dbquery_query extends DokuWiki_Syntax_Plugin
10{
11    /** @inheritDoc */
12    public function getType()
13    {
14        return 'substition';
15    }
16
17    /** @inheritDoc */
18    public function getPType()
19    {
20        return 'block';
21    }
22
23    /** @inheritDoc */
24    public function getSort()
25    {
26        return 135;
27    }
28
29    /** @inheritDoc */
30    public function connectTo($mode)
31    {
32        $this->Lexer->addSpecialPattern('{{QUERY:\w+}}', $mode, 'plugin_dbquery_query');
33    }
34
35    /** @inheritDoc */
36    public function handle($match, $state, $pos, Doku_Handler $handler)
37    {
38        return ['name' => substr($match, 8, -2)];
39    }
40
41    /** @inheritDoc */
42    public function render($mode, Doku_Renderer $renderer, $data)
43    {
44        if ($mode !== 'xhtml') {
45            return false;
46        }
47
48        /** @var helper_plugin_dbquery $hlp */
49        $hlp = plugin_load('helper', 'dbquery');
50        try {
51            $qdata = $hlp->loadDataFromPage($data['name']);
52            $result = $hlp->executeQuery($qdata['codeblocks']['_']);
53        } catch (\Exception $e) {
54            msg(hsc($e->getMessage()), -1);
55            return true;
56        }
57
58        if (count($result) === 1 && isset($result[0]['status']) && isset($qdata['codeblocks'][$result[0]['status']])) {
59            $this->renderStatus($result, $qdata['codeblocks'][$result[0]['status']], $renderer);
60        } else {
61            if ($qdata['macros']['transpose']) {
62                $this->renderTransposedResultTable($result, $renderer);
63            } else {
64                $this->renderResultTable($result, $renderer);
65            }
66        }
67
68        return true;
69    }
70
71    /**
72     * Render given result via the given status HTML
73     *
74     * @param string[][] $result
75     * @param string $html
76     * @param Doku_Renderer $R
77     */
78    public function renderStatus($result, $html, Doku_Renderer $R)
79    {
80        $value = isset($result[0]['result']) ? $result[0]['result'] : '';
81        $html = str_replace(':result', hsc($value), $html);
82        $R->doc .= $html;
83    }
84
85    /**
86     * Render the given result as a table
87     *
88     * @param string[][] $result
89     * @param Doku_Renderer $R
90     */
91    public function renderResultTable($result, Doku_Renderer $R)
92    {
93        global $lang;
94
95        if (!count($result)) {
96            $R->cdata($lang['nothingfound']);
97            return;
98        }
99
100        $R->table_open();
101        $R->tablerow_open();
102        foreach (array_keys($result[0]) as $header) {
103            $R->tableheader_open();
104            $R->cdata($header);
105            $R->tableheader_close();
106        }
107        $R->tablerow_close();
108
109        foreach ($result as $row) {
110            $R->tablerow_open();
111            foreach ($row as $cell) {
112                $R->tablecell_open();
113                $this->cellFormat($cell, $R);
114                $R->tablecell_close();
115            }
116            $R->tablerow_close();
117        }
118        $R->table_close();
119    }
120
121    /**
122     * Render the given result as a table, but turned 90 degrees
123     *
124     * @param string[][] $result
125     * @param Doku_Renderer $R
126     */
127    public function renderTransposedResultTable($result, Doku_Renderer $R)
128    {
129        global $lang;
130
131        if (!count($result)) {
132            $R->cdata($lang['nothingfound']);
133            return;
134        }
135
136        $width = count($result[0]);
137        $height = count($result);
138
139        $R->table_open();
140        for ($x = 0; $x < $width; $x++) {
141            $R->tablerow_open();
142            $R->tableheader_open();
143            $R->cdata(array_keys($result[0])[$x]);
144            $R->tableheader_close();
145
146            for ($y = 0; $y < $height; $y++) {
147                $R->tablecell_open();
148                $this->cellFormat(array_values($result[$y])[$x], $R);
149                $R->tablecell_close();
150            }
151            $R->tablerow_close();
152        }
153        $R->table_close();
154    }
155
156    /**
157     * Pass the given cell content to the correct renderer call
158     *
159     * Detects a subset of the wiki link syntax
160     *
161     * @param string $content
162     * @param Doku_Renderer $R
163     * @return void
164     */
165    protected function cellFormat($content, Doku_Renderer $R)
166    {
167        // external urls
168        if (preg_match('/^\[\[(https?:\/\/[^|\]]+)(|.*?)?]]$/', $content, $m)) {
169            $url = $m[1];
170            $title = $m[2] ?? '';
171            $title = trim($title,'|');
172            $R->externallink($url, $title);
173            return;
174        }
175
176        // internal urls
177        if (preg_match('/^\[\[([^|\]]+)(|.*?)?]]$/', $content, $m)) {
178            $page = cleanID($m[1]);
179            $title = $m[2] ?? '';
180            $title = trim($title,'|');
181            $R->internallink($page, $title);
182            return;
183        }
184
185        $R->cdata($content);
186    }
187}
188
189