Upgrade.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\shop\controller;
  11. use app\model\system\Database;
  12. use app\model\system\H5;
  13. use app\model\system\Menu;
  14. use app\model\system\Upgrade as UpgradeModel;
  15. use think\facade\Cache;
  16. use think\facade\Db;
  17. use app\model\system\Addon;
  18. use app\model\web\Config;
  19. use extend\FileManage;
  20. /**
  21. * 系统升级
  22. * @author Administrator
  23. * 版本 1.0.1
  24. */
  25. class Upgrade extends BaseShop
  26. {
  27. /**
  28. * 系统授权信息
  29. */
  30. public function auth()
  31. {
  32. if (request()->isAjax()) {
  33. $code = input('code', '');
  34. $upgrade_model = new UpgradeModel($code);
  35. $res = $upgrade_model->authInfo();
  36. if ($res[ 'code' ] == 0) {
  37. $config = new Config();
  38. $config->setAuth([ 'code' => $code ]);
  39. }
  40. return is_null($res) ? error() : $res;
  41. }
  42. //系统信息 获取自配置文件
  43. $app_info = config('info');
  44. $this->assign('app_info', $app_info);
  45. //授权文件 获取自接口
  46. $upgrade_model = new UpgradeModel();
  47. $auth_info = $upgrade_model->authInfo();
  48. $this->assign('auth_info', $auth_info);
  49. return $this->fetch('upgrade/auth');
  50. }
  51. /************************************************系统升级 START*****************************************/
  52. /**
  53. * 获取真实存在的目录 检测权限使用
  54. * @param $path
  55. * @return false|string
  56. */
  57. protected function getRealPath($path)
  58. {
  59. while (!is_dir($path) && strrpos($path, "/")) {
  60. $path = substr($path, 0, strrpos($path, "/"));
  61. }
  62. return $path;
  63. }
  64. /**
  65. * 系统升级
  66. */
  67. public function upgrade()
  68. {
  69. if (request()->isAjax()) {
  70. $upgrade_model = new UpgradeModel();
  71. $res = $upgrade_model->getSystemUpgradeInfo();
  72. if ($res[ 'code' ] != 0) return $res;
  73. $auth_info = $upgrade_model->authInfo();
  74. session('system_upgrade_new_version', $auth_info[ 'data' ][ 'newest_version' ]);
  75. $errors = $this->checkSystemUpgradeRight($res[ 'data' ]);
  76. session('system_upgrade_info_ready', $res[ 'data' ]);
  77. return success(0, '操作成功', [
  78. 'system_upgrade_info_ready' => $res[ 'data' ],
  79. 'right_check' => $errors,
  80. ]);
  81. } else {
  82. return $this->fetch('upgrade/upgrade');
  83. }
  84. }
  85. /**
  86. * 检测系统升级权限
  87. */
  88. protected function checkSystemUpgradeRight($system_upgrade_info_ready)
  89. {
  90. $errors = [];
  91. //检测下载文件目录权限
  92. $download_root = "upload/upgrade";
  93. $download_root = $this->getRealPath($download_root);
  94. if (!is_writeable($download_root)) {
  95. $errors[] = [
  96. 'path' => $download_root,
  97. 'type' => 'dir',
  98. 'type_name' => '文件夹',
  99. ];
  100. }
  101. //检测备份文件目录权限
  102. $backup_root = "upload/backup";
  103. $backup_root = $this->getRealPath($backup_root);
  104. if (!is_writeable($backup_root)) {
  105. $errors[] = [
  106. 'path' => $backup_root,
  107. 'type' => 'dir',
  108. 'type_name' => '文件夹',
  109. ];
  110. }
  111. //检测证书文件权限
  112. $cert_key_path = "./cert.key";
  113. if (!is_writeable($cert_key_path)) {
  114. $errors[] = [
  115. 'path' => $cert_key_path,
  116. 'type' => 'file',
  117. 'type_name' => '文件',
  118. ];
  119. }
  120. foreach ($system_upgrade_info_ready as $info) {
  121. //判断文件夹是否可写
  122. if ($info[ 'type' ] == 'addon' && $info[ 'action' ] == 'install') {
  123. $addon_path = "addon";
  124. if (!is_writeable($addon_path)) {
  125. $errors[] = [
  126. 'path' => $addon_path,
  127. 'type' => 'dir',
  128. 'type_name' => '文件夹',
  129. ];
  130. }
  131. }
  132. //遍历文件 检测权限
  133. if (is_array($info[ 'files' ])) {
  134. foreach ($info[ 'files' ] as $val) {
  135. $file_path = '';
  136. if ($info[ 'action' ] == 'upgrade') {
  137. if ($info[ 'type' ] == 'system') {
  138. $file_path = $val[ 'file_path' ];
  139. } else {
  140. $file_path = "addon/{$val['file_path']}";
  141. }
  142. }
  143. if ($info[ 'action' ] == 'download' && $info[ 'type' ] == 'client') {
  144. $file_path = "public/{$val['file_path']}";
  145. }
  146. if ($file_path) {
  147. if (file_exists($file_path)) {
  148. if (!is_writeable($file_path)) {
  149. $errors[] = [
  150. 'path' => $file_path,
  151. 'type' => 'file',
  152. 'type_name' => '文件',
  153. ];
  154. }
  155. } else {
  156. $dir_path = dirname($file_path);
  157. $dir_path = $this->getRealPath($dir_path);
  158. if (!is_writeable($dir_path)) {
  159. $errors[] = [
  160. 'path' => $dir_path,
  161. 'type' => 'dir',
  162. 'type_name' => '文件夹',
  163. ];
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. return $errors;
  171. }
  172. /**
  173. * 升级操作页面
  174. */
  175. public function upgradeAction()
  176. {
  177. if (request()->isAjax()) {
  178. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  179. $app_info = config('info');
  180. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  181. $name_text = $app_info[ 'version' ] . "_" . $system_upgrade_info_ready[ 0 ][ 'latest_version_name' ];
  182. //将系统和插件的文件及sql都整合到一起
  183. $files = [];
  184. $sqls = '';
  185. // $upgrade_no = uniqid();
  186. //合并文件和sql
  187. foreach ($system_upgrade_info_ready as $info) {
  188. foreach ($info[ 'files' ] as $val) {
  189. $val[ 'type' ] = $info[ 'type' ];
  190. $val[ 'code' ] = $info[ 'code' ];
  191. $files[] = $val;
  192. }
  193. if (isset($info[ 'sqls' ]) && !empty($info[ 'sqls' ])) {
  194. $sqls .= "\n";//防止脚本没有换行导致sql解析完成后将多条sql一起执行,导致出错
  195. $sqls .= $info[ 'sqls' ];
  196. }
  197. }
  198. $system_upgrade_info = [
  199. 'files' => $files,
  200. 'sqls' => $sqls,
  201. 'upgrade_no' => $name_text,
  202. ];
  203. session('system_upgrade_info', $system_upgrade_info);
  204. return success(0, '操作成功', session('system_upgrade_info'));
  205. } else {
  206. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  207. if (empty($system_upgrade_info_ready)) {
  208. $this->error('没有可以升级的内容');
  209. }
  210. return $this->fetch('upgrade/upgrade_action');
  211. }
  212. }
  213. /**
  214. * 升级操作--备份原文件
  215. * @return array
  216. */
  217. public function backupFile()
  218. {
  219. $system_upgrade_info = session('system_upgrade_info');
  220. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  221. //备份文件的根目录
  222. $backup_root = "upload/backup/{$upgrade_no}/file";
  223. if (!is_dir($backup_root)) {
  224. dir_mkdir($backup_root);
  225. }
  226. try {
  227. if (!empty($system_upgrade_info)) {
  228. foreach ($system_upgrade_info[ 'files' ] as $k => $v) {
  229. $type = $v[ 'type' ];
  230. if ($type == 'system') {
  231. //如果是系统升级 备份的文件是和根目录比对 下载文件类似 b2c_saas/index.php 要把前面的b2c_saas去掉
  232. $file_path = $v[ 'file_path' ];
  233. } else {
  234. //如果是插件升级 备份的文件是和插件目录比对 下载文件类似 test/index.php 需要补充前缀addon
  235. $file_path = "addon/{$v['file_path']}";
  236. }
  237. if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $file_path) > 0) {
  238. $file_path = iconv('utf-8', 'gbk', $file_path);
  239. }
  240. if (file_exists($file_path)) {
  241. $dest_file_path = "{$backup_root}/{$file_path}";
  242. $dest_dir_path = substr($dest_file_path, 0, strrpos($dest_file_path, '/'));
  243. //要先创建文件夹才可以执行copy操作
  244. if (!is_dir($dest_dir_path)) {
  245. dir_mkdir($dest_dir_path);
  246. }
  247. copy($file_path, $dest_file_path);
  248. }
  249. }
  250. //备份客户端
  251. $client_type_arr = [ 'h5', 'weapp' ];
  252. foreach ($client_type_arr as $client_type) {
  253. $client_path = "{$backup_root}/public/{$client_type}";
  254. if (!is_dir($client_path)) {
  255. dir_mkdir($client_path);
  256. }
  257. dir_copy("public/{$client_type}", $client_path);
  258. }
  259. }
  260. return success();
  261. } catch (\Exception $e) {
  262. return error(-1, [], $e->getMessage());
  263. }
  264. }
  265. /**
  266. * 升级操作---备份数据库
  267. */
  268. public function backupSql()
  269. {
  270. try {
  271. $system_upgrade_info = session('system_upgrade_info');
  272. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  273. $database = new Database();
  274. ini_set('memory_limit', '500M');
  275. $size = 300;
  276. $volumn = 1024 * 1024 * 2;
  277. $dump = '';
  278. $last_table = input('last_table', '');
  279. $series = max(1, input('series', 1));
  280. if (empty($last_table)) {
  281. $catch = true;
  282. } else {
  283. $catch = false;
  284. }
  285. $back_sql_root = "upload/backup/{$upgrade_no}/sql";
  286. if (!is_dir($back_sql_root)) {
  287. dir_mkdir($back_sql_root);
  288. }
  289. $tables = $database->getDatabaseList();
  290. if (empty($tables)) {
  291. return success();
  292. }
  293. foreach ($tables as $table) {
  294. $table = array_shift($table);
  295. if (!empty($last_table) && $table == $last_table) {
  296. $catch = true;
  297. }
  298. if (!$catch) {
  299. continue;
  300. }
  301. if (!empty($dump)) {
  302. $dump .= "\n\n";
  303. }
  304. $index = 0;
  305. if (!empty(input('index'))) {
  306. $index = input('index');
  307. }
  308. if ($table != $last_table) {
  309. $row = $database->getTableSchemas($table);
  310. $dump .= $row;
  311. $index = 0;
  312. }
  313. //枚举所有表的INSERT语句
  314. while (true) {
  315. $start = $index * $size;
  316. $result = $database->getTableInsertSql($table, $start, $size);
  317. if (!empty($result)) {
  318. $dump .= $result[ 'data' ];
  319. if (strlen($dump) > $volumn) {
  320. $bakfile = "{$back_sql_root}/backup-{$series}.sql";
  321. $dump .= "\n\n";
  322. file_put_contents($bakfile, $dump);
  323. ++$series;
  324. ++$index;
  325. $current = array (
  326. 'is_backup_end' => 0,
  327. 'last_table' => $table,
  328. 'index' => $index,
  329. 'series' => $series,
  330. );
  331. $current_series = $series - 1;
  332. return success(0, '正在导出数据, 请不要关闭浏览器, 当前第 ' . $current_series . ' 卷.', $current);
  333. }
  334. }
  335. if (empty($result) || count($result[ 'result' ]) < $size) {
  336. break;
  337. }
  338. ++$index;
  339. }
  340. }
  341. $back_file = "{$back_sql_root}/backup-{$series}.sql";
  342. $dump .= "\n\n----MySQL Dump End";
  343. file_put_contents($back_file, $dump);
  344. return success(0, '数据库备份完成', [ 'is_backup_end' => 1 ]);
  345. } catch (\Exception $e) {
  346. return error(-1, $e->getMessage());
  347. }
  348. }
  349. /**
  350. * 升级操作---下载文件
  351. */
  352. public function download()
  353. {
  354. ini_set("memory_limit", "-1");
  355. set_time_limit(300);
  356. $action_type = input('action_type', 'upgrade');
  357. $system_upgrade_info = session('system_upgrade_info');
  358. $download_file_index = input('download_file_index', 0);
  359. $file_path = $system_upgrade_info[ 'files' ][ $download_file_index ][ 'file_path' ];
  360. $token = $system_upgrade_info[ 'files' ][ $download_file_index ][ 'token' ];
  361. $type = $system_upgrade_info[ 'files' ][ $download_file_index ][ 'type' ];
  362. $code = $system_upgrade_info[ 'files' ][ $download_file_index ][ 'code' ];
  363. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  364. $app_info = config('info');
  365. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  366. if ($type == 'system') {
  367. $download_root = "upload/upgrade/{$upgrade_no}";//框架
  368. } else if ($type == 'client') {
  369. $download_root = "upload/upgrade/{$upgrade_no}";//客户端
  370. } else if ($type == 'addon') {
  371. $download_root = "upload/upgrade/{$upgrade_no}/addon";//插件
  372. }
  373. try {
  374. $up_model = new UpgradeModel();
  375. $data = array (
  376. 'file' => $file_path,
  377. "token" => $token
  378. );
  379. $info = $up_model->download($data);//异步下载更新文件
  380. //下载文件失败
  381. if ($info[ "code" ] < 0) {
  382. return json($info);
  383. }
  384. $dir_path = dirname($file_path);
  385. $dir_make = dir_mkdir($download_root . '/' . $dir_path);
  386. if ($dir_make) {
  387. if ($action_type == 'download' && $download_file_index == 0 && !empty($system_upgrade_info[ 'sqls' ])) {
  388. $sqls = str_replace("{{prefix}}", config("database.connections.mysql.prefix"), $system_upgrade_info[ 'sqls' ]);
  389. file_put_contents("upload/upgrade/{$upgrade_no}/upgrade.sql", $sqls);
  390. }
  391. if (!empty($info)) {
  392. $temp_path = $download_root . '/' . $file_path;
  393. if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $temp_path) > 0) {
  394. $temp_path = iconv('utf-8', 'gbk', $temp_path);
  395. }
  396. file_put_contents($temp_path, base64_decode($info[ 'data' ]));
  397. return json([
  398. 'code' => 0,
  399. 'message' => $file_path,
  400. 'download_root' => "upload/upgrade/{$upgrade_no}/",
  401. 'current' => $app_info[ 'version' ],
  402. 'upgrade' => $system_upgrade_info_ready[ 0 ][ 'latest_version_name' ],
  403. 'newVersion' => session('system_upgrade_new_version')
  404. ]);
  405. } else {
  406. return json([ 'code' => -1, 'message' => '升级文件不存在' ]);
  407. }
  408. } else {
  409. return json([ 'code' => -1, 'message' => '文件读写权限不足' ]);
  410. }
  411. } catch (\Exception $e) {
  412. return json([ 'code' => -1, 'message' => $e->getMessage() ]);
  413. }
  414. }
  415. /**
  416. * 升级操作---更新文件覆盖
  417. */
  418. public function executeFile()
  419. {
  420. $system_upgrade_info = session('system_upgrade_info');
  421. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  422. try {
  423. //下载目录和要覆盖的目录
  424. $download_root = "upload/upgrade/{$upgrade_no}";
  425. // 先解压客户端文件
  426. $client_type_arr = [ 'h5', 'weapp' ];
  427. $file_manage = new FileManage();
  428. foreach ($client_type_arr as $client_type) {
  429. $client_path = $download_root . '/' . $client_type . '.zip';
  430. if (file_exists($client_path)) {
  431. $to_path = "public/{$client_type}/";
  432. if (!is_dir($to_path)) {
  433. dir_mkdir($to_path);
  434. } else {
  435. deleteDir($to_path);
  436. }
  437. $file_manage->unzip($client_path, $to_path);
  438. unlink($client_path);
  439. }
  440. }
  441. $to_path = './';
  442. //文件替换
  443. dir_copy($download_root, $to_path, [ "download.lock" ]);
  444. return json([ 'code' => 0, 'message' => '操作成功' ]);
  445. } catch (\Exception $e) {
  446. //升级失败
  447. $upgrade_model = new UpgradeModel();
  448. $upgrade_model->editUpgradeLog([ 'status' => 2, 'error_message' => $e->getMessage() ], [ 'upgrade_no' => $upgrade_no ]);
  449. return json([ 'code' => -1, 'message' => $e->getMessage() ]);
  450. }
  451. }
  452. /**
  453. * 更新操作---sql执行
  454. */
  455. public function executeSql()
  456. {
  457. $system_upgrade_info = session('system_upgrade_info');
  458. $sqls = $system_upgrade_info[ 'sqls' ];
  459. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  460. try {
  461. if (!empty($sqls)) {
  462. $sqls = str_replace("{{prefix}}", config("database.connections.mysql.prefix"), $sqls);
  463. file_put_contents("upload/upgrade/{$upgrade_no}/upgrade.sql", $sqls);
  464. //执行sql
  465. $sql_arr = parse_sql($sqls);
  466. foreach ($sql_arr as $k => $v) {
  467. $v = trim($v);
  468. if (!empty($v) && $v != "") {
  469. Db::execute($v);
  470. }
  471. }
  472. return json(success());
  473. } else {
  474. return json(success());
  475. }
  476. } catch (\Exception $e) {
  477. //升级失败
  478. $upgrade_model = new UpgradeModel();
  479. $upgrade_model->editUpgradeLog([ 'status' => 2, 'error_message' => $e->getMessage() ], [ 'upgrade_no' => $upgrade_no ]);
  480. return json(error(-1, $e->getMessage()));
  481. }
  482. }
  483. /**
  484. * 升级开始
  485. * @return array
  486. */
  487. public function upgradeStart()
  488. {
  489. // 升级前先清除表结构缓存
  490. if (is_dir('runtime/schema')) {
  491. rmdirs("schema");
  492. }
  493. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  494. $system_upgrade_info = session('system_upgrade_info');
  495. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  496. // 添加升级日志
  497. $version_info = [];
  498. foreach ($system_upgrade_info_ready as $key => $val) {
  499. $version_info[] = [
  500. 'action' => $val[ 'action' ],
  501. 'action_name' => $val[ 'action_name' ],
  502. 'type' => $val[ 'type' ],
  503. 'type_name' => $val[ 'type_name' ],
  504. 'current_version_name' => $val[ 'current_version_name' ],
  505. 'latest_version_name' => $val[ 'latest_version_name' ],
  506. 'scripts' => $val[ 'scripts' ],
  507. 'goods_name' => $val[ 'goods_name' ],
  508. ];
  509. }
  510. $data = [
  511. 'upgrade_no' => $upgrade_no,
  512. 'upgrade_time' => time(),
  513. 'backup_root' => "upload/backup/{$upgrade_no}",
  514. 'download_root' => "upload/download_root/{$upgrade_no}",
  515. 'version_info' => json_encode($version_info),
  516. 'status' => 0
  517. ];
  518. $upgrade_model = new UpgradeModel();
  519. $res = $upgrade_model->addUpgradeLog($data);
  520. return $res;
  521. }
  522. /**
  523. * 升级完成
  524. */
  525. public function upgradeEnd()
  526. {
  527. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  528. $system_upgrade_info = session('system_upgrade_info');
  529. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  530. $upgrade_model = new UpgradeModel();
  531. try {
  532. $menu = new Menu();
  533. // 清空表,防止自增ID越来越大
  534. $menu->truncateMenu();
  535. $menu->truncateDiyView();
  536. //更新系统菜单
  537. $menu->refreshMenu('shop', '');
  538. //修改插件信息
  539. $addon_model = new Addon();
  540. $addon_model->refreshDiyView('');
  541. //刷新插件菜单
  542. $addon_list = $addon_model->getAddonList([], 'name');
  543. $addon_list = $addon_list[ 'data' ];
  544. foreach ($addon_list as $k => $v) {
  545. $menu->refreshMenu('shop', $v[ 'name' ]);
  546. }
  547. foreach ($system_upgrade_info_ready as $key => $val) {
  548. if ($val[ 'type' ] == 'addon') {
  549. if ($val[ 'action' ] == 'upgrade') {
  550. $addon_model->uninstall($val[ 'code' ]);
  551. $addon_model->install($val[ 'code' ]);
  552. } else {
  553. $addon_model->install($val[ 'code' ]);
  554. }
  555. }
  556. }
  557. //升级成功
  558. $upgrade_model->editUpgradeLog([ 'status' => 1 ], [ 'upgrade_no' => $upgrade_no ]);
  559. //刷新h5
  560. $h5 = new H5();
  561. $h5->refresh();
  562. // 处理升级版本数据遇到的数据问题
  563. $system = new System();
  564. $system->handleVersionData();
  565. //清空session数据
  566. session('system_upgrade_info_ready', null);
  567. session('system_upgrade_info', null);
  568. return json(success());
  569. } catch (\Exception $e) {
  570. //升级失败
  571. $upgrade_model->editUpgradeLog([ 'status' => 2, 'error_message' => $e->getMessage() ], [ 'upgrade_no' => $upgrade_no ]);
  572. return json(error(-1, $e->getMessage()));
  573. }
  574. }
  575. /**
  576. * 执行恢复
  577. * @return \think\response\Json
  578. */
  579. public function executeRecovery()
  580. {
  581. $system_upgrade_info_ready = session('system_upgrade_info_ready');
  582. $system_upgrade_info = session('system_upgrade_info');
  583. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  584. try {
  585. $upgrade_model = new UpgradeModel();
  586. $log_info = $upgrade_model->getUpgradeLogInfo([ 'upgrade_no' => $upgrade_no ]);
  587. if (empty($log_info)) {
  588. return json([ 'code' => -1, '回滚信息有误' ]);
  589. }
  590. $backup_file_path = "{$log_info['backup_root']}/file/";
  591. $backup_sql_path = "{$log_info['backup_root']}/sql/";
  592. //回滚备份的文件
  593. if (dir_is_empty($backup_file_path)) {
  594. return json([ 'code' => -1, '没有可回滚的备份文件!' ]);
  595. }
  596. dir_copy($backup_file_path, './');
  597. //回滚执行的sql语句
  598. $flag = \FilesystemIterator::KEY_AS_FILENAME;
  599. $glob = new \FilesystemIterator($backup_sql_path, $flag);
  600. foreach ($glob as $name => $sql) {
  601. $sql_path = $backup_sql_path . '/' . $name;
  602. $sql = file_get_contents($sql_path);
  603. //执行sql
  604. $sql_arr = parse_sql($sql);
  605. foreach ($sql_arr as $k => $v) {
  606. $v = trim($v);
  607. if (!empty($v) && $v != "") {
  608. Db::execute($v);
  609. }
  610. }
  611. }
  612. //删除已安装的插件
  613. foreach ($system_upgrade_info_ready as $val) {
  614. if ($val[ 'action' ] == 'install' && $val[ 'type' ] == 'addon') {
  615. $addon_dir_path = "addon/{$val['code']}";
  616. if (is_dir($addon_dir_path)) {
  617. deleteDir($addon_dir_path);
  618. @rmdir($addon_dir_path);
  619. }
  620. }
  621. }
  622. return json([ 'code' => 0, 'message' => '备份回滚成功!' ]);
  623. } catch (\Exception $e) {
  624. return json([ 'code' => -1, 'message' => $e->getMessage() ]);
  625. }
  626. }
  627. /************************************************系统升级 END*****************************************/
  628. /************************************************系统回滚 START*****************************************/
  629. /**
  630. * 系统回滚
  631. */
  632. public function recovery()
  633. {
  634. $upgrade_model = new UpgradeModel();
  635. $upgrade_log_list = $upgrade_model->getUpgradeLogList([ 'status' => 1 ], '*', 'upgrade_time desc', '1');
  636. if (!empty($upgrade_log_list[ 'data' ])) {
  637. $upgrade_log_info = $upgrade_log_list[ 'data' ][ 0 ];
  638. $upgrade_log_info[ 'version_info' ] = json_decode($upgrade_log_info[ 'version_info' ], true);
  639. } else {
  640. $upgrade_log_info = null;
  641. }
  642. if (request()->isAjax()) {
  643. try {
  644. $log_info = $upgrade_log_info;
  645. if (empty($log_info)) {
  646. return json([ 'code' => -1, '回滚信息有误' ]);
  647. }
  648. $backup_file_path = "{$log_info['backup_root']}/file/";
  649. $backup_sql_path = "{$log_info['backup_root']}/sql/";
  650. //回滚备份的文件
  651. if (dir_is_empty($backup_file_path)) {
  652. return json([ 'code' => -1, '没有可回滚的备份文件!' ]);
  653. }
  654. dir_copy($backup_file_path, './');
  655. //回滚执行的sql语句
  656. $flag = \FilesystemIterator::KEY_AS_FILENAME;
  657. $glob = new \FilesystemIterator($backup_sql_path, $flag);
  658. foreach ($glob as $name => $sql) {
  659. $sql_path = $backup_sql_path . '/' . $name;
  660. $sql = file_get_contents($sql_path);
  661. //执行sql
  662. $sql_arr = parse_sql($sql);
  663. foreach ($sql_arr as $k => $v) {
  664. $v = trim($v);
  665. if (!empty($v) && $v != "") {
  666. Db::execute($v);
  667. }
  668. }
  669. }
  670. return json([ 'code' => 0, 'message' => '备份回滚成功!' ]);
  671. } catch (\Exception $e) {
  672. return json([ 'code' => -1, 'message' => $e->getMessage() ]);
  673. }
  674. } else {
  675. $this->assign('upgrade_log_info', $upgrade_log_info);
  676. return $this->fetch('upgrade/recovery');
  677. }
  678. }
  679. /************************************************系统回滚 END*****************************************/
  680. /************************************************ 更新日志 START*****************************************/
  681. public function versionLog()
  682. {
  683. if (request()->isAjax()) {
  684. $upgrade_model = new UpgradeModel();
  685. $info = $upgrade_model->getUpdateLog();
  686. return $info;
  687. } else {
  688. return $this->fetch('upgrade/version_log');
  689. }
  690. }
  691. /************************************************ 更新日志 END*****************************************/
  692. /**
  693. * 版本恢复
  694. */
  695. public function versionRecovery()
  696. {
  697. try {
  698. //回滚备份的文件
  699. if (dir_is_empty('upload/backup/')) {
  700. return json([ 'code' => -1, '没有可回滚的备份!' ]);
  701. }
  702. dir_copy('upload/backup/release', './');
  703. //回滚执行的sql语句
  704. $path = "upload/backup/sql";
  705. $flag = \FilesystemIterator::KEY_AS_FILENAME;
  706. $glob = new \FilesystemIterator($path, $flag);
  707. foreach ($glob as $name => $sql) {
  708. $sql_path = $path . '/' . $name;
  709. $sql = file_get_contents($sql_path);
  710. Db::execute($sql);
  711. }
  712. return json([ 'code' => 0, 'message' => '备份回滚成功!' ]);
  713. } catch (\Exception $e) {
  714. return json([ 'code' => -1, 'message' => $e->getMessage() ]);
  715. }
  716. }
  717. /**
  718. * 清理缓存、刷新菜单、自定义组件
  719. * @return array
  720. */
  721. public function refresh()
  722. {
  723. if (request()->isAjax()) {
  724. try {
  725. Cache::clear();
  726. if (is_dir('runtime/schema')) {
  727. rmdirs("schema");
  728. }
  729. if (is_dir('runtime/temp')) {
  730. rmdirs("temp");
  731. }
  732. $menu = new Menu();
  733. // 清空表,防止自增ID越来越大
  734. $menu->truncateMenu();
  735. $menu->truncateDiyView();
  736. $menu->refreshMenu('shop', '');
  737. if (addon_is_exit('store', $this->site_id) == 1) {
  738. $menu->refreshMenu('store', 'store');
  739. };
  740. $addon_model = new Addon();
  741. $addon_model->installAllAddon();
  742. //刷新插件菜单
  743. $addon_list = $addon_model->getAddonList([], 'name')[ 'data' ];
  744. foreach ($addon_list as $k => $v) {
  745. $menu->refreshMenu('shop', $v[ 'name' ]);
  746. $addon_model->refreshDiyView($v[ 'name' ]);
  747. }
  748. return success('', '刷新成功', '');
  749. } catch (\Exception $e) {
  750. return error('', 'File:' . $e->getFile() . ',Line:' . $e->getLine() . ',message:' . $e->getMessage());
  751. }
  752. }
  753. }
  754. public function downComplete()
  755. {
  756. $system_upgrade_info = session('system_upgrade_info');
  757. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  758. $download_root = "upload/upgrade/{$upgrade_no}";
  759. file_put_contents($download_root . "/download.lock", "");
  760. }
  761. public function verificationDown()
  762. {
  763. $system_upgrade_info = session('system_upgrade_info');
  764. $upgrade_no = $system_upgrade_info[ 'upgrade_no' ];
  765. $download_root = "upload/upgrade/{$upgrade_no}";
  766. if (file_exists($download_root . "/download.lock")) {
  767. return true;
  768. }
  769. return false;
  770. }
  771. }