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($INPUT->bool('sqlite_rename')) { 27 28 $path = $conf['metadir'].'/'.$INPUT->str('db'); 29 if(io_rename($path.'.sqlite', $path.'.sqlite3')) { 30 msg('Renamed database file succesfull!', 1); 31 //set to new situation 32 $INPUT->set('version', 'sqlite3'); 33 34 } else { 35 msg('Renaming database file fails!', -1); 36 } 37 } elseif($INPUT->bool('sqlite_export') && checkSecurityToken()) { 38 39 /** @var $DBI helper_plugin_sqlite */ 40 $DBI = plugin_load('helper', 'sqlite'); 41 $dbname = $INPUT->str('db'); 42 43 $dumpfile = $DBI->dumpDatabase($dbname, DOKU_EXT_PDO, true); 44 if ($dumpfile) { 45 header('Content-Type: text/sql'); 46 header('Content-Disposition: attachment; filename="'.$dbname.'.sql";'); 47 48 readfile($dumpfile); 49 exit(0); 50 } 51 } elseif($INPUT->bool('sqlite_import') && checkSecurityToken()) { 52 global $conf; 53 54 /** @var $DBI helper_plugin_sqlite */ 55 $DBI = plugin_load('helper', 'sqlite'); 56 $dbname = $INPUT->str('db'); 57 $dumpfile = $_FILES['dumpfile']['tmp_name']; 58 59 if (empty($dumpfile)) { 60 msg($this->getLang('import_no_file'), -1); 61 return; 62 } 63 64 if ($DBI->fillDatabaseFromDump($dbname, $dumpfile, true)) { 65 msg($this->getLang('import_success'), 1); 66 } 67 } 68 } 69 70 function html() { 71 global $ID; 72 global $conf; 73 global $INPUT; 74 75 echo $this->locale_xhtml('intro'); 76 77 if($INPUT->has('db') && checkSecurityToken()) { 78 79 echo '<h2>'.$this->getLang('db').' "'.hsc($INPUT->str('db')).'"</h2>'; 80 echo '<div class="level2">'; 81 82 $sqlcommandform = true; 83 /** @var $DBI helper_plugin_sqlite */ 84 $DBI = plugin_load('helper', 'sqlite'); 85 if($INPUT->str('version') == 'sqlite2') { 86 if(helper_plugin_sqlite_adapter::isSqlite3db($conf['metadir'].'/'.$INPUT->str('db').'.sqlite')) { 87 88 msg('This is a database in sqlite3 format.', 2); 89 msg( 90 'This plugin needs your database file has the extension ".sqlite3" 91 instead of ".sqlite" before it will be recognized as sqlite3 database.', 2 92 ); 93 $form = new Doku_Form(array('method'=> 'post')); 94 $form->addHidden('page', 'sqlite'); 95 $form->addHidden('sqlite_rename', 'go'); 96 $form->addHidden('db', $INPUT->str('db')); 97 $form->addElement(form_makeButton('submit', 'admin', sprintf($this->getLang('rename2to3'), hsc($INPUT->str('db'))))); 98 $form->printForm(); 99 100 if($DBI->existsPDOSqlite()) $sqlcommandform = false; 101 102 } else { 103 msg( 104 'Before PDO sqlite can handle this format, it needs a conversion to the sqlite3 format. 105 Because PHP sqlite extension is no longer supported, 106 you should manually convert "'.hsc($INPUT->str('db')).'.sqlite" in the meta directory to "'.hsc($INPUT->str('db')).'.sqlite3".<br /> 107 See for info about the conversion '.$this->external_link('http://www.sqlite.org/version3.html').'.', -1 108 ); 109 } 110 } else { 111 if(!$DBI->existsPDOSqlite()) { 112 $sqlcommandform = false; 113 msg('A database in sqlite3 format needs the PHP PDO sqlite plugin.', -1); 114 } 115 } 116 117 if($sqlcommandform) { 118 echo '<ul>'; 119 echo '<li><div class="li"><a href="'. 120 wl( 121 $ID, array( 122 'do' => 'admin', 123 'page' => 'sqlite', 124 'db' => $INPUT->str('db'), 125 'version'=> $INPUT->str('version'), 126 'sql' => 'SELECT name,sql FROM sqlite_master WHERE type=\'table\' ORDER BY name', 127 'sectok' => getSecurityToken() 128 ) 129 ). 130 '">'.$this->getLang('table').'</a></div></li>'; 131 echo '<li><div class="li"><a href="'. 132 wl( 133 $ID, array( 134 'do' => 'admin', 135 'page' => 'sqlite', 136 'db' => $INPUT->str('db'), 137 'version'=> $INPUT->str('version'), 138 'sql' => 'SELECT name,sql FROM sqlite_master WHERE type=\'index\' ORDER BY name', 139 'sectok' => getSecurityToken() 140 ) 141 ). 142 '">'.$this->getLang('index').'</a></div></li>'; 143 echo '<li><div class="li"><a href="'. 144 wl( 145 $ID, array( 146 'do' => 'admin', 147 'page' => 'sqlite', 148 'db' => $INPUT->str('db'), 149 'version'=> $INPUT->str('version'), 150 'sqlite_export' => '1', 151 'sectok' => getSecurityToken() 152 ) 153 ). 154 '">'.$this->getLang('export').'</a></div></li>'; 155 156 157 $form = new \dokuwiki\Form\Form(array('enctype' => 'multipart/form-data')); 158 $form->setHiddenField('id', $ID); 159 $form->setHiddenField('do', 'admin'); 160 $form->setHiddenField('page', 'sqlite'); 161 $form->setHiddenField('db', $INPUT->str('db')); 162 $form->setHiddenField('version', $INPUT->str('version')); 163 $form->addElement(new dokuwiki\Form\InputElement('file', 'dumpfile')); 164 $form->addButton('sqlite_import', $this->getLang('import')); 165 echo '<li>' . $form->toHTML() . '</li>'; 166 echo '</ul>'; 167 168 /** @var $helper helper_plugin_sqlite */ 169 $sqlite_db = plugin_load('helper', 'sqlite'); 170 $sqlite_db->init('sqlite', DOKU_PLUGIN . 'sqlite/db/'); 171 172 if($INPUT->str('action') == 'save') { 173 $ok = true; 174 if(empty($INPUT->str('sql'))) { 175 msg($this->getLang('validation query_required'), -1); 176 $ok = false; 177 } 178 if(empty($INPUT->str('name'))) { 179 msg($this->getLang('validation query_name_required'), -1); 180 $ok = false; 181 } 182 183 if($ok) { 184 $sqlite_db->storeEntry('queries', array( 185 'db' => $INPUT->str('db'), 186 'name' => $INPUT->str('name'), 187 'sql' => $INPUT->str('sql') 188 )); 189 msg($this->getLang('success query_saved'), 1); 190 } 191 } elseif($INPUT->str('action') == 'delete') { 192 $sqlite_db->query("DELETE FROM queries WHERE id=?;", $INPUT->int('query_id')); 193 msg($this->getLang('success query_deleted'), 1); 194 } 195 196 $form = new Doku_Form(array('class'=> 'sqliteplugin', 'action' => wl($ID, '', true, '&'))); 197 $form->startFieldset('SQL Command'); 198 $form->addHidden('id', $ID); 199 $form->addHidden('do', 'admin'); 200 $form->addHidden('page', 'sqlite'); 201 $form->addHidden('db', $INPUT->str('db')); 202 $form->addHidden('version', $INPUT->str('version')); 203 $form->addElement('<textarea name="sql" class="edit">'.hsc($INPUT->str('sql')).'</textarea>'); 204 $form->addElement('<input type="submit" class="button" /> '); 205 $form->addElement('<label>'.$this->getLang('query_name').': <input type="text" name="name" /></label> '); 206 $form->addElement('<button name="action" value="save">'.$this->getLang('save_query').'</button>'); 207 $form->endFieldset(); 208 $form->printForm(); 209 210 // List saved queries 211 $res = $sqlite_db->query("SELECT id, name, sql FROM queries WHERE db=?", $INPUT->str('db')); 212 $result = $sqlite_db->res2arr($res); 213 if(count($result) > 0) { 214 echo '<h3>' . $this->getLang('saved_queries') . '</h3>'; 215 echo '<div>'; 216 echo '<table class="inline">'; 217 echo '<tr>'; 218 echo '<th>name</th>'; 219 echo '<th>sql</th>'; 220 echo '<th></th>'; 221 echo '</tr>'; 222 foreach($result as $row) { 223 echo '<tr>'; 224 echo '<td>'.hsc($row['name']).'</td>'; 225 $link = wl($ID, array( 'do'=> 'admin', 226 'page'=> 'sqlite', 227 'db'=> $INPUT->str('db'), 228 'version'=> $INPUT->str('version'), 229 'sql' => $row['sql'], 230 'sectok'=> getSecurityToken())); 231 echo '<td><a href="'.$link.'">'.hsc($row['sql']).'</a></td>'; 232 233 $link = wl($ID, array( 'do'=> 'admin', 234 'page'=> 'sqlite', 235 'db'=> $INPUT->str('db'), 236 'version'=> $INPUT->str('version'), 237 'action' => 'delete', 238 'query_id' => $row['id'], 239 'sectok'=> getSecurityToken())); 240 echo '<td><a href="'.$link.'">delete</a></td>'; 241 echo '</tr>'; 242 } 243 echo '</table>'; 244 echo '</div>'; 245 } 246 247 if($INPUT->has('sql')) { 248 if(!$DBI->init($INPUT->str('db'), '')) return; 249 250 print '<h3>Query results</h3>'; 251 $sql = $DBI->SQLstring2array($INPUT->str('sql')); 252 foreach($sql as $s) { 253 $s = preg_replace('!^\s*--.*$!m', '', $s); 254 $s = trim($s); 255 if(!$s) continue; 256 257 $time_start = microtime(true); 258 259 $res = $DBI->query("$s;"); 260 if($res === false) continue; 261 262 $result = $DBI->res2arr($res); 263 264 $time_end = microtime(true); 265 $time = $time_end - $time_start; 266 267 $cnt = $DBI->res2count($res); 268 msg($cnt.' affected rows in '.($time < 0.0001 ? substr($time, 0, 5).substr($time, -3) : substr($time, 0, 7)).' seconds', 1); 269 if(!$cnt) continue; 270 271 echo '<div>'; 272 $ths = array_keys($result[0]); 273 echo '<table class="inline">'; 274 echo '<tr>'; 275 foreach($ths as $th) { 276 echo '<th>'.hsc($th).'</th>'; 277 } 278 echo '</tr>'; 279 foreach($result as $row) { 280 echo '<tr>'; 281 $tds = array_values($row); 282 foreach($tds as $td) { 283 if($td === null) $td='␀'; 284 echo '<td>'.hsc($td).'</td>'; 285 } 286 echo '</tr>'; 287 } 288 echo '</table>'; 289 echo '</div>'; 290 } 291 } 292 293 } 294 echo '</div>'; 295 } 296 } 297 298 function getTOC() { 299 global $conf; 300 global $ID; 301 302 $toc = array(); 303 $fileextensions = array('sqlite2'=> '.sqlite', 'sqlite3'=> '.sqlite3'); 304 305 foreach($fileextensions as $dbformat => $fileextension) { 306 $toc[] = array( 307 'link' => wl($ID, array('do'=> 'admin', 'page'=> 'sqlite')), 308 'title' => $dbformat.':', 309 'level' => 1, 310 'type' => 'ul', 311 ); 312 313 $dbfiles = glob($conf['metadir'].'/*'.$fileextension); 314 315 if(is_array($dbfiles)) foreach($dbfiles as $file) { 316 $db = basename($file, $fileextension); 317 $toc[] = array( 318 'link' => wl($ID, array('do'=> 'admin', 'page'=> 'sqlite', 'db'=> $db, 'version'=> $dbformat, 'sectok'=> getSecurityToken())), 319 'title' => $this->getLang('db').' '.$db, 320 'level' => 2, 321 'type' => 'ul', 322 ); 323 } 324 } 325 326 return $toc; 327 } 328} 329 330// vim:ts=4:sw=4:et: 331