154 lines
5.3 KiB
PHP
154 lines
5.3 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Filament\Pages;
|
||
|
||
use App\Domain\Plugin\PluginManager;
|
||
use App\Models\Plugin;
|
||
use BackedEnum;
|
||
use Filament\Actions\Action;
|
||
use Filament\Notifications\Notification;
|
||
use Filament\Pages\Page;
|
||
use Filament\Support\Enums\Alignment;
|
||
use Filament\Support\Enums\Width;
|
||
use Filament\Support\Icons\Heroicon;
|
||
use Illuminate\Contracts\View\View;
|
||
|
||
class ManagePlugins extends Page
|
||
{
|
||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedPuzzlePiece;
|
||
|
||
protected static ?int $navigationSort = 81;
|
||
|
||
protected string $view = 'filament.pages.manage-plugins';
|
||
|
||
/** @var array<int, array<string, mixed>> */
|
||
public array $plugins = [];
|
||
|
||
public static function getNavigationGroup(): ?string
|
||
{
|
||
return __('admin.groups.system');
|
||
}
|
||
|
||
public static function getNavigationLabel(): string
|
||
{
|
||
return __('admin.nav.plugins');
|
||
}
|
||
|
||
public function getTitle(): string
|
||
{
|
||
return __('admin.pages.plugins_title');
|
||
}
|
||
|
||
public function mount(PluginManager $manager): void
|
||
{
|
||
$manager->syncDiscoveredPlugins();
|
||
$this->reload($manager);
|
||
}
|
||
|
||
public function enable(string $name, PluginManager $manager): void
|
||
{
|
||
try {
|
||
$manager->enable($name);
|
||
$this->reload($manager);
|
||
Notification::make()->title(__('admin.pages.enable').':'.$name)->success()->send();
|
||
} catch (\Throwable $e) {
|
||
Notification::make()->title($e->getMessage())->danger()->send();
|
||
}
|
||
}
|
||
|
||
public function disable(string $name, PluginManager $manager): void
|
||
{
|
||
try {
|
||
$manager->disable($name);
|
||
$this->reload($manager);
|
||
Notification::make()->title(__('admin.pages.disable').':'.$name)->success()->send();
|
||
} catch (\Throwable $e) {
|
||
Notification::make()->title($e->getMessage())->danger()->send();
|
||
}
|
||
}
|
||
|
||
public function showDocs(string $name, PluginManager $manager): void
|
||
{
|
||
if ($manager->readDocs($name) === null) {
|
||
Notification::make()->title(__('admin.messages.plugin_docs_missing'))->warning()->send();
|
||
|
||
return;
|
||
}
|
||
|
||
$this->mountAction('viewDocs', ['name' => $name]);
|
||
}
|
||
|
||
public function viewDocsAction(): Action
|
||
{
|
||
return Action::make('viewDocs')
|
||
->label(__('admin.pages.plugin_docs'))
|
||
->modalHeading(function (array $arguments): string {
|
||
$name = (string) ($arguments['name'] ?? '');
|
||
$plugin = collect($this->plugins)->firstWhere('name', $name);
|
||
$title = is_array($plugin) ? (string) ($plugin['title'] ?? $name) : $name;
|
||
|
||
return __('admin.pages.plugin_docs').($title !== '' ? ' · '.$title : '');
|
||
})
|
||
->modalContent(function (array $arguments): View {
|
||
return view('filament.partials.plugin-docs', [
|
||
'html' => app(PluginManager::class)->readDocsHtml((string) ($arguments['name'] ?? '')) ?? '',
|
||
]);
|
||
})
|
||
->modalAlignment(Alignment::Center)
|
||
->modalWidth(Width::FiveExtraLarge)
|
||
->modalSubmitAction(false)
|
||
->modalCancelAction(fn (Action $action): Action => $action
|
||
->label(__('admin.actions.close'))
|
||
->color('primary')
|
||
->close()
|
||
)
|
||
->modalFooterActionsAlignment(Alignment::End)
|
||
->closeModalByClickingAway()
|
||
->closeModalByEscaping()
|
||
->stickyModalHeader()
|
||
->stickyModalFooter()
|
||
->extraModalWindowAttributes(['class' => 'lb-plugin-docs-modal']);
|
||
}
|
||
|
||
protected function reload(PluginManager $manager): void
|
||
{
|
||
$discovered = $manager->discover();
|
||
$records = Plugin::query()->get()->keyBy('name');
|
||
$accents = ['#0f8a7a', '#c45c26', '#2563eb', '#7c3aed', '#db2777', '#0891b2'];
|
||
|
||
$this->plugins = $discovered->values()->map(function (array $manifest, int $index) use ($records, $accents, $manager) {
|
||
$name = (string) $manifest['name'];
|
||
$titleKey = 'admin.plugins.'.$name.'.title';
|
||
$descKey = 'admin.plugins.'.$name.'.description';
|
||
$record = $records->get($name);
|
||
$requires = (array) ($manifest['requires'] ?? []);
|
||
|
||
return [
|
||
'name' => $name,
|
||
'title' => __($titleKey) !== $titleKey ? __($titleKey) : ($manifest['title'] ?? $name),
|
||
'version' => $manifest['version'] ?? '1.0.0',
|
||
'description' => __($descKey) !== $descKey ? __($descKey) : ($manifest['description'] ?? ''),
|
||
'enabled' => (bool) ($record?->enabled),
|
||
'requires' => $requires,
|
||
'has_docs' => $manager->docsPath($name) !== null,
|
||
'accent' => $accents[$index % count($accents)],
|
||
];
|
||
})->all();
|
||
}
|
||
|
||
protected function getHeaderActions(): array
|
||
{
|
||
return [
|
||
Action::make('sync')
|
||
->label(__('admin.pages.plugins_sync'))
|
||
->action(function (PluginManager $manager): void {
|
||
$manager->syncDiscoveredPlugins();
|
||
$this->reload($manager);
|
||
Notification::make()->title(__('admin.pages.plugins_sync'))->success()->send();
|
||
}),
|
||
];
|
||
}
|
||
}
|