xref: /plugin/sqlite/admin.php (revision 271f9cae79deccd6c5d138d0ebf5aa9f77c0e187)
1<?php
2/**
3 * DokuWiki Plugin sqlite (Admin Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <andi@splitbrain.org>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class admin_plugin_sqlite extends DokuWiki_Admin_Plugin {
13
14    function getMenuSort() {
15        return 500;
16    }
17
18    function forAdminOnly() {
19        return true;
20    }
21
22    function handle() {
23        global $conf;
24        global $INPUT;
25
26        if(isset($_POST['sqlite_rename'])) {
27
28            $path = $conf['metadir'].'/'.$_REQUEST['db'];
29            if(io_rename($path.'.sqlite', $path.'.sqlite3')) {
30                msg('Renamed database file succesfull!', 1);
31                //set to new situation
32                $_REQUEST['version'] = 'sqlite3';
33
34            } else {
35                msg('Renaming database file fails!', -1);
36            }
37
38        } elseif(isset($_POST['sqlite_convert'])) {
39
40            /** @var $DBI helper_plugin_sqlite */
41            $DBI        = plugin_load('helper', 'sqlite');
42            $time_start = microtime(true);
43
44            if($dumpfile = $DBI->dumpDatabase($_REQUEST['db'], DOKU_EXT_SQLITE)) {
45                msg('Database temporary dumped to file: '.hsc($dumpfile).'. Now loading in new database...', 1);
46
47                if(!$DBI->fillDatabaseFromDump($_REQUEST['db'], $dumpfile)) {
48                    msg('Conversion failed!', -1);
49                    return false;
50                }
51
52                //TODO delete dumpfile
53                //return @unlink($dumpfile);
54                //TODO delete old sqlite2-db
55                // return @unlink($conf['metadir'].'/'.$_REQUEST['db'].'.sqlite');
56
57                msg('Conversion succeed!', 1);
58                //set to new situation
59                $_REQUEST['version'] = 'sqlite3';
60            }
61            $time_end = microtime(true);
62            $time     = $time_end - $time_start;
63            msg('Database "'.hsc($_REQUEST['db']).'" converted from sqlite 2 to 3 in '.$time.' seconds.', 0);
64
65        } elseif($INPUT->bool('sqlite_export') && checkSecurityToken()) {
66
67            /** @var $DBI helper_plugin_sqlite */
68            $DBI        = plugin_load('helper', 'sqlite');
69            $dbname = $INPUT->str('db');
70
71            $dumpfile = $DBI->dumpDatabase($dbname, DOKU_EXT_PDO, true);
72            if ($dumpfile) {
73                header('Content-Type: text/sql');
74                header('Content-Disposition: attachment; filename="'.$dbname.'.sql";');
75
76                readfile($dumpfile);
77                exit(0);
78            }
79        } elseif($INPUT->bool('sqlite_import') && checkSecurityToken()) {
80            global $conf;
81
82            /** @var $DBI helper_plugin_sqlite */
83            $DBI        = plugin_load('helper', 'sqlite');
84            $dbname = $INPUT->str('db');
85            $dumpfile = $_FILES['dumpfile']['tmp_name'];
86
87            if (empty($dumpfile)) {
88                msg($this->getLang('import_no_file'), -1);
89                return;
90            }
91
92            if ($DBI->fillDatabaseFromDump($dbname, $dumpfile, true)) {
93                msg($this->getLang('import_success'), 1);
94            }
95        }
96    }
97
98    function html() {
99        global $ID;
100        global $conf;
101        global $INPUT;
102
103        echo $this->locale_xhtml('intro');
104
105        if(isset($_REQUEST['db']) && checkSecurityToken()) {
106
107            echo '<h2>'.$this->getLang('db').' "'.hsc($_REQUEST['db']).'"</h2>';
108            echo '<div class="level2">';
109
110            $sqlcommandform = true;
111            /** @var $DBI helper_plugin_sqlite */
112            $DBI = plugin_load('helper', 'sqlite');
113            if($_REQUEST['version'] == 'sqlite2') {
114                if(helper_plugin_sqlite_adapter::isSqlite3db($conf['metadir'].'/'.$_REQUEST['db'].'.sqlite')) {
115
116                    msg('This is a database in sqlite3 format.', 2);
117                    msg(
118                        'This plugin needs your database file has the extension ".sqlite3"
119                        instead of ".sqlite" before it will be recognized as sqlite3 database.', 2
120                    );
121                    $form = new Doku_Form(array('method'=> 'post'));
122                    $form->addHidden('page', 'sqlite');
123                    $form->addHidden('sqlite_rename', 'go');
124                    $form->addHidden('db', $_REQUEST['db']);
125                    $form->addElement(form_makeButton('submit', 'admin', sprintf($this->getLang('rename2to3'), hsc($_REQUEST['db']))));
126                    $form->printForm();
127
128                    if($DBI->existsPDOSqlite()) $sqlcommandform = false;
129
130                } else {
131                    if($DBI->existsPDOSqlite()) {
132                        $sqlcommandform = false;
133                        msg('This is a database in sqlite2 format.', 2);
134
135                        if($DBI->existsSqlite2()) {
136                            $form = new Doku_Form(array('method'=> 'post'));
137                            $form->addHidden('page', 'sqlite');
138                            $form->addHidden('sqlite_convert', 'go');
139                            $form->addHidden('db', $_REQUEST['db']);
140                            $form->addElement(form_makeButton('submit', 'admin', sprintf($this->getLang('convert2to3'), hsc($_REQUEST['db']))));
141                            $form->printForm();
142                        } else {
143                            msg(
144                                'Before PDO sqlite can handle this format, it needs a conversion to the sqlite3 format.
145                                Because PHP sqlite extension is not available,
146                                you should manually convert "'.hsc($_REQUEST['db']).'.sqlite" in the meta directory to "'.hsc($_REQUEST['db']).'.sqlite3".<br />
147                                See for info about the conversion '.$this->external_link('http://www.sqlite.org/version3.html').'.', -1
148                            );
149                        }
150                    }
151                }
152            } else {
153                if(!$DBI->existsPDOSqlite()) {
154                    $sqlcommandform = false;
155                    msg('A database in sqlite3 format needs the PHP PDO sqlite plugin.', -1);
156                }
157            }
158
159            if($sqlcommandform) {
160                echo '<ul>';
161                echo '<li><div class="li"><a href="'.
162                    wl(
163                        $ID, array(
164                                  'do'     => 'admin',
165                                  'page'   => 'sqlite',
166                                  'db'     => $_REQUEST['db'],
167                                  'version'=> $_REQUEST['version'],
168                                  'sql'    => 'SELECT name,sql FROM sqlite_master WHERE type=\'table\' ORDER BY name',
169                                  'sectok' => getSecurityToken()
170                             )
171                    ).
172                    '">'.$this->getLang('table').'</a></div></li>';
173                echo '<li><div class="li"><a href="'.
174                    wl(
175                        $ID, array(
176                                  'do'     => 'admin',
177                                  'page'   => 'sqlite',
178                                  'db'     => $_REQUEST['db'],
179                                  'version'=> $_REQUEST['version'],
180                                  'sql'    => 'SELECT name,sql FROM sqlite_master WHERE type=\'index\' ORDER BY name',
181                                  'sectok' => getSecurityToken()
182                             )
183                    ).
184                    '">'.$this->getLang('index').'</a></div></li>';
185                echo '<li><div class="li"><a href="'.
186                    wl(
187                        $ID, array(
188                               'do'     => 'admin',
189                               'page'   => 'sqlite',
190                               'db'     => $_REQUEST['db'],
191                               'version'=> $_REQUEST['version'],
192                               'sqlite_export' => '1',
193                               'sectok' => getSecurityToken()
194                           )
195                    ).
196                    '">'.$this->getLang('export').'</a></div></li>';
197
198
199                $form = new \dokuwiki\Form\Form(array('enctype' => 'multipart/form-data'));
200                $form->setHiddenField('id', $ID);
201                $form->setHiddenField('do', 'admin');
202                $form->setHiddenField('page', 'sqlite');
203                $form->setHiddenField('db', $_REQUEST['db']);
204                $form->setHiddenField('version', $_REQUEST['version']);
205                $form->addElement(new dokuwiki\Form\InputElement('file', 'dumpfile'));
206                $form->addButton('sqlite_import', $this->getLang('import'));
207                echo '<li>' . $form->toHTML() . '</li>';
208                echo '</ul>';
209
210                if(!$DBI->init($_REQUEST['db'], '')) return;
211
212                if($INPUT->str('action') == 'save') {
213                    $ok = true;
214                    if(empty($INPUT->str('sql'))) {
215                        echo '<div class="error">give the query</div>';
216                        $ok = false;
217                    }
218                    if(empty($INPUT->str('name'))) {
219                        echo '<div class="error">give the query name</div>';
220                        $ok = false;
221                    }
222                    if($ok) {
223                        // Create queries table if not exists
224                        $res = $DBI->query("CREATE TABLE IF NOT EXISTS meta_queries
225                                                    (id INTEGER PRIMARY KEY,
226                                                    name TEXT NOT NULL,
227                                                    sql TEXT NOT NULL);");
228                        $DBI->storeEntry('meta_queries', array(
229                            'name' => $INPUT->str('name'),
230                            'sql' => $INPUT->str('sql')
231                        ));
232                        echo '<div class="success">query saved</div>';
233                    }
234                } elseif($INPUT->str('action') == 'delete') {
235                    $DBI->query("DELETE FROM meta_queries WHERE id=?;", $INPUT->int('id'));
236                    echo '<div class="success">query deleted</div>';
237                }
238
239                $form = new Doku_Form(array('class'=> 'sqliteplugin'));
240                $form->startFieldset('SQL Command');
241                $form->addHidden('id', $ID);
242                $form->addHidden('do', 'admin');
243                $form->addHidden('page', 'sqlite');
244                $form->addHidden('db', $_REQUEST['db']);
245                $form->addHidden('version', $_REQUEST['version']);
246                $form->addElement('<textarea name="sql" class="edit">'.hsc($_REQUEST['sql']).'</textarea>');
247                $form->addElement('<input type="submit" class="button" /> ');
248                $form->addElement('<label>Query name: <input type="text" name="name" /></label> ');
249                $form->addElement('<button name="action" value="save">Save</button>');
250                $form->endFieldset();
251                $form->printForm();
252
253                // List saved queries
254                $meta_queries_table_name = 'meta_queries';
255                $res = $DBI->query("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", $meta_queries_table_name);
256                $cnt = $DBI->res2count($res);
257                if($cnt == 1) {
258                    print '<h3>Saved queries</h3>';
259                    $res = $DBI->query("SELECT id, name, sql FROM $meta_queries_table_name");
260                    $result = $DBI->res2arr($res);
261                    echo '<div>';
262                    echo '<table class="inline">';
263                    echo '<tr>';
264                    echo '<th>id</th>';
265                    echo '<th>name</th>';
266                    echo '<th>sql</th>';
267                    echo '<th></th>';
268                    echo '</tr>';
269                    foreach($result as $row) {
270                        echo '<tr>';
271                        echo '<td>'.hsc($row['id']).'</td>';
272                        echo '<td>'.hsc($row['name']).'</td>';
273                        $link = wl($ID, array(  'do'=> 'admin',
274                                                'page'=> 'sqlite',
275                                                'db'=> $_REQUEST['db'],
276                                                'version'=> $_REQUEST['version'],
277                                                'sql' => $row['sql'],
278                                                'sectok'=> getSecurityToken()));
279                        echo '<td><a href="'.$link.'">'.hsc($row['sql']).'</a></td>';
280
281                        $link = wl($ID, array(  'do'=> 'admin',
282                            'page'=> 'sqlite',
283                            'db'=> $_REQUEST['db'],
284                            'version'=> $_REQUEST['version'],
285                            'action' => 'delete',
286                            'id' => $row['id'],
287                            'sectok'=> getSecurityToken()));
288                        echo '<td><a href="'.$link.'">delete</a></td>';
289                        echo '</tr>';
290                    }
291                    echo '</table>';
292                    echo '</div>';
293                }
294
295                $result = $DBI->res2arr($res);
296
297                if($_REQUEST['sql']) {
298                    print '<h3>Query results</h3>';
299                    $sql = $DBI->SQLstring2array($_REQUEST['sql']);
300                    foreach($sql as $s) {
301                        $s = preg_replace('!^\s*--.*$!m', '', $s);
302                        $s = trim($s);
303                        if(!$s) continue;
304
305                        $time_start = microtime(true);
306
307                        $res = $DBI->query("$s;");
308                        if($res === false) continue;
309
310                        $result = $DBI->res2arr($res);
311
312                        $time_end = microtime(true);
313                        $time     = $time_end - $time_start;
314
315                        $cnt = $DBI->res2count($res);
316                        msg($cnt.' affected rows in '.($time < 0.0001 ? substr($time, 0, 5).substr($time, -3) : substr($time, 0, 7)).' seconds', 1);
317                        if(!$cnt) continue;
318
319                        echo '<div>';
320                        $ths = array_keys($result[0]);
321                        echo '<table class="inline">';
322                        echo '<tr>';
323                        foreach($ths as $th) {
324                            echo '<th>'.hsc($th).'</th>';
325                        }
326                        echo '</tr>';
327                        foreach($result as $row) {
328                            echo '<tr>';
329                            $tds = array_values($row);
330                            foreach($tds as $td) {
331                                if($td === null) $td='';
332                                echo '<td>'.hsc($td).'</td>';
333                            }
334                            echo '</tr>';
335                        }
336                        echo '</table>';
337                        echo '</div>';
338                    }
339                }
340
341            }
342            echo '</div>';
343        }
344    }
345
346    function getTOC() {
347        global $conf;
348        global $ID;
349
350        $toc            = array();
351        $fileextensions = array('sqlite2'=> '.sqlite', 'sqlite3'=> '.sqlite3');
352
353        foreach($fileextensions as $dbformat => $fileextension) {
354            $toc[] = array(
355                'link'  => wl($ID, array('do'=> 'admin', 'page'=> 'sqlite')),
356                'title' => $dbformat.':',
357                'level' => 1,
358                'type'  => 'ul',
359            );
360
361            $dbfiles = glob($conf['metadir'].'/*'.$fileextension);
362
363            if(is_array($dbfiles)) foreach($dbfiles as $file) {
364                $db    = basename($file, $fileextension);
365                $toc[] = array(
366                    'link'  => wl($ID, array('do'=> 'admin', 'page'=> 'sqlite', 'db'=> $db, 'version'=> $dbformat, 'sectok'=> getSecurityToken())),
367                    'title' => $this->getLang('db').' '.$db,
368                    'level' => 2,
369                    'type'  => 'ul',
370                );
371            }
372        }
373
374        return $toc;
375    }
376}
377
378// vim:ts=4:sw=4:et:
379