UpdateController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Author: 芸众商城 www.yunzshop.com
  5. * Date: 18/04/2017
  6. * Time: 11:13
  7. */
  8. namespace app\platform\modules\system\controllers;
  9. use app\common\components\BaseController;
  10. use app\common\facades\Setting;
  11. use app\common\services\AutoUpdate;
  12. use app\common\services\systemUpgrade;
  13. use app\host\HostManager;
  14. class UpdateController extends BaseController
  15. {
  16. private $set;
  17. private $key;
  18. private $secret;
  19. public $systemUpgrade;
  20. public $update;
  21. public function __construct()
  22. {
  23. $this->set = Setting::getNotUniacid('platform_shop.key');
  24. $this->key = $this->set['key'];
  25. $this->secret = $this->set['secret'];
  26. $this->systemUpgrade = new systemUpgrade($this->key, $this->secret);
  27. $this->update = new AutoUpdate(null, null, 300);
  28. $this->__init();
  29. }
  30. private function __init()
  31. {
  32. if (!$this->key || !$this->secret) {
  33. return;
  34. }
  35. $this->update->setBasicAuth($this->key, $this->secret);
  36. $this->update->setUpdateUrl(config('auto-update.checkUrl')); //Replace with your server update directory
  37. }
  38. public function systemInfo()
  39. {
  40. //删除非法文件
  41. $this->systemUpgrade->deleteFile();
  42. //执行迁移文件
  43. $this->systemUpgrade->runMigrate();
  44. //清理缓存
  45. $this->systemUpgrade->createCache();
  46. $result = $this->systemUpgrade->systemCheck($this->update);
  47. $data = [
  48. 'result' => 1,
  49. 'msg' => 'ok',
  50. 'data' => $result
  51. ];
  52. response()->json($data)->send();
  53. }
  54. public function log()
  55. {
  56. $page = \YunShop::request()->page ?: 1;
  57. $log = $this->systemUpgrade->showLog($this->update, $page);
  58. $log = json_decode($log);
  59. $data = [
  60. 'result' => 1,
  61. 'msg' => 'ok',
  62. 'data' => $log->result
  63. ];
  64. response()->json($data)->send();
  65. }
  66. /**
  67. * 废弃
  68. *
  69. * @return array|string
  70. * @throws \Throwable
  71. */
  72. public function upgrade()
  73. {
  74. $list = [];
  75. //删除非法文件
  76. $this->systemUpgrade->deleteFile();
  77. //执行迁移文件
  78. $this->systemUpgrade->runMigrate();
  79. $this->update->setUpdateFile('check_app.json');
  80. if (is_file(base_path() . '/' . 'config/front-version.php')) {
  81. $this->update->setCurrentVersion(config('front-version'));
  82. $version = config('front-version');
  83. } else {
  84. $this->update->setCurrentVersion(config('version'));
  85. $version = config('version');
  86. }
  87. $this->update->checkUpdate();
  88. if ($this->update->newVersionAvailable()) {
  89. $list = $this->update->getUpdates();
  90. }
  91. krsort($list);
  92. if (!empty($list[0]['php_version']) && !$this->systemUpgrade->checkPHPVersion($list[0]['php_version'])) {
  93. $list = [];
  94. }
  95. return view('system.update.upgrad', [
  96. 'list' => $list,
  97. 'version' => $version,
  98. 'count' => count($list)
  99. ])->render();
  100. }
  101. /**
  102. * footer检测更新
  103. * @return \Illuminate\Http\JsonResponse
  104. */
  105. public function check()
  106. {
  107. $result = ['msg' => '', 'last_version' => '', 'updated' => 0];
  108. $this->update->setUpdateFile('check_app.json');
  109. $this->update->setCurrentVersion(config('version'));
  110. $res = $this->update->checkUpdate();
  111. //Check for a new update
  112. if ($res === false) {
  113. $result['msg'] = 'Could not check for updates! See log file for details.';
  114. response()->json($result)->send();
  115. return;
  116. }
  117. if (isset($res['result']) && 0 == $res['result']) {
  118. $res['updated'] = 0;
  119. return response()->json($res)->send();
  120. }
  121. if ($this->update->newVersionAvailable()) {
  122. $result['last_version'] = $this->update->getLatestVersion()->getVersion();
  123. $result['updated'] = 1;
  124. $result['current_version'] = config('version');
  125. }
  126. response()->json($result)->send();
  127. return;
  128. }
  129. /**
  130. * 检测更新
  131. * @return \Illuminate\Http\JsonResponse
  132. */
  133. public function verifyCheck()
  134. {
  135. set_time_limit(0);
  136. //执行迁移文件
  137. $this->systemUpgrade->runMigrate();
  138. $filter_file = ['composer.json', 'README.md'];
  139. $plugins_dir = $this->update->getDirsByPath('plugins', $this->systemUpgrade->filesystem);
  140. $result = ['result' => -2, 'msg' => '网络请求超时', 'version' => ''];
  141. if (!$this->key || !$this->secret) {
  142. return response()->json(['result' => -1, 'msg' => '商城未授权', 'data' => []]);
  143. }
  144. //前端更新文件检测
  145. $frontendUpgrad = $this->systemUpgrade->frontendUpgrad($this->key, $this->secret);
  146. //后台更新文件检测
  147. $this->update->setUpdateFile('backcheck_app.json');
  148. $this->update->setCurrentVersion(config('version'));
  149. //Check for a new update
  150. $ret = $this->update->checkBackUpdate();
  151. if ($ret == 'unknown') {
  152. $result = ['result' => -1];
  153. }
  154. if (is_array($ret)) {
  155. if (!empty($ret['php-version']) && !$this->systemUpgrade->checkPHPVersion($ret['php-version'])) {
  156. $result = ['result' => 98, 'msg' => '服务器php版本(v' . PHP_VERSION . ')过低,不符合更新条件,建议升级到php版本>=(v' . $ret['php-version'] . ')', 'last_version' => ''];
  157. response()->json($result)->send();
  158. exit;
  159. }
  160. if (1 == $ret['result']) {
  161. $files = [];
  162. if (!empty($ret['files'])) {
  163. foreach ($ret['files'] as $file) {
  164. //忽略指定文件
  165. if (in_array($file['path'], $filter_file)) {
  166. continue;
  167. }
  168. //忽略前端样式文件
  169. if (preg_match('/^static\/app/', $file['path'])) {
  170. continue;
  171. }
  172. //忽略没有安装的插件
  173. if (preg_match('/^plugins/', $file['path'])) {
  174. $sub_dir = substr($file['path'], strpos($file['path'], '/') + 1);
  175. $sub_dir = substr($sub_dir, 0, strpos($sub_dir, '/'));
  176. if (!in_array($sub_dir, $plugins_dir)) {
  177. continue;
  178. }
  179. }
  180. //忽略前后端版本号记录文件
  181. if (($file['path'] == 'config/front-version.php'
  182. || $file['path'] == 'config/backend_version.php'
  183. || $file['path'] == 'config/wq-ersion.php'
  184. || $file['path'] == 'config/business_version.php')
  185. && is_file(base_path() . '/' . $file['path'])) {
  186. continue;
  187. }
  188. $entry = base_path() . '/' . $file['path'];
  189. if ($file['path'] == 'composer.lock' && md5_file($entry) != $file['md5']) {
  190. $this->systemUpgrade->setComposerStatus();
  191. }
  192. //如果本地没有此文件或者文件与服务器不一致
  193. if (!is_file($entry) || md5_file($entry) != $file['md5']) {
  194. $files[] = array(
  195. 'path' => $file['path'],
  196. 'download' => 0
  197. );
  198. $difffile[] = $file['path'];
  199. } else {
  200. $samefile[] = $file['path'];
  201. }
  202. }
  203. }
  204. $tmpdir = storage_path('app/public/tmp/' . date('ymd'));
  205. if (!is_dir($tmpdir)) {
  206. $this->systemUpgrade->filesystem->makeDirectory($tmpdir, 0755, true);
  207. }
  208. $ret['files'] = $files;
  209. file_put_contents($tmpdir . "/file.txt", json_encode($ret));
  210. if (empty($files)) {
  211. $version = config('version');
  212. //TODO 更新日志记录
  213. } else {
  214. $version = $ret['version'];
  215. }
  216. $this->systemUpgrade->mvenv();
  217. //business更新
  218. $this->systemUpgrade->business($ret['business_version']);
  219. $result = [
  220. 'result' => 1,
  221. 'version' => $version,
  222. 'files' => $ret['files'],
  223. 'filecount' => count($files),
  224. 'frontendUpgrad' => count($frontendUpgrad),
  225. 'list' => $frontendUpgrad
  226. ];
  227. } else {
  228. preg_match('/"[\d\.]+"/', file_get_contents(base_path('config/') . 'version.php'), $match);
  229. $version = $match ? trim($match[0], '"') : '1.0.0';
  230. $result = ['result' => 99, 'msg' => '', 'version' => $version];
  231. }
  232. }
  233. response()->json($result)->send();
  234. }
  235. public function fileDownload()
  236. {
  237. $protocol = \YunShop::request()->protocol;
  238. /*if (!$protocol['file'] || !$protocol['update']) {
  239. response()->json([
  240. 'result' => 0,
  241. 'msg' => '未同意更新协议,禁止更新',
  242. 'data' => []
  243. ])->send();
  244. exit;
  245. }*/
  246. $tmpdir = storage_path('app/public/tmp/' . date('ymd'));
  247. $f = file_get_contents($tmpdir . "/file.txt");
  248. $upgrade = json_decode($f, true);
  249. $files = $upgrade['files'];
  250. $total = count($upgrade['files']);
  251. $path = "";
  252. $nofiles = \YunShop::request()->nofiles;
  253. $status = 1;
  254. //找到一个没更新过的文件去更新
  255. foreach ($files as $f) {
  256. if (empty($f['download'])) {
  257. $path = $f['path'];
  258. break;
  259. }
  260. }
  261. if (!empty($path)) {
  262. if (!empty($nofiles)) {
  263. if (in_array($path, $nofiles)) {
  264. foreach ($files as &$f) {
  265. if ($f['path'] == $path) {
  266. $f['download'] = 1;
  267. break;
  268. }
  269. }
  270. unset($f);
  271. $upgrade['files'] = $files;
  272. $tmpdir = storage_path('app/public/tmp/' . date('ymd'));
  273. if (!is_dir($tmpdir)) {
  274. $this->systemUpgrade->filesystem->makeDirectory($tmpdir, 0755, true);
  275. }
  276. file_put_contents($tmpdir . "/file.txt", json_encode($upgrade));
  277. return response()->json(['result' => 3])->send();
  278. }
  279. }
  280. $this->update->setUpdateFile('backdownload_app.json');
  281. $this->update->setCurrentVersion(config('version'));
  282. //Check for a new download
  283. $ret = $this->update->checkBackDownload([
  284. 'path' => urlencode($path)
  285. ]);
  286. $this->systemUpgrade->setSysUpgrade($ret);
  287. $this->systemUpgrade->setVendorZip($ret);
  288. //下载vendor
  289. if ($this->systemUpgrade->isVendorZip()) {
  290. $this->systemUpgrade->downloadVendorZip();
  291. }
  292. //预下载
  293. if (is_array($ret)) {
  294. $path = $ret['path'];
  295. $dirpath = dirname($path);
  296. $save_path = storage_path('app/auto-update/shop') . '/' . $dirpath;
  297. if (!is_dir($save_path)) {
  298. $this->systemUpgrade->filesystem->makeDirectory($save_path, 0755, true);
  299. }
  300. //新建
  301. $content = base64_decode($ret['content']);
  302. file_put_contents(storage_path('app/auto-update/shop') . '/' . $path, $content);
  303. $success = 0;
  304. foreach ($files as &$f) {
  305. if ($f['path'] == $path) {
  306. $f['download'] = 1;
  307. break;
  308. }
  309. if ($f['download']) {
  310. $success++;
  311. }
  312. }
  313. unset($f);
  314. $upgrade['files'] = $files;
  315. $tmpdir = storage_path('app/public/tmp/' . date('ymd'));
  316. if (!is_dir($tmpdir)) {
  317. $this->systemUpgrade->filesystem->makeDirectory($tmpdir, 0755, true);
  318. }
  319. file_put_contents($tmpdir . "/file.txt", json_encode($upgrade));
  320. }
  321. } else {
  322. //检查并下载框架更新文件
  323. $this->startDownloadFramework();
  324. //覆盖
  325. foreach ($files as $f) {
  326. $path = $f['path'];
  327. $file_dir = dirname($path);
  328. if (!is_dir(base_path($file_dir))) {
  329. $this->systemUpgrade->filesystem->makeDirectory(base_path($file_dir), 0755, true);
  330. }
  331. $content = file_get_contents(storage_path('app/auto-update/shop') . '/' . $path);
  332. //去除空文件判断
  333. if (!empty($content)) {
  334. file_put_contents(base_path($path), $content);
  335. @unlink(storage_path('app/auto-update/shop') . '/' . $path);
  336. }
  337. }
  338. //执行迁移文件
  339. $this->systemUpgrade->runMigrate();
  340. $status = 2;
  341. $success = $total;
  342. $response = response()->json([
  343. 'result' => $status,
  344. 'total' => $total,
  345. 'success' => $success
  346. ]);
  347. if ($this->systemUpgrade->isVendorZip() && $this->systemUpgrade->validateVendorZip()) {
  348. $this->systemUpgrade->delConfig();
  349. $this->systemUpgrade->renameVendor();
  350. $res = $this->systemUpgrade->unVendorZip();
  351. if (!$res) {
  352. $this->systemUpgrade->renameVendor($res);
  353. }
  354. }
  355. //清理缓存
  356. $this->systemUpgrade->clearCache($this->systemUpgrade->filesystem);
  357. \Log::debug('----Queue Restarth----');
  358. app('supervisor')->restart();
  359. (new HostManager())->restart();
  360. if ($this->systemUpgrade->isVendorZip()) {
  361. if ($this->systemUpgrade->validateVendorZip()) {
  362. $this->systemUpgrade->delVendor(base_path('vendor_' . date('Y-m-d')));
  363. }
  364. $this->systemUpgrade->delVendorZip();
  365. }
  366. $response->send();
  367. }
  368. response()->json([
  369. 'result' => $status,
  370. 'total' => $total,
  371. 'success' => $success
  372. ])->send();
  373. }
  374. /**
  375. * 开始下载并更新前端vue
  376. * @return \Illuminate\Http\RedirectResponse
  377. */
  378. public function startDownload()
  379. {
  380. \Cache::flush();
  381. $resultArr = ['msg' => '', 'status' => 0, 'data' => []];
  382. set_time_limit(0);
  383. $this->update->setUpdateFile('check_app.json');
  384. if (is_file(base_path() . '/' . 'config/front-version.php')) {
  385. $this->update->setCurrentVersion(config('front-version'));
  386. } else {
  387. $this->update->setCurrentVersion(config('version'));
  388. }
  389. //Check for a new update
  390. if ($this->update->checkUpdate() === false) {
  391. $resultArr['msg'] = 'Could not check for updates! See log file for details.';
  392. response()->json($resultArr)->send();
  393. return;
  394. }
  395. if ($this->update->newVersionAvailable()) {
  396. $result = $this->update->update();
  397. if ($result === true) {
  398. $list = $this->update->getUpdates();
  399. if (!empty($list)) {
  400. $this->systemUpgrade->setSystemVersion($list);
  401. if (!is_dir(base_path('config/shop-foundation'))) {
  402. \Artisan::call('config:cache');
  403. }
  404. }
  405. $resultArr['status'] = 1;
  406. $resultArr['msg'] = '更新成功';
  407. } else {
  408. $resultArr['msg'] = '更新失败: ' . $result;
  409. if ($result = AutoUpdate::ERROR_SIMULATE) {
  410. $resultArr['data'] = $this->update->getSimulationResults();
  411. }
  412. }
  413. } else {
  414. $resultArr['msg'] = 'Current Version is up to date frontend';
  415. }
  416. response()->json($resultArr)->send();
  417. return;
  418. }
  419. /**
  420. * 开始下载并更新框架vue
  421. * @return \Illuminate\Http\RedirectResponse
  422. */
  423. public function startDownloadFramework()
  424. {
  425. $resultArr = ['msg' => '', 'status' => 0, 'data' => []];
  426. set_time_limit(0);
  427. $this->update->setUpdateFile('check_fromework.json');
  428. $this->update->setCurrentVersion(config('backend_version'));
  429. //Check for a new update
  430. if ($this->update->checkUpdate() === false) {
  431. $resultArr['msg'] = 'Could not check for updates! See log file for details.';
  432. response()->json($resultArr)->send();
  433. return;
  434. }
  435. if ($this->update->newVersionAvailable()) {
  436. $result = $this->update->update(2);
  437. if ($result === true) {
  438. $list = $this->update->getUpdates();
  439. if (!empty($list)) {
  440. $this->systemUpgrade->setSystemVersion($list, 2);
  441. }
  442. $resultArr['status'] = 1;
  443. $resultArr['msg'] = '-----------后台框架更新成功---------';
  444. \Log::debug($resultArr['msg']);
  445. } else {
  446. $resultArr['msg'] = '---------后台框架更新失败---------: ' . $result;
  447. if ($result = AutoUpdate::ERROR_SIMULATE) {
  448. $resultArr['data'] = $this->update->getSimulationResults();
  449. }
  450. response()->json($resultArr)->send();
  451. return;
  452. }
  453. } else {
  454. \Log::debug('--------后台框架已是最新版本-------');
  455. }
  456. }
  457. public function pirate()
  458. {
  459. return view('update.pirate', [])->render();
  460. }
  461. }