Skip to content

Commit fd1841f

Browse files
committed
Merge branch 'master' into 3.2.0-alpha.1
2 parents 8dcb795 + f19444b commit fd1841f

5 files changed

Lines changed: 233 additions & 3 deletions

File tree

README-en.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# MineAdmin
44

55
<p align="center">
6-
<img src="web/public/logo.svg" width="120" alt="MineAdmin Logo" />
6+
<img src="https://raw.githubusercontent.com/mineadmin/MineAdmin-Vue/53924b3f98733201d4a2492cf2c91e65a56421be/public/logo.svg" width="120" alt="MineAdmin Logo" />
77
</p>
88

99
<p align="center">
@@ -18,6 +18,13 @@ It includes the common capabilities needed by enterprise admin systems, such as
1818

1919
Before using MineAdmin, please read and agree to the [Disclaimer](https://www.mineadmin.com/about/declaration).
2020

21+
## Frontend Repository
22+
Go to the frontend repository
23+
24+
- [Github MineAdmin-Vue](https://github.com/mineadmin/MineAdmin-Vue)
25+
- [Gitee MineAdmin-Vue](https://gitee.com/mineadmin/MineAdmin-vue)
26+
27+
2128
## What Can It Be Used For
2229

2330
- Build internal enterprise admin systems, such as basic management for employees, departments, positions, roles, and permissions.

README-ja.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# MineAdmin
44

55
<p align="center">
6-
<img src="web/public/logo.svg" width="120" alt="MineAdmin Logo" />
6+
<img src="https://raw.githubusercontent.com/mineadmin/MineAdmin-Vue/53924b3f98733201d4a2492cf2c91e65a56421be/public/logo.svg" width="120" alt="MineAdmin Logo" />
77
</p>
88

99
<p align="center">
@@ -18,6 +18,13 @@ MineAdmin は、Web サイトの管理画面、運営プラットフォーム、
1818

1919
MineAdmin を使用する前に、必ず[《免責事項》](https://www.mineadmin.com/about/declaration)をお読みいただき、同意してください。
2020

21+
## フロントエンドリポジトリ
22+
フロントエンドリポジトリはこちら
23+
24+
- [Github MineAdmin-Vue](https://github.com/mineadmin/MineAdmin-Vue)
25+
- [Gitee MineAdmin-Vue](https://gitee.com/mineadmin/MineAdmin-vue)
26+
27+
2128
## 何に使えるか
2229

2330
- 社内管理画面の構築。社員、部門、役職、ロール、権限などの基本管理に利用できます。

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# MineAdmin
44

55
<p align="center">
6-
<img src="web/public/logo.svg" width="120" alt="MineAdmin Logo" />
6+
<img src="https://raw.githubusercontent.com/mineadmin/MineAdmin-Vue/53924b3f98733201d4a2492cf2c91e65a56421be/public/logo.svg" width="120" alt="MineAdmin Logo" />
77
</p>
88

99
<p align="center">
@@ -18,6 +18,13 @@ MineAdmin 是一套开箱即用的后台管理系统,适合快速搭建网站
1818

1919
在使用 MineAdmin 前,请认真阅读并同意[《免责声明》](https://www.mineadmin.com/about/declaration)
2020

21+
## 前端仓库地址
22+
移步前端仓库
23+
24+
- [Github MineAdmin-Vue](https://github.com/mineadmin/MineAdmin-Vue)
25+
- [Gitee MineAdmin-Vue](https://gitee.com/mineadmin/MineAdmin-vue)
26+
27+
2128
## 适合用来做什么
2229

2330
- 搭建企业内部管理后台,例如人员、部门、岗位、角色、权限等基础管理。

app/Command/InstallCommand.php

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of MineAdmin.
6+
*
7+
* @link https://www.mineadmin.com
8+
* @document https://doc.mineadmin.com
9+
* @contact root@imoi.cn
10+
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
11+
*/
12+
13+
namespace App\Command;
14+
15+
use Hyperf\Command\Annotation\Command as CommandAnnotation;
16+
use Hyperf\Command\Command;
17+
use Hyperf\Context\ApplicationContext;
18+
use Hyperf\Contract\ConfigInterface;
19+
use Hyperf\DbConnection\Db;
20+
use Hyperf\Redis\RedisFactory;
21+
use Throwable;
22+
23+
#[CommandAnnotation]
24+
class InstallCommand extends Command
25+
{
26+
protected ?string $name = 'mine:install';
27+
28+
protected string $description = 'Install MineAdmin data and configured extensions';
29+
30+
public function handle(): int
31+
{
32+
$this->output->title('MineAdmin Install');
33+
34+
if (! $this->checkEnvironment()) {
35+
return self::FAILURE;
36+
}
37+
38+
if (! $this->runRequiredCommand('migrate')) {
39+
return self::FAILURE;
40+
}
41+
42+
if (! $this->runRequiredCommand('db:seed')) {
43+
return self::FAILURE;
44+
}
45+
46+
if (! $this->installExtensions()) {
47+
return self::FAILURE;
48+
}
49+
50+
$this->output->success('MineAdmin Install Success');
51+
52+
return self::SUCCESS;
53+
}
54+
55+
private function checkEnvironment(): bool
56+
{
57+
$this->output->section('Environment Check');
58+
59+
if (! file_exists(BASE_PATH . '/.env')) {
60+
$this->output->error('The .env file does not exist. Please create .env before installing MineAdmin.');
61+
return false;
62+
}
63+
$this->output->writeln('<info>[OK]</info> .env file exists');
64+
65+
try {
66+
Db::select('SELECT 1');
67+
$this->output->writeln('<info>[OK]</info> Database connection is available');
68+
} catch (Throwable $throwable) {
69+
$this->output->error('Database connection failed: ' . $throwable->getMessage());
70+
return false;
71+
}
72+
73+
try {
74+
$this->redisFactory()->get('default')->ping();
75+
$this->output->writeln('<info>[OK]</info> Redis connection is available');
76+
} catch (Throwable $throwable) {
77+
$this->output->error('Redis connection failed: ' . $throwable->getMessage());
78+
return false;
79+
}
80+
81+
return true;
82+
}
83+
84+
private function runRequiredCommand(string $command): bool
85+
{
86+
$this->output->section(sprintf('Run %s', $command));
87+
88+
try {
89+
$exitCode = $this->call($command);
90+
} catch (Throwable $throwable) {
91+
$this->output->error(sprintf('Command %s failed: %s', $command, $throwable->getMessage()));
92+
return false;
93+
}
94+
95+
if ($exitCode !== self::SUCCESS) {
96+
$this->output->error(sprintf('Command %s failed with exit code %d.', $command, $exitCode));
97+
return false;
98+
}
99+
100+
$this->output->writeln(sprintf('<info>[OK]</info> Command %s completed', $command));
101+
102+
return true;
103+
}
104+
105+
private function installExtensions(): bool
106+
{
107+
$this->output->section('Install Extensions');
108+
109+
$extensions = $this->config()->get('mine-extension.auto_install_list', []);
110+
if (! is_array($extensions)) {
111+
$this->output->error('Config mine-extension.auto_install_list must be an array.');
112+
return false;
113+
}
114+
115+
if ($extensions === []) {
116+
$this->output->writeln('<comment>[SKIP]</comment> auto_install_list is empty');
117+
return true;
118+
}
119+
120+
$failed = [];
121+
foreach ($extensions as $key => $extension) {
122+
$path = $this->normalizeExtensionPath($extension, $key);
123+
if ($path === null) {
124+
$this->output->warning(sprintf('Skip invalid extension config item: %s', (string) $key));
125+
continue;
126+
}
127+
128+
$this->output->writeln(sprintf('<comment>[INSTALL]</comment> %s', $path));
129+
if (! $this->installExtension($path)) {
130+
$failed[] = $path;
131+
}
132+
}
133+
134+
if ($failed !== []) {
135+
$this->output->warning(sprintf(
136+
'The following extensions failed and were skipped: %s',
137+
implode(', ', $failed)
138+
));
139+
}
140+
141+
return true;
142+
}
143+
144+
private function installExtension(string $path): bool
145+
{
146+
try {
147+
$exitCode = $this->call('mine-extension:install', [
148+
'path' => $path,
149+
'--yes' => true,
150+
]);
151+
} catch (Throwable $throwable) {
152+
$this->output->error(sprintf(
153+
'Plugin %s install failed: %s. Skip it and continue.',
154+
$path,
155+
$throwable->getMessage()
156+
));
157+
return false;
158+
}
159+
160+
if ($exitCode !== self::SUCCESS) {
161+
$this->output->error(sprintf(
162+
'Plugin %s install failed with exit code %d. Skip it and continue.',
163+
$path,
164+
$exitCode
165+
));
166+
return false;
167+
}
168+
169+
$this->output->writeln(sprintf('<info>[OK]</info> Plugin %s installed', $path));
170+
171+
return true;
172+
}
173+
174+
private function normalizeExtensionPath(mixed $extension, int|string $key): ?string
175+
{
176+
if (is_string($extension) || is_numeric($extension)) {
177+
$path = trim((string) $extension);
178+
return $path === '' ? null : $path;
179+
}
180+
181+
if (is_array($extension) && isset($extension['path']) && is_string($extension['path'])) {
182+
$path = trim($extension['path']);
183+
return $path === '' ? null : $path;
184+
}
185+
186+
if (is_string($key) && ($extension === true || $extension === null)) {
187+
$path = trim($key);
188+
return $path === '' ? null : $path;
189+
}
190+
191+
return null;
192+
}
193+
194+
private function config(): ConfigInterface
195+
{
196+
return ApplicationContext::getContainer()->get(ConfigInterface::class);
197+
}
198+
199+
private function redisFactory(): RedisFactory
200+
{
201+
return ApplicationContext::getContainer()->get(RedisFactory::class);
202+
}
203+
}

config/autoload/mine-extension.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
*/
2424
'access_token' => env('MINE_ACCESS_TOKEN'),
2525

26+
/*
27+
* The list of extensions to be automatically installed when the system is initialized.
28+
* 设置执行 mine:install 命令时,自动安装插件列表
29+
*/
30+
'auto_install_list' => [],
31+
2632
/*
2733
* The root directory where the front-end code resides.
2834
*

0 commit comments

Comments
 (0)