|
|
<?php |
|
|
namespace app\admin\controller; |
|
|
use think\Db; |
|
|
use app\common\util\Dir; |
|
|
use app\common\util\Database as dbOper; |
|
|
|
|
|
class Database extends Base |
|
|
{ |
|
|
var $_db_config; |
|
|
public function __construct() |
|
|
{ |
|
|
parent::__construct(); |
|
|
} |
|
|
|
|
|
public function index() |
|
|
{ |
|
|
$group = input('group'); |
|
|
if($group=='import'){ |
|
|
|
|
|
$path = trim( $GLOBALS['config']['db']['backup_path'], '/').DS; |
|
|
if (!is_dir($path)) { |
|
|
Dir::create($path); |
|
|
} |
|
|
$flag = \FilesystemIterator::KEY_AS_FILENAME; |
|
|
$glob = new \FilesystemIterator($path, $flag); |
|
|
|
|
|
$list = []; |
|
|
foreach ($glob as $name => $file) { |
|
|
if(preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql(?:\.gz)?$/', $name)){ |
|
|
$name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d'); |
|
|
$date = "{$name[0]}-{$name[1]}-{$name[2]}"; |
|
|
$time = "{$name[3]}:{$name[4]}:{$name[5]}"; |
|
|
$part = $name[6]; |
|
|
|
|
|
if(isset($list["{$date} {$time}"])){ |
|
|
$info = $list["{$date} {$time}"]; |
|
|
$info['part'] = max($info['part'], $part); |
|
|
$info['size'] = $info['size'] + $file->getSize(); |
|
|
} else { |
|
|
$info['part'] = $part; |
|
|
$info['size'] = $file->getSize(); |
|
|
} |
|
|
|
|
|
$extension = strtoupper($file->getExtension()); |
|
|
$info['compress'] = ($extension === 'SQL') ? '无' : $extension; |
|
|
$info['time'] = strtotime("{$date} {$time}"); |
|
|
|
|
|
$list["{$date} {$time}"] = $info; |
|
|
} |
|
|
} |
|
|
} |
|
|
else{ |
|
|
$group='export'; |
|
|
$list = Db::query("SHOW TABLE STATUS"); |
|
|
} |
|
|
|
|
|
$this->assign('list',$list); |
|
|
$this->assign('title',lang('admin/database/title')); |
|
|
return $this->fetch('admin@database/'.$group); |
|
|
} |
|
|
|
|
|
public function export($ids = '', $start = 0) |
|
|
{ |
|
|
if ($this->request->isPost()) { |
|
|
if (empty($ids)) { |
|
|
return $this->error(lang('admin/database/select_export_table')); |
|
|
} |
|
|
|
|
|
if (!is_array($ids)) { |
|
|
$tables[] = $ids; |
|
|
} else { |
|
|
$tables = $ids; |
|
|
} |
|
|
$have_admin = false; |
|
|
$admin_table=''; |
|
|
foreach($tables as $k=>$v){ |
|
|
if(strpos($v,'_admin')!==false){ |
|
|
$have_admin=true; |
|
|
$admin_table = $v; |
|
|
unset($tables[$k]); |
|
|
} |
|
|
} |
|
|
if($have_admin){ |
|
|
$tables[] = $admin_table; |
|
|
} |
|
|
|
|
|
|
|
|
$config = array( |
|
|
'path' => $GLOBALS['config']['db']['backup_path'] .DS, |
|
|
'part' => $GLOBALS['config']['db']['part_size'] , |
|
|
'compress' => $GLOBALS['config']['db']['compress'] , |
|
|
'level' => $GLOBALS['config']['db']['compress_level'] , |
|
|
); |
|
|
|
|
|
|
|
|
$lock = "{$config['path']}backup.lock"; |
|
|
if(is_file($lock)){ |
|
|
return $this->error(lang('admin/database/lock_check')); |
|
|
} else { |
|
|
if (!is_dir($config['path'])) { |
|
|
Dir::create($config['path'], 0755, true); |
|
|
} |
|
|
|
|
|
file_put_contents($lock, $this->request->time()); |
|
|
} |
|
|
|
|
|
|
|
|
$file = [ |
|
|
'name' => date('Ymd-His', $this->request->time()), |
|
|
'part' => 1, |
|
|
]; |
|
|
|
|
|
|
|
|
$database = new dbOper($file, $config); |
|
|
if($database->create() !== false) { |
|
|
|
|
|
foreach ($tables as $table) { |
|
|
$start = $database->backup($table, $start); |
|
|
while (0 !== $start) { |
|
|
if (false === $start) { |
|
|
return $this->error(lang('admin/database/backup_err')); |
|
|
} |
|
|
$start = $database->backup($table, $start[0]); |
|
|
} |
|
|
} |
|
|
|
|
|
unlink($lock); |
|
|
} |
|
|
return $this->success(lang('admin/database/backup_ok')); |
|
|
} |
|
|
return $this->error(lang('admin/database/backup_err')); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function import($id = '') |
|
|
{ |
|
|
if (empty($id)) { |
|
|
return $this->error(lang('admin/database/select_file')); |
|
|
} |
|
|
|
|
|
$name = date('Ymd-His', $id) . '-*.sql*'; |
|
|
$path = trim( $GLOBALS['config']['db']['backup_path'] , '/').DS.$name; |
|
|
$files = glob($path); |
|
|
$list = array(); |
|
|
foreach($files as $name){ |
|
|
$basename = basename($name); |
|
|
$match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d'); |
|
|
$gz = preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql.gz$/', $basename); |
|
|
$list[$match[6]] = array($match[6], $name, $gz); |
|
|
} |
|
|
ksort($list); |
|
|
|
|
|
|
|
|
$last = end($list); |
|
|
if(count($list) === $last[0]){ |
|
|
foreach ($list as $item) { |
|
|
$config = [ |
|
|
'path' => trim($GLOBALS['config']['db']['backup_path'], '/').DS, |
|
|
'compress' => $item[2] |
|
|
]; |
|
|
$database = new dbOper($item, $config); |
|
|
$start = $database->import(0); |
|
|
|
|
|
while (0 !== $start) { |
|
|
if (false === $start) { |
|
|
return $this->error(lang('admin/database/import_err')); |
|
|
} |
|
|
$start = $database->import($start[0]); |
|
|
} |
|
|
} |
|
|
return $this->success(lang('admin/database/import_ok')); |
|
|
} |
|
|
return $this->error(lang('admin/database/file_damage')); |
|
|
} |
|
|
|
|
|
public function optimize($ids = '') |
|
|
{ |
|
|
if (empty($ids)) { |
|
|
return $this->error(lang('admin/database/select_optimize_table')); |
|
|
} |
|
|
|
|
|
if (!is_array($ids)) { |
|
|
$table[] = $ids; |
|
|
} else { |
|
|
$table = $ids; |
|
|
} |
|
|
|
|
|
$tables = implode('`,`', $table); |
|
|
$res = Db::query("OPTIMIZE TABLE `{$tables}`"); |
|
|
if ($res) { |
|
|
return $this->success(lang('admin/database/optimize_ok')); |
|
|
} |
|
|
return $this->error(lang('admin/database/optimize_err')); |
|
|
} |
|
|
|
|
|
public function repair($ids = '') |
|
|
{ |
|
|
if (empty($ids)) { |
|
|
return $this->error(lang('admin/database/select_repair_table')); |
|
|
} |
|
|
|
|
|
if (!is_array($ids)) { |
|
|
$table[] = $ids; |
|
|
} else { |
|
|
$table = $ids; |
|
|
} |
|
|
|
|
|
$tables = implode('`,`', $table); |
|
|
$res = Db::query("REPAIR TABLE `{$tables}`"); |
|
|
if ($res) { |
|
|
return $this->success(lang('admin/database/repair_ok')); |
|
|
} |
|
|
return $this->error(lang('admin/database/repair_ok')); |
|
|
} |
|
|
|
|
|
public function del($id = '') |
|
|
{ |
|
|
if (empty($id)) { |
|
|
return $this->error(lang('admin/database/select_del_file')); |
|
|
} |
|
|
|
|
|
$name = date('Ymd-His', $id) . '-*.sql*'; |
|
|
$path = trim($GLOBALS['config']['db']['backup_path']).DS.$name; |
|
|
array_map("unlink", glob($path)); |
|
|
if(count(glob($path)) && glob($path)){ |
|
|
return $this->error(lang('del_err')); |
|
|
} |
|
|
return $this->success(lang('del_ok')); |
|
|
} |
|
|
|
|
|
public function sql() |
|
|
{ |
|
|
if($this->request->isPost()){ |
|
|
$param=input(); |
|
|
$validate = \think\Loader::validate('Token'); |
|
|
if(!$validate->check($param)){ |
|
|
return $this->error($validate->getError()); |
|
|
} |
|
|
|
|
|
$sql = trim($param['sql']); |
|
|
|
|
|
if(!empty($sql)){ |
|
|
$sql = str_replace('{pre}',config('database.prefix'),$sql); |
|
|
|
|
|
if( |
|
|
strtolower(substr($sql,0,6))=="select" || |
|
|
stripos($sql, ' outfile') !== false |
|
|
){ |
|
|
|
|
|
} |
|
|
else{ |
|
|
Db::execute($sql); |
|
|
} |
|
|
} |
|
|
$this->success(lang('run_ok')); |
|
|
} |
|
|
return $this->fetch('admin@database/sql'); |
|
|
} |
|
|
|
|
|
public function columns() |
|
|
{ |
|
|
$param = input(); |
|
|
$table = $param['table']; |
|
|
if (!empty($table) && !$this->isValidTable($table)) { |
|
|
return $this->error('Table is invalid.'); |
|
|
} |
|
|
if (!empty($table)) { |
|
|
$list = Db::query('SHOW COLUMNS FROM ' . $table); |
|
|
$this->success(lang('obtain_ok'),null, $list); |
|
|
} |
|
|
$this->error(lang('param_err')); |
|
|
} |
|
|
|
|
|
public function rep() |
|
|
{ |
|
|
if($this->request->isPost()){ |
|
|
$param = input(); |
|
|
$table = $param['table']; |
|
|
$field = $param['field']; |
|
|
$findstr = $param['findstr']; |
|
|
$tostr = $param['tostr']; |
|
|
$where = $param['where']; |
|
|
|
|
|
$validate = \think\Loader::validate('Token'); |
|
|
if(!$validate->check($param)){ |
|
|
return $this->error($validate->getError()); |
|
|
} |
|
|
if (!empty($table) && !$this->isValidTable($table)) { |
|
|
return $this->error('Table is invalid.'); |
|
|
} |
|
|
if(!empty($field) && !empty($findstr) && !empty($tostr)){ |
|
|
$sql = "UPDATE ".$table." set ".$field."=Replace(".$field.",'".$findstr."','".$tostr."') where 1=1 ". $where; |
|
|
Db::execute($sql); |
|
|
return $this->success(lang('run_ok')); |
|
|
} |
|
|
|
|
|
return $this->error(lang('param_err')); |
|
|
} |
|
|
$list = Db::query("SHOW TABLE STATUS"); |
|
|
$this->assign('list',$list); |
|
|
return $this->fetch('admin@database/rep'); |
|
|
} |
|
|
|
|
|
private function isValidTable($table) { |
|
|
$list = Db::query("SHOW TABLE STATUS"); |
|
|
foreach ($list as $table_raw) { |
|
|
if ($table_raw['Name'] == $table) { |
|
|
return true; |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|