UpdateController.php 17 KB

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