PluginsInstall.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. ini_set('max_execution_time', 0);
  3. ini_set('memory_limit', '500M');
  4. class PluginsInstall
  5. {
  6. protected string $archiveFile = '';//升级文件地址
  7. protected string $extractPath = '';//解压目录地址
  8. protected string $root_path = '';//程序根目录
  9. public string $download = '';//升级zip文件下载地址
  10. protected string $directory = '';//插件目录名称
  11. protected string $update_sql = '';//升级sql文件地址
  12. //构造方法初始化一些数据
  13. function __construct($info)
  14. {
  15. $this->archiveFile = runtime_path() . $info['name_en'] . '.zip';
  16. $this->extractPath = runtime_path();
  17. $this->root_path = root_path() . 'plugins/';
  18. if (!is_dir($this->root_path)) {//不存在插件目录则创建
  19. mkdir($this->root_path, 0777, true);
  20. }
  21. $this->download = $info['download'];
  22. $this->directory = $info['name_en'];
  23. if (isset($info['update_sql']) && $info['update_sql']) {
  24. $this->update_sql = $info['update_sql'];
  25. }
  26. }
  27. //运行入口
  28. function run()
  29. {
  30. return $this->startUpgrade();
  31. }
  32. //新的进程启动升级
  33. private function startUpgrade()
  34. {
  35. //如果有程序代码的更新资源则更新程序代码
  36. if (strlen($this->download) > 1) {
  37. //如果有遗留的解压资源则删除
  38. $this->deleteDirectory("{$this->extractPath}{$this->directory}");
  39. //如果存在旧的升级包则删除
  40. $this->delZip();
  41. //下载远程更新包
  42. if (!$this->fileDownload()) {
  43. abort(0, "资源下载失败");
  44. }
  45. //解压升级包
  46. if (!$this->unzip($this->archiveFile, $this->extractPath)) {
  47. $this->delZip();
  48. abort(0, '升级资源包解压失败');
  49. }
  50. //拷贝覆盖
  51. $this->copy();
  52. //删除下载的更新包
  53. $this->delZip();
  54. //更新完后的一些操作
  55. if (mb_strlen($this->update_sql) > 0) {
  56. $this->updateSql();
  57. }
  58. }
  59. //退出
  60. return true;
  61. }
  62. private function fileDownload(): bool
  63. {
  64. try {
  65. $f = fopen($this->download, 'r');
  66. $w = fopen($this->archiveFile, 'wb+');
  67. do {
  68. $a = fread($f, 1024);
  69. fwrite($w, $a);
  70. } while ($a);
  71. fclose($w);
  72. fclose($f);
  73. } catch (ErrorException $e) {
  74. return false;
  75. }
  76. return true;
  77. }
  78. //删除升级包
  79. function delZip()
  80. {
  81. if (file_exists($this->archiveFile)) {
  82. unlink($this->archiveFile);
  83. }
  84. }
  85. //解压
  86. private function unzip($archiveFile, $extractPath): bool
  87. {
  88. $zip = new ZipArchive();
  89. if ($zip->open($archiveFile) === TRUE) {
  90. $zip->extractTo($extractPath, null);
  91. $zip->close();
  92. } else {
  93. return false;
  94. }
  95. return true;
  96. }
  97. //升级的数据库
  98. function updateSql()
  99. {
  100. $f = fopen($this->update_sql, 'r');
  101. $sql = '';
  102. do {
  103. $sqlTmp = fread($f, 1024);
  104. $sql = $sql . $sqlTmp;
  105. } while ($sqlTmp);
  106. fclose($f);
  107. // 解析SQL文件内容并执行
  108. $sql_statements = explode(';', trim($sql));
  109. foreach ($sql_statements as $sql_statement) {
  110. if (!empty($sql_statement)) {
  111. try {
  112. \think\facade\Db::query($sql_statement);
  113. } catch (Exception $e) {
  114. }
  115. }
  116. }
  117. }
  118. //递归删除目录
  119. function deleteDirectory($dir)
  120. {
  121. if (!is_dir($dir)) {
  122. return;
  123. }
  124. $files = scandir($dir);
  125. foreach ($files as $file) {
  126. if ($file != '.' && $file != '..') {
  127. if (is_dir("$dir/$file")) {
  128. $this->deleteDirectory("$dir/$file");
  129. } else {
  130. unlink("$dir/$file");
  131. }
  132. }
  133. }
  134. rmdir($dir);
  135. }
  136. // 递归复制目录及其内容
  137. function copyDir($source, $dest)
  138. {
  139. if (!is_dir($dest)) {
  140. mkdir($dest, 0777, true);
  141. }
  142. $files = scandir($source);
  143. foreach ($files as $file) {
  144. if ($file !== '.' && $file !== '..') {
  145. $src = $source . '/' . $file;
  146. $dst = $dest . '/' . $file;
  147. if (is_dir($src)) {
  148. $this->copyDir($src, $dst);
  149. } else {
  150. copy($src, $dst);
  151. }
  152. }
  153. }
  154. }
  155. //覆盖原来的程序
  156. private function copy()
  157. {
  158. //移动覆盖
  159. $this->copyDir("{$this->extractPath}{$this->directory}/", "{$this->root_path}{$this->directory}");
  160. //删除解压目录
  161. $this->deleteDirectory("{$this->extractPath}{$this->directory}");
  162. }
  163. }