PanelInstallation.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\User;
  4. use Artisan;
  5. use Exception;
  6. use File;
  7. use Illuminate\Console\Command;
  8. use Illuminate\Contracts\Filesystem\FileNotFoundException;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Str;
  11. class PanelInstallation extends Command
  12. {
  13. protected $signature = 'panel:install';
  14. protected $description = 'ProxyPanel Installation (面板自主安装)';
  15. public function handle(): int
  16. {
  17. $bar = $this->output->createProgressBar(7);
  18. $bar->minSecondsBetweenRedraws(0);
  19. $this->displayBanner();
  20. $bar->start();
  21. $this->createEnvironmentFile();
  22. $bar->advance();
  23. $this->setDatabaseInfo(); // 设置数据库信息
  24. $bar->advance();
  25. $this->generateAppKey(); // 设置 app key
  26. $bar->advance();
  27. $this->testDatabaseConnection(); // 测试数据库连通性
  28. $bar->advance();
  29. $this->importDatabase(); // 初始化数据库
  30. $bar->advance();
  31. $this->createStorageLink(); // 文件夹软连接
  32. $bar->advance();
  33. $this->setAdminAccount(); // 设置管理员信息
  34. $bar->finish();
  35. $this->info('Initial installation completed! | 初步安装完毕');
  36. $this->line(PHP_EOL.'View your http(s)://[website url]/admin to insert Administrator Dashboard | 访问 http(s)://[你的站点]/admin 进入管理面板');
  37. return 0;
  38. }
  39. private function displayBanner(): void
  40. {
  41. $banner = <<<BANNER
  42. ___ ___ _
  43. / _ \ _ __ ___ __ __ _ _ / _ \ __ _ _ __ ___ | |
  44. / /_)/| '__| / _ \ \ \/ /| | | | / /_)/ / _` || '_ \ / _ \| |
  45. / ___/ | | | (_) | > < | |_| |/ ___/ | (_| || | | || __/| |
  46. \/ |_| \___/ /_/\_\ \__, |\/ \__,_||_| |_| \___||_|
  47. |___/
  48. BANNER;
  49. $this->info($banner);
  50. }
  51. private function createEnvironmentFile(): void
  52. {
  53. $this->line(' Creating .env | 创建.env');
  54. $envPath = app()->environmentFilePath();
  55. if (File::exists($envPath)) {
  56. $this->error('.env file already exists. | .env已存在');
  57. if (! $this->confirm('Do you wish to continue by deleting the existing .env file? | 是否删除已存.env文件, 并继续安装?')) {
  58. abort(500, 'Installation aborted by user decision. | 安装程序终止');
  59. }
  60. File::delete($envPath);
  61. }
  62. try {
  63. File::copy(base_path('.env.example'), $envPath);
  64. } catch (Exception $e) {
  65. abort(500, 'Failed to copy .env.example to .env file. Please check file permissions. | 复制环境文件失败, 请检查目录权限 '.$e->getMessage());
  66. }
  67. }
  68. /**
  69. * @throws FileNotFoundException
  70. */
  71. private function setDatabaseInfo(): void
  72. {
  73. $this->line(' Setting up database information | 设置数据库信息');
  74. $databaseInfo = [
  75. 'DB_HOST' => $this->ask('Enter the database host (default: localhost) | 请输入数据库地址(默认:localhost)', 'localhost'),
  76. 'DB_PORT' => $this->ask('Enter the database port (default: 3306) | 请输入数据库地址(默认:3306)', 3306),
  77. 'DB_DATABASE' => $this->ask('Enter the database name | 请输入数据库名'),
  78. 'DB_USERNAME' => $this->ask('Enter the database username | 请输入数据库用户名'),
  79. 'DB_PASSWORD' => $this->ask('Enter the database password | 请输入数据库密码'),
  80. ];
  81. $this->saveToEnv($databaseInfo);
  82. }
  83. /**
  84. * @throws FileNotFoundException
  85. */
  86. private function saveToEnv(array $data = []): void
  87. {
  88. $envPath = app()->environmentFilePath();
  89. $contents = File::get($envPath);
  90. foreach ($data as $key => $value) {
  91. $key = strtoupper($key);
  92. $value = Str::contains($value, ' ') ? '"'.$value.'"' : $value;
  93. $line = $key.'='.$value;
  94. $contents = preg_replace("/^$key=[^\r\n]*/m", $line, $contents, -1, $count);
  95. if ($count === 0) {
  96. $contents .= "\n".$line;
  97. }
  98. }
  99. File::put($envPath, $contents);
  100. $this->line('.env file updated successfully. | .env文件更新成功');
  101. }
  102. private function generateAppKey(): void
  103. {
  104. $this->line(' Generating app key | 设置 app key');
  105. Artisan::call('key:generate');
  106. }
  107. private function testDatabaseConnection(): void
  108. {
  109. $this->line(' Testing database connection | 测试数据库连通性');
  110. try {
  111. Artisan::call('config:cache');
  112. DB::connection()->getPdo();
  113. } catch (Exception $e) {
  114. File::delete(app()->environmentFilePath());
  115. abort(500, 'Failed to connect to the database: | 数据库连接失败: '.$e->getMessage());
  116. }
  117. }
  118. private function importDatabase(): void
  119. {
  120. $this->line(' Importing database | 导入数据库');
  121. try {
  122. Artisan::call('migrate --seed');
  123. } catch (Exception $e) {
  124. Artisan::call('db:wipe');
  125. abort(500, 'Failed to import database: | 导入数据库失败: '.$e->getMessage());
  126. }
  127. $this->info('Database loaded! | 数据库导入完成');
  128. }
  129. private function createStorageLink(): void
  130. {
  131. $this->line(' Creating storage link | 建立文件夹软连接');
  132. try {
  133. Artisan::call('storage:link');
  134. } catch (Exception $e) {
  135. abort(500, 'Failed to create storage link: | 建立文件夹软连接失败: '.$e->getMessage());
  136. }
  137. }
  138. private function setAdminAccount(): void
  139. {
  140. $this->line(' Setting up admin account | 设置管理员基础信息');
  141. $username = $this->ask('Please set your administrator account email address | 请输入[管理员]邮箱 默认: [email protected]', '[email protected]');
  142. $this->info('[管理员] 账号: '.$username);
  143. $password = $this->ask('Please set your administrator account password | 请输入[管理员]密码 默认: 123456', '123456');
  144. $this->info('[管理员] 密码: '.$password);
  145. if ($this->editAdmin($username, $password)) {
  146. $this->info('Admin account created successfully. | 管理员账号创建成功');
  147. } else {
  148. abort(500, '管理员账号注册失败,请重试');
  149. }
  150. $this->info('Admin account created successfully.');
  151. }
  152. private function editAdmin(string $username, string $password): bool
  153. {
  154. $user = User::find(1);
  155. $user->username = $username;
  156. $user->password = $password;
  157. return $user->save();
  158. }
  159. }