ToolsController.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. <?php
  2. namespace Admin\Controller;
  3. class ToolsController extends AdminController
  4. {
  5. protected function _initialize(){
  6. parent::_initialize();
  7. $allow_action=array("index","cache","delcahe","getDirSize","queue","delcache","invoke","rmdirr","excel","export","import");
  8. if(!in_array(ACTION_NAME,$allow_action)){
  9. $this->error("页面不存在!");
  10. }
  11. }
  12. public function cache()
  13. {
  14. $size = $this->getDirSize('./Runtime/');
  15. $this->assign('cacheSize', round($size / pow(1024, $i = floor(log($size, 1024))), 2));
  16. $this->display();
  17. }
  18. public function delcahe()
  19. {
  20. $size = $this->getDirSize('./Runtime/');
  21. $this->assign('cacheSize', round($size / pow(1024, $i = floor(log($size, 1024))), 2));
  22. $this->display();
  23. }
  24. protected function getDirSize($dir)
  25. {
  26. $sizeResult = '';
  27. $handle = opendir($dir);
  28. while (false !== $FolderOrFile = readdir($handle)) {
  29. if (($FolderOrFile != '.') && ($FolderOrFile != '..')) {
  30. if (is_dir($dir . '/' . $FolderOrFile)) {
  31. $sizeResult += $this->getDirSize($dir . '/' . $FolderOrFile);
  32. }
  33. else {
  34. $sizeResult += filesize($dir . '/' . $FolderOrFile);
  35. }
  36. }
  37. }
  38. closedir($handle);
  39. return $sizeResult;
  40. }
  41. public function delcache()
  42. {
  43. if (APP_DEMO) {
  44. $this->error('测试站暂时不能修改!');
  45. }
  46. $dirs = array('./Runtime/');
  47. @(mkdir('Runtime', 511, true));
  48. foreach ($dirs as $value) {
  49. $this->rmdirr($value);
  50. }
  51. @(mkdir('Runtime', 511, true));
  52. $this->success('系统缓存清除成功!');
  53. }
  54. public function invoke()
  55. {
  56. $dirs = array('./Runtime/');
  57. @(mkdir('Runtime', 511, true));
  58. foreach ($dirs as $value) {
  59. $this->rmdirr($value);
  60. }
  61. @(mkdir('Runtime', 511, true));
  62. }
  63. protected function rmdirr($dirname)
  64. {
  65. if (!file_exists($dirname)) {
  66. return false;
  67. }
  68. if (is_file($dirname) || is_link($dirname)) {
  69. return unlink($dirname);
  70. }
  71. $dir = dir($dirname);
  72. if ($dir) {
  73. while (false !== $entry = $dir->read()) {
  74. if (($entry == '.') || ($entry == '..')) {
  75. continue;
  76. }
  77. $this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
  78. }
  79. }
  80. $dir->close();
  81. return rmdir($dirname);
  82. }
  83. public function dataExport()
  84. {
  85. redirect('/Admin/Tools/database?type=export');
  86. }
  87. public function dataImport()
  88. {
  89. redirect('/Admin/Tools/database?type=import');
  90. }
  91. public function database($type = NULL)
  92. {
  93. switch ($type) {
  94. case 'import':
  95. $path = realpath(DATABASE_PATH);
  96. $glob = self::FilesystemIterator($path);
  97. $list = array();
  98. for($i=0;$i<count($glob);$i++){
  99. $name=$glob[$i];
  100. $a = str_replace(".sql.gz","",$glob[$i]);
  101. $lv=explode("-",$a);
  102. if (preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql(?:\\.gz)?$/', $name)) {
  103. $name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d');
  104. $date = $name[0] . '-' . $name[1] . '-' . $name[2];
  105. $time = $name[3] . ':' . $name[4] . ':' . $name[5];
  106. $part = $name[6];
  107. $list[$i]['time']=strtotime($date." ".$time);
  108. $list[$i]['part']=$lv[2];
  109. $list[$i]['size']=filesize($path."/".$glob[$i])."B";
  110. $list[$i]['key']=$date." ".$time;
  111. }
  112. }
  113. break;
  114. case 'export':
  115. $Db = \Think\Db::getInstance();
  116. $list = $Db->query('SHOW TABLE STATUS');
  117. $list = array_map('array_change_key_case', $list);
  118. $title = '数据备份';
  119. break;
  120. default:
  121. $this->error('参数错误!');
  122. }
  123. $this->assign('meta_title', $title);
  124. $this->assign('list', $list);
  125. $this->display($type);
  126. }
  127. function FilesystemIterator($dir){
  128. exit;
  129. //PHP遍历文件夹下所有文件
  130. $handle=opendir($dir.".");
  131. //定义用于存储文件名的数组
  132. $array_file = array();
  133. while (false !== ($file = readdir($handle))) {
  134. if ($file != "." && $file != "..") {
  135. $array_file[] = $file; //输出文件名
  136. }
  137. }
  138. closedir($handle);
  139. for($i=0;$i<count($array_file);$i++){
  140. if(strstr($array_file[$i],'.sql.gz')){
  141. $date[]=$array_file[$i];
  142. }
  143. }
  144. return $date;
  145. }
  146. public function optimize($tables = NULL)
  147. {
  148. exit;
  149. if ($tables) {
  150. $Db = \Think\Db::getInstance();
  151. if (is_array($tables)) {
  152. $tables = implode('`,`', $tables);
  153. $list = $Db->query('OPTIMIZE TABLE `' . $tables . '`');
  154. if ($list) {
  155. $this->success('数据表优化完成!');
  156. }
  157. else {
  158. $this->error('数据表优化出错请重试!');
  159. }
  160. }
  161. else {
  162. $list = $Db->query('OPTIMIZE TABLE `' . $tables . '`');
  163. if ($list) {
  164. $this->success('数据表\'' . $tables . '\'优化完成!');
  165. }
  166. else {
  167. $this->error('数据表\'' . $tables . '\'优化出错请重试!');
  168. }
  169. }
  170. }
  171. else {
  172. $this->error('请指定要优化的表!');
  173. }
  174. }
  175. public function repair($tables = NULL)
  176. {
  177. exit;
  178. if ($tables) {
  179. $Db = \Think\Db::getInstance();
  180. if (is_array($tables)) {
  181. $tables = implode('`,`', $tables);
  182. $list = $Db->query('REPAIR TABLE `' . $tables . '`');
  183. if ($list) {
  184. $this->success('数据表修复完成!');
  185. }
  186. else {
  187. $this->error('数据表修复出错请重试!');
  188. }
  189. }
  190. else {
  191. $list = $Db->query('REPAIR TABLE `' . $tables . '`');
  192. if ($list) {
  193. $this->success('数据表\'' . $tables . '\'修复完成!');
  194. }
  195. else {
  196. $this->error('数据表\'' . $tables . '\'修复出错请重试!');
  197. }
  198. }
  199. }
  200. else {
  201. $this->error('请指定要修复的表!');
  202. }
  203. }
  204. public function del($time = 0)
  205. {
  206. exit;
  207. if (APP_DEMO) {
  208. $this->error('测试站暂时不能修改!');
  209. }
  210. if ($time) {
  211. $name = date('Ymd-His', $time) . '-*.sql*';
  212. $path = realpath(DATABASE_PATH) . DIRECTORY_SEPARATOR . $name;
  213. array_map('unlink', glob($path));
  214. if (count(glob($path))) {
  215. $this->success('备份文件删除失败,请检查权限!');
  216. }
  217. else {
  218. $this->success('备份文件删除成功!');
  219. }
  220. }
  221. else {
  222. $this->error('参数错误!');
  223. }
  224. }
  225. public function export($tables = NULL, $id = NULL, $start = NULL)
  226. {
  227. if (APP_DEMO) {
  228. $this->error('测试站暂时不能修改!');
  229. }
  230. if (C('web_close')) {
  231. $this->error('请先关闭网站再备份数据库!');
  232. }
  233. if (IS_POST && !empty($tables) && is_array($tables)) {
  234. $config = array('path' => realpath(DATABASE_PATH) . DIRECTORY_SEPARATOR, 'part' => 20971520, 'compress' => 1, 'level' => 9);
  235. $lock = $config['path'] . 'backup.lock';
  236. if (is_file($lock)) {
  237. $this->error('检测到有一个备份任务正在执行,请稍后再试!');
  238. }
  239. else {
  240. file_put_contents($lock, NOW_TIME);
  241. }
  242. is_writeable($config['path']) || $this->error('备份目录不存在或不可写,请检查后重试!');
  243. session('backup_config', $config);
  244. $file = array('name' => date('Ymd-His', NOW_TIME), 'part' => 1);
  245. session('backup_file', $file);
  246. session('backup_tables', $tables);
  247. $Database = new \OT\Database($file, $config);
  248. if (false !== $Database->create()) {
  249. $tab = array('id' => 0, 'start' => 0);
  250. $this->success('初始化成功!', '', array('tables' => $tables, 'tab' => $tab));
  251. }
  252. else {
  253. $this->error('初始化失败,备份文件创建失败!');
  254. }
  255. }
  256. else if (IS_GET && is_numeric($id) && is_numeric($start)) {
  257. $tables = session('backup_tables');
  258. $Database = new \OT\Database(session('backup_file'), session('backup_config'));
  259. $start = $Database->backup($tables[$id], $start);
  260. if (false === $start) {
  261. $this->error('备份出错!');
  262. }
  263. else if (0 === $start) {
  264. if (isset($tables[++$id])) {
  265. $tab = array('id' => $id, 'start' => 0);
  266. $this->success('备份完成!', '', array('tab' => $tab));
  267. }
  268. else {
  269. unlink(session('backup_config.path') . 'backup.lock');
  270. session('backup_tables', null);
  271. session('backup_file', null);
  272. session('backup_config', null);
  273. $this->success('备份完成!');
  274. }
  275. }
  276. else {
  277. $tab = array('id' => $id, 'start' => $start[0]);
  278. $rate = floor(100 * ($start[0] / $start[1]));
  279. $this->success('正在备份...(' . $rate . '%)', '', array('tab' => $tab));
  280. }
  281. }
  282. else {
  283. $this->error('参数错误!');
  284. }
  285. //$this->display();
  286. }
  287. public function import($time = 0, $part = NULL, $start = NULL)
  288. {
  289. if (APP_DEMO) {
  290. $this->error('测试站暂时不能修改!');
  291. }
  292. if (C('web_close')) {
  293. $this->error('请先关闭网站再还原数据库!');
  294. }
  295. if (is_numeric($time) && is_null($part) && is_null($start)) {
  296. $name = date('Ymd-His', $time) . '-*.sql*';
  297. $path = realpath(DATABASE_PATH) . DIRECTORY_SEPARATOR . $name;
  298. $files = glob($path);
  299. $list = array();
  300. foreach ($files as $name) {
  301. $basename = basename($name);
  302. $match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
  303. $gz = preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql.gz$/', $basename);
  304. $list[$match[6]] = array($match[6], $name, $gz);
  305. }
  306. ksort($list);
  307. $last = end($list);
  308. if (count($list) === $last[0]) {
  309. session('backup_list', $list);
  310. $this->success('初始化完成!', '', array('part' => 1, 'start' => 0));
  311. }
  312. else {
  313. $this->error('备份文件可能已经损坏,请检查!');
  314. }
  315. }
  316. else if (is_numeric($part) && is_numeric($start)) {
  317. $list = session('backup_list');
  318. $db = new \OT\Database($list[$part], array('path' => realpath(DATABASE_PATH) . DIRECTORY_SEPARATOR, 'compress' => 1, 'level' => 9));
  319. $start = $db->import($start);
  320. if (false === $start) {
  321. $this->error('还原数据出错!');
  322. }
  323. else if (0 === $start) {
  324. if (isset($list[++$part])) {
  325. $data = array('part' => $part, 'start' => 0);
  326. $this->success('正在还原...#' . $part, '', $data);
  327. }
  328. else {
  329. session('backup_list', null);
  330. $this->success('还原完成!');
  331. }
  332. }
  333. else {
  334. $data = array('part' => $part, 'start' => $start[0]);
  335. if ($start[1]) {
  336. $rate = floor(100 * ($start[0] / $start[1]));
  337. $this->success('正在还原...#' . $part . ' (' . $rate . '%)', '', $data);
  338. }
  339. else {
  340. $data['gz'] = 1;
  341. $this->success('正在还原...#' . $part, '', $data);
  342. }
  343. }
  344. }
  345. else {
  346. $this->error('参数错误!');
  347. }
  348. //$this->display();
  349. }
  350. public function excel($tables = NULL)
  351. {
  352. if ($tables) {
  353. if (APP_DEMO) {
  354. $this->error('测试站暂时不能修改!');
  355. }
  356. $mo = M();
  357. $mo->execute('set autocommit=0');
  358. $mo->execute('lock tables ' . $tables . ' write');
  359. $rs = $mo->table($tables)->select();
  360. $zd = $mo->table($tables)->getDbFields();
  361. if ($rs) {
  362. $mo->execute('commit');
  363. $mo->execute('unlock tables');
  364. }
  365. else {
  366. $mo->execute('rollback');
  367. }
  368. $xlsName = $tables;
  369. $xls = array();
  370. foreach ($zd as $k => $v) {
  371. $xls[$k][0] = $v;
  372. $xls[$k][1] = $v;
  373. }
  374. $this->exportExcel($xlsName, $xls, $rs);
  375. }
  376. else {
  377. $this->error('请指定要导出的表!');
  378. }
  379. }
  380. public function exportExcel($expTitle, $expCellName, $expTableData)
  381. {
  382. import('Org.Util.PHPExcel');
  383. import('Org.Util.PHPExcel.Writer.Excel5');
  384. import('Org.Util.PHPExcel.IOFactory.php');
  385. $xlsTitle = iconv('utf-8', 'gb2312', $expTitle);
  386. $fileName = $_SESSION['loginAccount'] . date('_YmdHis');
  387. $cellNum = count($expCellName);
  388. $dataNum = count($expTableData);
  389. $objPHPExcel = new PHPExcel();
  390. $cellName = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ');
  391. $objPHPExcel->getActiveSheet(0)->mergeCells('A1:' . $cellName[$cellNum - 1] . '1');
  392. $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $expTitle . ' Export time:' . date('Y-m-d H:i:s'));
  393. $i = 0;
  394. for (; $i < $cellNum; $i++) {
  395. $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i] . '2', $expCellName[$i][1]);
  396. }
  397. $i = 0;
  398. for (; $i < $dataNum; $i++) {
  399. $j = 0;
  400. for (; $j < $cellNum; $j++) {
  401. $objPHPExcel->getActiveSheet(0)->setCellValue($cellName[$j] . ($i + 3), $expTableData[$i][$expCellName[$j][0]]);
  402. }
  403. }
  404. ob_end_clean();
  405. header('pragma:public');
  406. header('Content-type:application/vnd.ms-excel;charset=utf-8;name="' . $xlsTitle . '.xls"');
  407. header('Content-Disposition:attachment;filename=' . $fileName . '.xls');
  408. $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  409. $objWriter->save('php://output');
  410. exit();
  411. }
  412. public function importExecl($file)
  413. {
  414. exit;
  415. import('Org.Util.PHPExcel');
  416. import('Org.Util.PHPExcel.Writer.Excel5');
  417. import('Org.Util.PHPExcel.IOFactory.php');
  418. if (!file_exists($file)) {
  419. return array('error' => 0, 'message' => 'file not found!');
  420. }
  421. $objReader = PHPExcel_IOFactory::createReader('Excel5');
  422. try {
  423. $PHPReader = $objReader->load($file);
  424. }
  425. catch (Exception $e) {
  426. }
  427. if (!file_exists($file)) {
  428. return array('error' => 0, 'message' => 'read error!');
  429. }
  430. $allWorksheets = $PHPReader->getAllSheets();
  431. $i = 0;
  432. foreach ($allWorksheets as $objWorksheet) {
  433. $sheetname = $objWorksheet->getTitle();
  434. $allRow = $objWorksheet->getHighestRow();
  435. $highestColumn = $objWorksheet->getHighestColumn();
  436. $allColumn = PHPExcel_Cell::columnIndexFromString($highestColumn);
  437. $array[$i]['Title'] = $sheetname;
  438. $array[$i]['Cols'] = $allColumn;
  439. $array[$i]['Rows'] = $allRow;
  440. $arr = array();
  441. $isMergeCell = array();
  442. foreach ($objWorksheet->getMergeCells() as $cells) {
  443. foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) {
  444. $isMergeCell[$cellReference] = true;
  445. }
  446. }
  447. $currentRow = 1;
  448. for (; $currentRow <= $allRow; $currentRow++) {
  449. $row = array();
  450. $currentColumn = 0;
  451. for (; $currentColumn < $allColumn; $currentColumn++) {
  452. $cell = $objWorksheet->getCellByColumnAndRow($currentColumn, $currentRow);
  453. $afCol = PHPExcel_Cell::stringFromColumnIndex($currentColumn + 1);
  454. $bfCol = PHPExcel_Cell::stringFromColumnIndex($currentColumn - 1);
  455. $col = PHPExcel_Cell::stringFromColumnIndex($currentColumn);
  456. $address = $col . $currentRow;
  457. $value = $objWorksheet->getCell($address)->getValue();
  458. if (substr($value, 0, 1) == '=') {
  459. return array('error' => 0, 'message' => 'can not use the formula!');
  460. exit();
  461. }
  462. if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_NUMERIC) {
  463. $cellstyleformat = $cell->getParent()->getStyle($cell->getCoordinate())->getNumberFormat();
  464. $formatcode = $cellstyleformat->getFormatCode();
  465. if (preg_match('/^([$[A-Z]*-[0-9A-F]*])*[hmsdy]/i', $formatcode)) {
  466. $value = gmdate('Y-m-d', PHPExcel_Shared_Date::ExcelToPHP($value));
  467. }
  468. else {
  469. $value = PHPExcel_Style_NumberFormat::toFormattedString($value, $formatcode);
  470. }
  471. }
  472. if ($isMergeCell[$col . $currentRow] && $isMergeCell[$afCol . $currentRow] && !empty($value)) {
  473. $temp = $value;
  474. }
  475. else if ($isMergeCell[$col . $currentRow] && $isMergeCell[$col . ($currentRow - 1)] && empty($value)) {
  476. $value = $arr[$currentRow - 1][$currentColumn];
  477. }
  478. else if ($isMergeCell[$col . $currentRow] && $isMergeCell[$bfCol . $currentRow] && empty($value)) {
  479. $value = '';
  480. }
  481. $row[$currentColumn] = $value;
  482. }
  483. $arr[$currentRow] = $row;
  484. }
  485. $array[$i]['Content'] = $arr;
  486. $i++;
  487. }
  488. spl_autoload_register(array('Think', 'autoload'));
  489. unset($objWorksheet);
  490. unset($PHPReader);
  491. unset($PHPExcel);
  492. unlink($file);
  493. return array('error' => 1, 'data' => $array);
  494. }
  495. public function xiazai()
  496. {
  497. exit;
  498. if (APP_DEMO) {
  499. $this->error('测试站暂时不能修改!');
  500. }
  501. if (!check($_GET['file'], 'dw', '-.')) {
  502. $this->error('失败!');
  503. }
  504. DownloadFile(DATABASE_PATH . $_GET['file']);
  505. exit();
  506. }
  507. public function queue()
  508. {
  509. $file_path = DATABASE_PATH . '/check_queue.json';
  510. $time = time();
  511. $timeArr = array();
  512. if (file_exists($file_path)) {
  513. $timeArr = file_get_contents($file_path);
  514. $timeArr = json_decode($timeArr, true);
  515. }
  516. $str = '';
  517. foreach ($timeArr as $key => $val) {
  518. if ($key == 0) {
  519. $val = '上一次执行:' . addtime($val);
  520. }
  521. if ($key == 1) {
  522. $val = '上二次执行:' . addtime($val);
  523. }
  524. if ($key == 2) {
  525. $val = '上三次执行:' . addtime($val);
  526. }
  527. $str .= $val . ' ';
  528. }
  529. $status = '';
  530. $count = count($timeArr);
  531. if (3 <= $count) {
  532. $_t1 = $timeArr[2] - $timeArr[1];
  533. $_t2 = $timeArr[1] - $timeArr[0];
  534. if (60 < abs($timeArr[0] - time())) {
  535. $status = '<span class="btn btn-warning">队列停止运行</span>';
  536. }
  537. if ((50 < abs($_t1)) && (50 < abs($_t2))) {
  538. $status = '<span class="btn">队列运行正常</span>';
  539. }
  540. else {
  541. $status = '<span class="btn btn-warning">队列时间异常,请稍后再试</span>';
  542. }
  543. }
  544. else {
  545. $msg = '';
  546. if ($count == 0) {
  547. $msg = '队列还未开始运行,请1分钟后刷新';
  548. }
  549. if ($count == 1) {
  550. $msg = '队列运行一次请再等待2分钟检查';
  551. }
  552. if ($count == 2) {
  553. $msg = '队列运行两次请再等待1分钟检查';
  554. }
  555. $status = '<span class="btn btn-warning">' . $msg . '</span>';
  556. }
  557. $this->assign('status', $status);
  558. $this->assign('str', $str);
  559. $this->display();
  560. return NULL;
  561. }
  562. }
  563. ?>