getSrvState(); // 服务器状态单独获取 $data = array(); $data['base'] = $this->getServerInfo(); $data['cache'] = $GLOBALS['config']['cache']; $database = $GLOBALS['config']['database']; $data['db'] = array_change_key_case($database); $data['db']['db_info'] = $this->getDbInfo($data['db']); show_json($data); } // 获取服务器状态 public function getSrvState(){ if(!Input::get('state', null, 0)) return; $driver = KodIO::defaultDriver(); // 默认为本地存储,且大小不限制,则获取所在磁盘大小 if(strtolower($driver['driver']) == 'local' && $driver['sizeMax'] == '0') { $path = realpath($driver['config']['basePath']); $sizeDef = $this->srvSize($path); }else{ $sizeUse = Model('File')->where(array('ioType' => $driver['id']))->sum('size'); $sizeDef = array( 'sizeTotal' => ((float) $driver['sizeMax']) * 1024 * 1024 * 1024, 'sizeUse' => (float) $sizeUse ); } $server = new ServerInfo(); $memUsage = $server->memUsage(); $sizeMem = array( 'sizeTotal' => $memUsage['total'], 'sizeUse' => $memUsage['used'], ); $data = array( 'cpu' => $server->cpuUsage(), // CPU使用率 'memory' => $sizeMem, // 内存使用率 'server' => $this->srvSize($this->srvPath()), // 服务器系统盘空间 'default' => $sizeDef, // 网盘默认存储空间 'time' => array( 'time' => date('Y-m-d H:i:s'), 'upTime'=> $this->srvUptime() ) ); show_json($data); } // 系统盘路径 private function srvPath(){ $path = '/'; $isWin = $GLOBALS['config']['systemOS'] == 'windows'; if($isWin) { $path = 'C:/'; if(function_exists("exec")){ exec("wmic LOGICALDISK get name",$out); $path = $out[1] . '/'; } } return !file_exists($path) ? false : $path; } // 系统盘大小 private function srvSize ($path){ $data = array('sizeTotal' => 0, 'sizeUse' => 0); if(!function_exists('disk_total_space')){return $data;} if($path) { $data['sizeTotal'] = @disk_total_space($path); $data['sizeUse'] = $data['sizeTotal'] - @disk_free_space($path); } return $data; } // 获取服务器持续运行时间 private function srvUptime(){ $list = array( 'day' => 0, 'hour' => 0, 'minute' => 0, 'second' => 0, ); $time = ''; if ($GLOBALS['config']['systemOS'] == 'windows') { $res = shell_exec('WMIC OS Get LastBootUpTime'); $time = explode("\r\n", $res); $time = isset($time[1]) ? intval($time[1]) : ''; if (!$time) return LNG('common.unavailable'); $time = time() - strtotime($time); }else { $filePath = '/proc/uptime'; if (@is_file($filePath)) { $time = file_get_contents($filePath); } if (!$time) return LNG('common.unavailable'); } $num = (float) $time; $second = (int) fmod($num, 60); $num = (int) ($num / 60); $minute = (int) $num % 60; $num = (int) ($num / 60); $hour = (int) $num % 24; $num = (int) ($num / 24); $day = (int) $num; foreach($list as $k => $v) { $list[$k] = $$k; } $str = ''; foreach($list as $key => $val) { $str .= ' ' . ($val ? $val : 0) . ' ' . LNG('common.'.$key); } return $str; } // 服务器基本信息 public function getServerInfo(){ $data = array( 'server_state' => array(), // 服务器状态 'server_info' => array(), // 服务器信息 'php_info' => array(), // PHP信息 'db_cache_info' => array(), // 数据库&缓存信息 'client_info' => array(), // 我的(客户端)信息 ); // 1.服务器状态 // 2.服务器信息 $server = $_SERVER; $phpVersion = 'PHP/' . PHP_VERSION; $data['server_info'] = array( 'name' => $server['SERVER_NAME'], 'ip' => $server['SERVER_ADDR'], 'time' => date('Y-m-d H:i:s'), 'upTime' => '', 'softWare' => $server['SERVER_SOFTWARE'], 'phpVersion'=> $phpVersion, 'system' => php_uname('a'), 'webPath' => BASIC_PATH, ); // 3.php信息 $data['php_info']['detail'] = 'phpinfo'; $data['php_info']['version'] = $phpVersion; $info = array('memory_limit', 'post_max_size', 'upload_max_filesize', 'max_execution_time', 'max_input_time'); foreach($info as $key) { $data['php_info'][$key] = ini_get($key); // get_cfg_var获取的是配置文件的值,ini_get获取的是当前值 } $data['php_info']['disable_functions'] = ini_get('disable_functions'); $exts = get_loaded_extensions(); $data['php_info']['php_ext'] = implode(',',$exts); $data['php_info']['php_ext_need'] = $this->phpExtNeed($exts); // 4.数据库&缓存信息 $database = $GLOBALS['config']['database']; $dbType = $database['DB_TYPE']; if($dbType == 'pdo') { $dsn = explode(":", $database['DB_DSN']); $dbType = $dsn[0]; } if(in_array($dbType, array('mysql', 'mysqli'))) { $res = Model()->db()->query('select VERSION() as version'); $version = ($res[0] && isset($res[0]['version'])) ? $res[0]['version'] : 0; $dbType = 'MySQL' . ($version ? '/' . $version : ''); }else{ $dbType = ($database['DB_TYPE'] == 'pdo' ? 'PDO-' : '') . str_replace('sqlite', 'SQLite', $dbType); } $data['db_cache_info'] = array( 'db' => $dbType, 'cache' => ucfirst($GLOBALS['config']['cache']['cacheType']) ); // 5.我的信息 $data['client_info'] = array( 'ip' => get_client_ip(), 'ua' => $server['HTTP_USER_AGENT'], 'language' => $server['HTTP_ACCEPT_LANGUAGE'] ); return $data; } private function phpExtNeed($exts){ $init = 'cURL,date,Exif,Fileinfo,Ftp,GD,gettext,intl,Iconv,imagick,json,ldap,Mbstring,Mcrypt,Memcached,MySQLi,SQLite3,OpenSSL,PDO,pdo_mysql,pdo_sqlite,Redis,session,Sockets,Swoole,dom,xml,SimpleXML,libxml,bz2,zip,zlib'; $init = explode(',', $init); $data = array(); foreach($init as $ext) { $value = in_array_not_case($ext, $exts) ? 1 : 0; $data[$ext] = $value; } return $data; } // 数据库信息 public function getDbInfo($database){ $type = $this->_dbType($database); if($type == 'sqlite') { $tables = Model()->db()->getTables(); $rows = 0; foreach($tables as $table) { $rows += Model($table)->count(); } // 数据库文件大小 $file = $database['db_name']; if(!isset($database['db_name'])) { $file = substr($database['db_dsn'], strlen('sqlite:')); } $size = @filesize($file); }else{ $tables = Model()->db()->query('show table status from `' . $database['db_name'] . '`'); $rows = $size = 0; foreach($tables as $item) { $rows += $item['Rows']; $size += ($item['Data_lenth'] + $item['Index_length'] - $item['Data_free']); } } return array( 'total_tables' => count($tables), 'total_rows' => $rows, 'total_size' => $size ); } // 数据库类型:sqlite、mysql public function _dbType($database){ $type = $database['db_type']; if($type == 'pdo') { $dsn = explode(':', $database['db_dsn']); $type = $dsn[0]; } $typeArr = array('sqlite3' => 'sqlite', 'mysqli' => 'mysql'); if(isset($typeArr[$type])) $type = $typeArr[$type]; return $type; } /** * 缓存配置切换检测、保存 */ public function cacheSave(){ if($this->in['check'] == '1'){ $type = Input::get('type','in',null,array('file','redis','memcached')); }else{ $type = Input::get('cacheType','in',null,array('file','redis','memcached')); } if(in_array($type, array('redis','memcached'))) { $data = $this->_cacheCheck($type); if(Input::get('check', null, 0)) { show_json(LNG('admin.setting.checkPassed')); } } // 更新setting_user.php $file = BASIC_PATH . 'config/setting_user.php'; $text = array( PHP_EOL . PHP_EOL, "\$config['cache']['sessionType'] = '{$type}';", "\$config['cache']['cacheType'] = '{$type}';" ); if($type != 'file'){ $text[] = "\$config['cache']['{$type}']['host'] = '".$data['host']."';"; $text[] = "\$config['cache']['{$type}']['port'] = '".$data['port']."';"; if ($type == 'redis' && $data['auth']) { $text[] = "\$config['cache']['{$type}']['auth'] = '".$data['auth']."';"; } } $content = implode(PHP_EOL, $text); if(!file_put_contents($file, $content, FILE_APPEND)) { show_json(LNG('explorer.error'), false); } Cache::deleteAll(); show_json(LNG('explorer.success')); } private function _cacheCheck($type){ if(!extension_loaded($type)){ show_json(sprintf(LNG('common.env.invalidExt'), "[php-{$type}]"), false); } $data = Input::getArray(array( "{$type}Host" => array('check'=>'require', 'aliasKey'=>'host'), "{$type}Port" => array('check'=>'require', 'aliasKey'=>'port') )); $cacheType = ucfirst($type); $handle = new $cacheType(); try{ if($type == 'redis') { $handle->connect($data['host'], $data['port'], 1); $auth = Input::get('redisAuth'); if ($auth) { $data['auth'] = $auth; $handle->auth($auth); } $conn = $handle->ping(); }else{ $conn = $handle->addServer($data['host'], $data['port']); if($conn && !$handle->getStats()) $conn = false; } if(!$conn) show_json(sprintf(LNG('admin.install.cacheError'),"[{$type}]"), false); }catch(Exception $e){ $msg = sprintf(LNG('admin.install.cacheConnectError'),"[{$type}]"); $msg .= '
'.$e->getMessage(); show_json($msg, false); } return $data; } /** * 数据库切换检测、保存 * @return void */ public function dbSave(){ $this->taskGet('change'); // 获取任务状态 $this->taskClear('change'); // 清除失败的数据 // 当前数据库配置 $database = $GLOBALS['config']['database']; $database = array_change_key_case($database); $type = $this->_dbType($database); // 数据库类型 $data = Input::getArray(array( 'db_type' => array('check' => 'in', 'param' => array('sqlite', 'mysql', 'pdo')), 'db_dsn' => array('default' => ''), // mysql/sqlite )); $dbType = !empty($data['db_dsn']) ? $data['db_dsn'] : $data['db_type']; $pdo = !empty($data['db_dsn']) ? 'pdo' : ''; $dbList = $this->validDbList(); // 判断系统环境是否支持选择的数据库类型 if($pdo == 'pdo') { if(!in_array('pdo_'.$dbType, $dbList)) { show_json(sprintf(LNG('common.env.invalidExt'), 'pdo_'.$dbType), false); } }else{ $allow = false; foreach($dbList as $value) { if($value == $dbType || stripos($value, $dbType) === 0) { $allow = true; break; } } if(!$allow) show_json(sprintf(LNG('common.env.invalidExt'), $dbType), false); } // 1. 切换了数据库类型,则全新安装,走完整流程 if($dbType != $type) { return $this->dbChangeSave($dbType, $pdo, $database); } // 2. 没有改变数据库类型:pdo连接、配置参数、数据库变更等 if($type == 'sqlite') { // 无论是检测还是保存,都直接返回 show_json(LNG('admin.setting.dbNeedOthers'), false); } $data = $this->filterMysqlData(); $match = true; foreach($data as $key => $value) { if($value != $database[$key]) { $match = false; break; } } // 2.2.1 配置参数不同 if(!$match) { return $this->dbChangeSave($dbType, $pdo, $database); } $check = Input::get('check', null, false); // 2.2.2 配置参数相同,都是or不是pdo方式 if($pdo == $database['db_type'] || (!$pdo && $database['db_type'] != 'pdo')) { if($check) show_json(LNG('admin.setting.dbNeedChange'), false); // 说明没有修改,禁止切换 show_json(LNG('explorer.success')); } if($check) show_json(LNG('admin.setting.checkPassed')); // 2.2.3 只是变更了pdo连接方式,更新配置文件,无需其他操作 $option = $this->filterDatabase($pdo, $type, $database, $dbList); $option = array_merge($option, $data); $option = array_merge($option, $this->dbExtend($database)); $option = array_change_key_case($option, CASE_UPPER); // 3. 保存配置 $this->settingSave($dbType, $option, 'change'); show_json(LNG('explorer.success')); } // 获取db_type、db_name/dsn配置 private function filterDatabase($pdo, $type, $data, $dbList){ if($pdo == 'pdo') { $option = array( 'db_type' => 'pdo', 'db_dsn' => $type, 'db_name' => $data['db_name'] ); $dsn = $data['db_name']; if($type == 'mysql') { $port = (isset($data['db_port']) && $data['db_port'] != '3306') ? "port={$data['db_port']};" : ''; $dsn = "host={$data['db_host']};{$port}dbname={$data['db_name']}"; } $option['db_dsn'] .= ':' . $dsn; }else{ $option = array( 'db_type' => $type, 'db_name' => $data['db_name'] ); if($type == 'sqlite') { if(in_array('sqlite3', $dbList)) $option['db_type'] = 'sqlite3'; }else{ if(in_array('mysqli', $dbList)) $option['db_type'] = 'mysqli'; } } return $option; } // 获取mysql配置参数 private function filterMysqlData(){ $data = Input::getArray(array( 'db_host' => array('check' => 'require'), 'db_port' => array('default' => 3306), 'db_user' => array('check' => 'require'), 'db_pwd' => array('check' => 'require', 'default' => ''), 'db_name' => array('check' => 'require'), )); $host = explode(':', $data['db_host']); if(isset($host[1])) { $data['db_host'] = $host[0]; $data['db_port'] = (int) $host[1]; } return $data; } // 数据库配置追加内容 private function dbExtend($database){ $keys = array('db_sql_log', 'db_fields_cache', 'db_sql_build_cache'); $data = array(); foreach($keys as $key) { $data[$key] = $database[$key]; } return $data; } // 写入配置文件的sqlite信息位置过滤 private function filterSqliteSet($content) { $replaceFrom = "'DB_NAME' => '".USER_SYSTEM; $replaceTo = "'DB_NAME' => USER_SYSTEM.'"; $replaceFrom2= "'DB_DSN' => 'sqlite:".USER_SYSTEM; $replaceTo2 = "'DB_DSN' => 'sqlite:'.USER_SYSTEM.'"; $content = str_replace($replaceFrom,$replaceTo,$content); $content = str_replace($replaceFrom2,$replaceTo2,$content); return $content; } // 有效的数据库扩展 private function validDbList(){ $db_exts = array('sqlite', 'sqlite3', 'mysql', 'mysqli', 'pdo_sqlite', 'pdo_mysql'); $dblist = array_map(function($ext){ if (extension_loaded($ext)){ return $ext; } }, $db_exts); return array_filter($dblist); } // 数据库配置保存到setting_user.php private function settingSave($dbType, $option, $type){ $option = var_export($option, true); $file = BASIC_PATH . 'config/setting_user.php'; $content = PHP_EOL . PHP_EOL . "\$config['database'] = {$option};"; if($dbType == 'sqlite') { $content = $this->filterSqliteSet($content); } if(!file_put_contents($file, $content, FILE_APPEND)) { // 删除复制的数据表文件 del_dir($this->tmpActPath($type)); show_json(LNG('explorer.error'), false); } } // 生成全新的数据库 public function dbChangeSave($dbType, $pdo, $database){ // 1. 获取数据库配置信息 $dbList = $this->validDbList(); if($dbType == 'sqlite') { if(Input::get('check', null, false)) { show_json(LNG('admin.setting.checkPassed')); } $dbFile = USER_SYSTEM . rand_string(12) . '.php'; if(!@touch($dbFile)) { show_json(LNG('admin.setting.dbCreateError'), false); } $data = array('db_name' => $dbFile); $option = $this->filterDatabase($pdo, $dbType, $data, $dbList); }else{ $data = $this->filterMysqlData(); $option = $this->filterDatabase($pdo, $dbType, $data, $dbList); $option = array_merge($option, $data); } $option = array_merge($option, $this->dbExtend($database)); $option = array_change_key_case($option, CASE_UPPER); // 数据库配置存缓存,用于清除获取 $key = 'db_change.new_config.' . date('Y-m-d'); Cache::set($key, array('type' => $dbType, 'db' => $option), 3600*24); // 2. 复制数据库 $this->dbChangeAct($database, $option, $dbType); // 3.保存配置 $taskSet = new Task('db.setting_user.set', $dbType, 1, LNG('admin.setting.dbSetSave')); $this->settingSave($dbType, $option, 'change'); $taskSet->update(1); $this->taskToCache($taskSet); show_json(LNG('explorer.success')); } // 任务进度入缓存 private function taskToCache($task, $id = ''){ $total = isset($task->task['taskTotal']) ? $task->task['taskTotal'] : $task->task['taskFinished']; $cache = array( 'currentTitle' => $task->task['currentTitle'], 'taskTotal' => $total, 'taskFinished' => $task->task['taskFinished'], ); if($cache['taskFinished'] > 0 && $cache['taskTotal'] == $cache['taskFinished']) { $cache['success'] = 1; } // 某些环境下进度请求获取不到缓存,加上过期时间后正常,原因未知——应该是时间过短,被即刻删除了 $key = !empty($task->task['id']) ? $task->task['id'] : $id; Cache::set('task_'.$key, $cache, 3600*24); $task->end(); } /** * 复制数据库:当前到新增 * @param [type] $database * @param [type] $option * @param [type] $type 新增db类型 * @return void */ public function dbChangeAct($database, $option, $type){ // 1.初始化db $manageOld = new DbManage($database); $manageNew = new DbManage($option); $dbNew = $manageNew->db(true); // 2.指定库存在数据表,提示重新指定;不存在则继续 $tableNew = $dbNew->getTables(); if(!empty($tableNew)) { show_json(LNG('admin.setting.recDbExist'), false); } if(Input::get('check', null, false)) { show_json(LNG('admin.setting.checkPassed')); } // 截断http请求,后面的操作继续执行 echo json_encode(array('code'=>true,'data'=>'OK', 'info'=>1)); http_close(); $taskId = 'db.new.table.create'; $taskCrt = new Task($taskId, $type, 0, LNG('admin.setting.dbCreate')); // 3.表结构写入目标库 $file = $manageOld->getSqlFile($type); $manageNew->createTable($file, $taskCrt); $this->taskToCache($taskCrt, $taskId); $tableNew = $dbNew->getTables(); del_dir(get_path_father($file)); // 4.获取当前表数据,写入sql文件 $pathLoc = $this->tmpActPath('change'); del_dir($pathLoc); mk_dir($pathLoc); $fileList = array(); $tableOld = $manageOld->db()->getTables(); $tableOld = array_diff($tableOld, array('______', 'sqlite_sequence')); // 排除sqlite系统表 $total = 0; foreach($tableOld as $table) { if(!in_array($table, $tableNew)) continue; $total += $manageOld->model($table)->count(); } $taskId = 'db.old.table.select'; $taskGet = new Task('db.old.table.select', $type, $total, LNG('admin.setting.dbSelect')); foreach($tableOld as $table) { // 对比原始库,当前库如有新增表(不存在的表),直接跳过 if(!in_array($table, $tableNew)) continue; $file = $pathLoc . $table . '.sql'; $manageOld->sqlFromDb($table, $file, $taskGet); $fileList[] = $file; } // 这里的task缺失id等参数,导致cache无法保存,原因未知 $this->taskToCache($taskGet, $taskId); $taskId = 'db.new.table.insert'; $taskAdd = new Task($taskId, $type, 0, LNG('admin.setting.dbInsert')); // 5.读取sql文件,写入目标库 $manageNew->insertTable($fileList, $taskAdd); $this->taskToCache($taskAdd, $taskId); // 6.删除临时sql文件 del_dir($pathLoc); } /** * 数据库恢复 * @return void */ public function recoverySave(){ // TODO 待优化问题: // 备份文件先下载至临时目录,如果本就在本地,则没有必要;中途失败,显示提示到弹窗下;中途失败不能继续(包括切换) $this->taskGet('recovery'); // 获取任务状态 $this->taskClear('recovery'); // 清除失败的数据 $data = Input::getArray(array( 'recType' => array('check' => 'in', 'param' => array('sqlite', 'mysql'), 'aliasKey' => 'type'), 'recPath' => array('check' => 'require', 'aliasKey' => 'path'), )); if(!$info = IO::info($data['path'])){ show_json(LNG('admin.setting.recPathErr'), false); } // 1.判断选择的路径是否有效 $type = $data['type']; $path = $info['path']; if($info['type'] != 'folder') { show_json(LNG('admin.setting.recSysPathErr'), false); } // 1.1 结构文件是否存在 if(!IO::fileNameExist($path, $type.'.sql')) { show_json(LNG('admin.setting.recSysTbErr'), false); } // 1.2 数据表文件是否完整 $list = IO::listPath($path, true); $tableNew = array(); foreach($list['fileList'] as $value) { $tableNew[] = basename($value['name'], '.sql'); } $tableOld = Model()->db()->getTables(); $tableOld = array_diff($tableOld, array('______', 'sqlite_sequence')); $diff = array_diff($tableOld, $tableNew); // 当前表vs备份表,当前有新增表时会失败 if(!empty($diff)) { $cnt = count($diff); $msg = str_replace('[0]',$cnt, LNG('admin.setting.recDbFileErr')); if ($cnt > 5) $diff = array_slice($diff, 0, 5); $msg .= '
'.implode(',',$diff).($cnt > 5 ? '...' : ''); show_json($msg, false); } // 检测结果直接返回 if(Input::get('check', null, false)) { if ($type == 'mysql') { // 如果没有权限,这里会直接报错 $dbname = 'kod_rebuild_test'; $res = Model()->db()->execute("create database `{$dbname}`"); if ($res) { Model()->db()->execute("drop database if exists `{$dbname}`"); } } show_json(LNG('admin.setting.checkPassed')); } echo json_encode(array('code'=>true,'data'=>'OK', 'info'=>1)); http_close(); // 2.导入数据库 ActionCall('user.index.maintenance', true, 1); // 2.1 下载备份文件到本地临时目录 $pathLoc = $this->tmpActPath('recovery'); $path = $this->recLocPath($type, $path, $pathLoc); $list = IO::listPath($path, true); $fileList = array_to_keyvalue($list['fileList'], 'name', 'path'); $file = $fileList[$type . '.sql']; // sqlite.sql、mysql.sql if(!$file) { ActionCall('user.index.maintenance', true, 0); show_json(LNG('admin.setting.dbFileDownErr'), false); } // 2.2 新建数据库 $database = $this->recDatabase($data); $manage = new DbManage($database); $manage->db(true); // 新建数据库 // 2.3 新建数据表 $taskId = 'recovery.db.table.create'; $taskCrt = new Task($taskId, $type, 0, LNG('admin.setting.dbCreate')); $manage->createTable($file, $taskCrt); $this->taskToCache($taskCrt, $taskId); // 2.4 读取sql文件,写入目标库 $taskId = 'recovery.db.table.insert'; $taskAdd = new Task($taskId, $type, 0, LNG('admin.setting.dbInsert')); $manage->insertTable($fileList, $taskAdd); $this->taskToCache($taskAdd, $taskId); // 2.5 删除临时sql文件 del_dir($pathLoc); $database = array_change_key_case($database, CASE_UPPER); // 3.保存配置 $taskSet = new Task('recovery.db.setting_user.set', $type, 1, LNG('admin.setting.dbSetSave')); $this->settingSave($type, $database, 'recovery'); $taskSet->update(1); $this->taskToCache($taskSet); ActionCall('user.index.maintenance', true, 0); // $this->in['clear'] = 1; // $this->in['success'] = 1; // $this->taskClear('recovery'); show_json(LNG('explorer.success')); } // sql文件下载到本地临时目录 private function recLocPath($type, $path, $pathLoc){ del_dir($pathLoc); mk_dir($pathLoc); $task = new TaskFileTransfer('recovery.db.file.download', $type, 0, LNG('admin.setting.dbFileDown')); $task->addPath($path); $path = IO::copy($path, $pathLoc); $this->taskToCache($task); return $path; } // 数据恢复使用的db配置信息 private function recDatabase($data, $name = '') { $type = $data['type']; $database = $GLOBALS['config']['database']; $database = array_change_key_case($database); if($type == 'sqlite') { if(!$name) { $name = USER_SYSTEM . rand_string(12) . '.php'; if(!@touch($name)) { ActionCall('user.index.maintenance', true, 0); show_json(LNG('admin.setting.dbCreateError'), false); } } }else{ $name = $database['db_name'] . '_' . date('Ymd') . '_rebuild'; $name = substr($name, 0, 64); // 长度限制64 } $database['db_name'] = $name; if($database['db_type'] == 'pdo') { if($type == 'mysql') { $dsn = explode(';', $database['db_dsn']); $dsn[count($dsn) - 1] = 'dbname=' . $name; $dsn = implode(';', $dsn); }else{ $dsn = $type . ':' . $name; } $database['db_dsn'] = $dsn; } $key = 'db_recovery.new_config.' . date('Y-m-d'); Cache::set($key, array('type' => $type, 'db' => $database), 3600*24); return $database; } // 临时目录 private function tmpActPath($type){ return TEMP_FILES . 'db_' . $type . '_' . date('Ymd') . '/'; } // 获取(切换、恢复)任务名称 private function actTask($type, $step = '') { $task = array( 'change' => array( 'step1' => 'db.new.table.create', 'step2' => 'db.old.table.select', 'step3' => 'db.new.table.insert', // 'step4' => 'db.temp_dir.del', 'step4' => 'db.setting_user.set', ), 'recovery' => array( 'step1' => 'recovery.db.file.download', 'step2' => 'recovery.db.table.create', 'step3' => 'recovery.db.table.insert', 'step4' => 'recovery.db.setting_user.set', ) ); return $step ? $task[$type][$step] : $task[$type]; } // 进行中(切换、恢复)任务进度获取 private function taskGet($type){ if(!Input::get('task', null, 0)) return; $task = $this->actTask($type); $data = array(); foreach($task as $k => $val) { $value = Cache::get('task_'.$val); if(!$value) $value = Task::get($val); // if(isset($value['status']) && $value['status'] == 'kill') $value = false; $data[$k] = $value; } show_json($data); } // 结束后(切换、恢复)任务、及其他清除 private function taskClear($type){ if(!Input::get('clear', null, 0)) return; if(Input::get('success', null, false)) { echo json_encode(array('code'=>true,'data'=>LNG('explorer.success'))); http_close(); Action('admin.setting')->clearCache();exit; } // 1.杀掉任务、清除缓存 $task = $this->actTask($type); foreach($task as $key) { Task::kill($key); Cache::remove('task_'.$key); } // 2.删除临时sql目录 del_dir($this->tmpActPath($type)); // 3.删除导入失败的数据库 $this->dropErrorDb($type); show_json(LNG('explorer.success')); } // 删除导入失败的数据表 private function dropErrorDb($type){ $key = 'db_'.$type.'.new_config.'.date('Y-m-d'); if(!$cache = Cache::get($key) || empty($cache['db'])) return; $type = $cache['type']; if($type == 'sqlite') { del_file($cache['db']['db_name']); }else if ($type == 'mysql') { $manage = new DbManage($cache['db']); // if($manage) $manage->dropTable(); if($manage) { $dbname = $cache['db']['db_name']; model()->db()->execute("drop database if exists `{$dbname}`"); } } Cache::remove($key); } }