VersionUpdate.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\command;
  12. use think\console\Command;
  13. use think\console\Input;
  14. use think\console\input\Option;
  15. use think\console\Output;
  16. use think\Exception;
  17. use think\facade\Db;
  18. class VersionUpdate extends Command
  19. {
  20. protected function configure()
  21. {
  22. $this->setName('version:update')
  23. ->setDescription('crmeb_merchant 版本更新命令')
  24. ->addOption('package', 'p', Option::VALUE_REQUIRED, '指定更新包的路径');
  25. }
  26. protected function execute(Input $input, Output $output)
  27. {
  28. $flag = $output->confirm($input, '更新之前请务必做好数据库和代码的备份,防止数据或代码在更新中被覆盖 !!!', false);
  29. if (!$flag) return;
  30. $flag = $output->confirm($input, '请确保swoole服务和队列服务已关闭,防止意外报错', false);
  31. if (!$flag) return;
  32. $version = get_crmeb_version_code();
  33. ini_set('memory_limit', '-1');
  34. set_time_limit(0);
  35. $packagePath = $input->getOption('package') ?: 'auto_update.zip';
  36. $updateFilePath = app()->getRootPath() . ltrim($packagePath, '/= ');
  37. $updatePath = dirname($updateFilePath);
  38. $unzipPath = $updatePath . '/_update_runtime_' . str_replace('.', '_', $version);
  39. if (!is_file($updateFilePath)) {
  40. $output->warning($updateFilePath . ' 更新包不存在');
  41. return;
  42. }
  43. $zip = new \ZipArchive();
  44. if ($zip->open($updateFilePath) === true) {
  45. $zip->extractTo($unzipPath);
  46. $zip->close();
  47. } else {
  48. $output->warning($updateFilePath . ' 更新包打开失败');
  49. return;
  50. }
  51. $unlink = function () use ($unzipPath) {
  52. @unlink($unzipPath . '/update.sql');
  53. @unlink($unzipPath . '/update.zip');
  54. @unlink($unzipPath . '/AutoUpdate.php');
  55. @unlink($unzipPath . '/.env');
  56. @unlink($unzipPath . '/.config');
  57. @rmdir($unzipPath);
  58. };
  59. if (!is_file($unzipPath . '/.env') && !is_file($unzipPath . '/.config')) {
  60. $output->warning('文件不完整');
  61. $unlink();
  62. return;
  63. }
  64. if (is_file($unzipPath . '/.env')) {
  65. $env = parse_ini_file($unzipPath . '/.env', true) ?: [];
  66. }
  67. if (is_file($unzipPath . '/.config')) {
  68. $env = parse_ini_file($unzipPath . '/.config', true) ?: [];
  69. }
  70. if (($env['NAME'] ?? '') !== 'CRMEB-MERCHANT' || ((($env['OLD_VERSION'] ?? '') && ($env['OLD_VERSION'] ?? '') !== $version))) {
  71. if (($env['TYPE'] ?? '') !== 'MODEL') {
  72. $output->warning('版本号对比失败,请检查当前版本号(.version/更新包)是否被修改');
  73. $unlink();
  74. return;
  75. }
  76. }
  77. $confirm = [];
  78. if (isset($env['confirm'])) {
  79. $confirm = is_array($env['confirm']) ? $env['confirm'] : [$env['confirm']];
  80. }
  81. foreach ($confirm as $item) {
  82. if (!$output->confirm($input, $item, false)) {
  83. $unlink();
  84. return;
  85. }
  86. }
  87. $installHost = systemConfig('site_url');
  88. if (substr($installHost, 0, 5) == 'https'){
  89. $_url = str_replace('//' ,'\\\/\\\/', $installHost);
  90. } else {
  91. $_url = str_replace('http://' ,'http:\\\/\\\/', $installHost);
  92. }
  93. if (is_file($unzipPath . '/update.sql')) {
  94. $str = preg_replace('/--.*/i', '', file_get_contents($unzipPath . '/update.sql'));
  95. $str = preg_replace('/\/\*.*\*\/(\;)?/i', '', $str);
  96. $sqlList = explode(";\n", $str);
  97. } else {
  98. $sqlList = [];
  99. }
  100. $autoUpdateData = null;
  101. if (is_file($unzipPath . '/AutoUpdate.php')) {
  102. try {
  103. require_once $unzipPath . '/AutoUpdate.php';
  104. $autoUpdateData = new \crmeb\update\AutoUpdate($input, $output);
  105. } catch (\Throwable $e) {}
  106. }
  107. if ($autoUpdateData) $autoUpdateData->autoUpdateStart();
  108. $output->info('开始更新');
  109. $pre = env('database.prefix');
  110. try {
  111. Db::transaction(function () use ($pre, $output, $unzipPath, $sqlList, $autoUpdateData,$installHost,$_url) {
  112. if ($autoUpdateData) $autoUpdateData->autoUpdateBefore();
  113. $count = count($sqlList);
  114. if ($count && $autoUpdateData) {
  115. $autoUpdateData->autoSqlBefore();
  116. }
  117. foreach ($sqlList as $idx => $sql) {
  118. $sql = trim($sql, " \xEF\xBB\xBF\r\n");
  119. if (!$sql) continue;
  120. if ($pre && $pre !== 'eb_') {
  121. $sql = str_replace('eb_', $pre, $sql);
  122. }
  123. $sql = str_replace('https://mer1.crmeb.net', $installHost , $sql);
  124. $sql = str_replace('https:\\\/\\\/mer1.crmeb.net', $_url , $sql);
  125. Db::query($sql . ';');
  126. if (!($idx % 50)) {
  127. $output->info("导入中($idx/$count)");
  128. }
  129. }
  130. if ($count) {
  131. if ($autoUpdateData) $autoUpdateData->autoSqlAfter();
  132. $output->info('数据库更新成功');
  133. }
  134. $zip = new \ZipArchive();
  135. if ($zip->open($unzipPath . '/update.zip') === true) {
  136. if ($autoUpdateData) $autoUpdateData->autoCopyBefore();
  137. $zip->extractTo(app()->getRootPath());
  138. $zip->close();
  139. if ($autoUpdateData) $autoUpdateData->autoCopyAfter();
  140. } else {
  141. throw new Exception('更新文件覆盖失败');
  142. }
  143. });
  144. if ($autoUpdateData) $autoUpdateData->autoUpdateAfter();
  145. } catch (\Throwable $e) {
  146. $output->warning('更新失败:' . $e->getMessage());
  147. $unlink();
  148. if ($autoUpdateData) $autoUpdateData->autoUpdateFail($e);
  149. return;
  150. }
  151. $unlink();
  152. if ($autoUpdateData) $autoUpdateData->autoUpdateEnd();
  153. $output->info('版本更新成功, 请重启swoole服务和队列服务');
  154. update_crmeb_compiled();
  155. }
  156. }