feat: 插件依赖强制校验 + 文章后台表单/表格注入 hook
- PluginManager: requires 依赖链校验(enable 需依赖已启用,disable 阻止有启用依赖者的插件,boot 跳过依赖未满足插件),all() 输出依赖状态供后台展示 - Plugins 页:卡片显示依赖链徽章,依赖未满足时禁用启用按钮,启停失败弹错误通知 - PostResource: form()/table() 增加 filament.post_form / filament.post_table 注入点 - membership 插件:注入「付费设置」Section(meta.price 单篇价格 + meta.members_only 会员专享)与表格价格/会员列
This commit is contained in:
@@ -8,6 +8,7 @@ namespace App\Blog\Support;
|
||||
use App\Models\PluginRecord;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
@@ -54,6 +55,25 @@ class PluginManager
|
||||
|
||||
[$vendor, $name] = array_pad(explode('.', $basename), 2, $basename);
|
||||
|
||||
$requires = $manifest['requires'] ?? [];
|
||||
$dependencies = [];
|
||||
$dependencyErrors = [];
|
||||
|
||||
foreach ($requires as $req) {
|
||||
$installed = $this->exists($req);
|
||||
$enabled = $installed && $this->isEnabled($req);
|
||||
$dependencies[] = [
|
||||
'key' => $req,
|
||||
'title' => $this->manifest($req)['title'] ?? $req,
|
||||
'ok' => $enabled,
|
||||
'reason' => $installed ? ($enabled ? '' : '未启用') : '未安装',
|
||||
];
|
||||
|
||||
if (! $enabled) {
|
||||
$dependencyErrors[] = $req;
|
||||
}
|
||||
}
|
||||
|
||||
$plugins[$basename] = [
|
||||
'key' => $basename,
|
||||
'vendor' => $vendor,
|
||||
@@ -63,6 +83,9 @@ class PluginManager
|
||||
'description' => $manifest['description'] ?? '',
|
||||
'author' => $manifest['author'] ?? '',
|
||||
'enabled' => $this->isEnabled($basename),
|
||||
'requires' => $requires,
|
||||
'dependencies' => $dependencies,
|
||||
'dependency_errors' => $dependencyErrors,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -84,8 +107,53 @@ class PluginManager
|
||||
return in_array($plugin, config('plugins.enabled', []), true);
|
||||
}
|
||||
|
||||
public function requires(string $plugin): array
|
||||
{
|
||||
return $this->manifest($plugin)['requires'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 依赖未满足的问题列表(空数组 = 依赖完好)。
|
||||
*/
|
||||
public function dependencyProblems(string $plugin): array
|
||||
{
|
||||
$problems = [];
|
||||
|
||||
foreach ($this->requires($plugin) as $req) {
|
||||
if (! $this->exists($req)) {
|
||||
$problems[] = "缺少依赖插件:{$req}(未安装)";
|
||||
} elseif (! $this->isEnabled($req)) {
|
||||
$problems[] = '依赖插件未启用:'.$req.'('.$this->manifest($req)['title'].')';
|
||||
}
|
||||
}
|
||||
|
||||
return $problems;
|
||||
}
|
||||
|
||||
/**
|
||||
* 已启用且依赖本插件的插件列表。
|
||||
*/
|
||||
public function dependents(string $plugin): array
|
||||
{
|
||||
$dependents = [];
|
||||
|
||||
foreach ($this->all() as $key => $p) {
|
||||
if ($p['enabled'] && in_array($plugin, $p['requires'] ?? [], true)) {
|
||||
$dependents[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $dependents;
|
||||
}
|
||||
|
||||
public function enable(string $plugin): void
|
||||
{
|
||||
$problems = $this->dependencyProblems($plugin);
|
||||
|
||||
if ($problems) {
|
||||
throw new RuntimeException('无法启用 '.$plugin.':'.implode(';', $problems));
|
||||
}
|
||||
|
||||
[$vendor, $name] = array_pad(explode('.', $plugin), 2, $plugin);
|
||||
PluginRecord::query()->updateOrCreate(
|
||||
['vendor' => $vendor, 'name' => $name],
|
||||
@@ -95,6 +163,12 @@ class PluginManager
|
||||
|
||||
public function disable(string $plugin): void
|
||||
{
|
||||
$dependents = $this->dependents($plugin);
|
||||
|
||||
if ($dependents) {
|
||||
throw new RuntimeException('无法停用 '.$plugin.':以下已启用插件依赖它:'.implode('、', $dependents).'。请先停用这些插件。');
|
||||
}
|
||||
|
||||
[$vendor, $name] = array_pad(explode('.', $plugin), 2, $plugin);
|
||||
PluginRecord::query()->updateOrCreate(
|
||||
['vendor' => $vendor, 'name' => $name],
|
||||
|
||||
Reference in New Issue
Block a user