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