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