292 lines
10 KiB
PHP
292 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\Admin\Pages;
|
|
|
|
use App\Services\Agent\AgentClient;
|
|
use BackedEnum;
|
|
use Filament\Actions\Action;
|
|
use Filament\Actions\Concerns\InteractsWithActions;
|
|
use Filament\Actions\Contracts\HasActions;
|
|
use Filament\Forms\Concerns\InteractsWithForms;
|
|
use Filament\Forms\Contracts\HasForms;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Schemas\Components\Grid;
|
|
use Filament\Schemas\Components\Section;
|
|
use Filament\Schemas\Schema;
|
|
use Filament\Tables\Columns\IconColumn;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Concerns\InteractsWithTable;
|
|
use Filament\Tables\Contracts\HasTable;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Contracts\Support\Htmlable;
|
|
|
|
class PhpManager extends Page implements HasActions, HasForms, HasTable
|
|
{
|
|
use InteractsWithActions;
|
|
use InteractsWithForms;
|
|
use InteractsWithTable;
|
|
|
|
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-code-bracket';
|
|
|
|
protected static ?int $navigationSort = 6;
|
|
|
|
protected static ?string $slug = 'php-manager';
|
|
|
|
protected string $view = 'filament.admin.pages.php-manager';
|
|
|
|
public array $installedVersions = [];
|
|
|
|
public array $availableVersions = [];
|
|
|
|
public ?string $defaultVersion = null;
|
|
|
|
public static function getNavigationLabel(): string
|
|
{
|
|
return __('PHP Manager');
|
|
}
|
|
|
|
public function getTitle(): string|Htmlable
|
|
{
|
|
return __('PHP Manager');
|
|
}
|
|
|
|
protected function getAgent(): AgentClient
|
|
{
|
|
return new AgentClient;
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->loadPhpVersions();
|
|
}
|
|
|
|
public function loadPhpVersions(): void
|
|
{
|
|
$result = $this->getAgent()->send('php.list_versions', []);
|
|
|
|
if ($result['success'] ?? false) {
|
|
$this->installedVersions = $result['versions'] ?? [];
|
|
$this->defaultVersion = $result['default'] ?? null;
|
|
} else {
|
|
$this->installedVersions = [];
|
|
$this->defaultVersion = null;
|
|
}
|
|
|
|
$allVersions = ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'];
|
|
$installed = array_column($this->installedVersions, 'version');
|
|
$this->availableVersions = array_diff($allVersions, $installed);
|
|
}
|
|
|
|
protected function getForms(): array
|
|
{
|
|
return ['statsForm'];
|
|
}
|
|
|
|
public function statsForm(Schema $schema): Schema
|
|
{
|
|
return $schema->schema([
|
|
Section::make(__('Warning: Modifying PHP versions can cause server downtime'))
|
|
->description(__('Uninstalling PHP versions may break websites that depend on them. Ensure you understand the impact before making changes.'))
|
|
->icon('heroicon-o-exclamation-triangle')
|
|
->iconColor('warning')
|
|
->collapsed(false)
|
|
->compact(),
|
|
Grid::make(['default' => 1, 'sm' => 2])
|
|
->schema([
|
|
Section::make('PHP '.($this->defaultVersion ?? __('N/A')))
|
|
->description(__('Default CLI Version'))
|
|
->icon('heroicon-o-command-line')
|
|
->iconColor('primary'),
|
|
Section::make((string) count($this->installedVersions))
|
|
->description(__('Installed Versions'))
|
|
->icon('heroicon-o-squares-2x2')
|
|
->iconColor('success'),
|
|
]),
|
|
]);
|
|
}
|
|
|
|
public function getAllVersionsData(): array
|
|
{
|
|
$allVersions = ['8.4', '8.3', '8.2', '8.1', '8.0', '7.4'];
|
|
$installedMap = [];
|
|
|
|
foreach ($this->installedVersions as $php) {
|
|
$installedMap[$php['version']] = $php;
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($allVersions as $version) {
|
|
$installed = isset($installedMap[$version]);
|
|
$result[] = [
|
|
'version' => $version,
|
|
'installed' => $installed,
|
|
'fpm_status' => $installed ? ($installedMap[$version]['fpm_status'] ?? 'inactive') : null,
|
|
'is_default' => $version === $this->defaultVersion,
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->records(fn () => $this->getAllVersionsData())
|
|
->columns([
|
|
TextColumn::make('version')
|
|
->label(__('PHP Version'))
|
|
->formatStateUsing(fn (string $state): string => 'PHP '.$state)
|
|
->icon('heroicon-o-code-bracket')
|
|
->weight('bold')
|
|
->sortable(),
|
|
TextColumn::make('installed')
|
|
->label(__('Status'))
|
|
->badge()
|
|
->formatStateUsing(fn (bool $state): string => $state ? __('Installed') : __('Not Installed'))
|
|
->color(fn (bool $state): string => $state ? 'success' : 'gray'),
|
|
IconColumn::make('is_default')
|
|
->label(__('Default'))
|
|
->boolean()
|
|
->trueIcon('heroicon-o-check-badge')
|
|
->falseIcon('heroicon-o-minus')
|
|
->trueColor('info')
|
|
->falseColor('gray'),
|
|
TextColumn::make('fpm_status')
|
|
->label(__('FPM'))
|
|
->badge()
|
|
->formatStateUsing(fn (?string $state): string => $state === 'active' ? __('Running') : ($state ? __('Stopped') : '-'))
|
|
->color(fn (?string $state): string => $state === 'active' ? 'success' : ($state ? 'danger' : 'gray')),
|
|
])
|
|
->recordActions([
|
|
Action::make('install')
|
|
->label(__('Install'))
|
|
->icon('heroicon-o-arrow-down-tray')
|
|
->color('primary')
|
|
->size('sm')
|
|
->visible(fn (array $record): bool => ! $record['installed'])
|
|
->action(fn (array $record) => $this->installPhp($record['version'])),
|
|
Action::make('reload')
|
|
->label(__('Reload'))
|
|
->icon('heroicon-o-arrow-path')
|
|
->color('warning')
|
|
->size('sm')
|
|
->visible(fn (array $record): bool => $record['installed'])
|
|
->requiresConfirmation()
|
|
->modalHeading(__('Reload PHP-FPM'))
|
|
->modalDescription(fn (array $record): string => __('Are you sure you want to reload PHP :version FPM?', ['version' => $record['version']]))
|
|
->action(fn (array $record) => $this->reloadFpm($record['version'])),
|
|
Action::make('uninstall')
|
|
->label(__('Uninstall'))
|
|
->icon('heroicon-o-trash')
|
|
->color('danger')
|
|
->size('sm')
|
|
->visible(fn (array $record): bool => $record['installed'] && ! $record['is_default'])
|
|
->action(fn (array $record) => $this->uninstallPhp($record['version'])),
|
|
])
|
|
->heading(__('PHP Versions'))
|
|
->description(__('Install, manage and configure PHP versions'))
|
|
->striped()
|
|
->poll('30s');
|
|
}
|
|
|
|
public function installPhp(string $version): void
|
|
{
|
|
$result = $this->getAgent()->send('php.install', ['version' => $version]);
|
|
|
|
if ($result['success'] ?? false) {
|
|
$this->loadPhpVersions();
|
|
$this->resetTable();
|
|
Notification::make()
|
|
->title(__('PHP :version installed successfully!', ['version' => $version]))
|
|
->success()
|
|
->send();
|
|
} else {
|
|
Notification::make()
|
|
->title(__('Failed to install PHP :version', ['version' => $version]))
|
|
->body($result['error'] ?? __('Unknown error'))
|
|
->danger()
|
|
->send();
|
|
}
|
|
}
|
|
|
|
public function uninstallPhp(string $version): void
|
|
{
|
|
if ($version === $this->defaultVersion) {
|
|
Notification::make()
|
|
->title(__('Cannot uninstall default PHP version'))
|
|
->body(__('Please set a different PHP version as default first'))
|
|
->danger()
|
|
->send();
|
|
|
|
return;
|
|
}
|
|
|
|
$result = $this->getAgent()->send('php.uninstall', ['version' => $version]);
|
|
|
|
if ($result['success'] ?? false) {
|
|
$this->loadPhpVersions();
|
|
$this->resetTable();
|
|
Notification::make()
|
|
->title(__('PHP :version uninstalled successfully!', ['version' => $version]))
|
|
->success()
|
|
->send();
|
|
} else {
|
|
Notification::make()
|
|
->title(__('Failed to uninstall PHP :version', ['version' => $version]))
|
|
->body($result['error'] ?? __('Unknown error'))
|
|
->danger()
|
|
->send();
|
|
}
|
|
}
|
|
|
|
public function setDefaultPhp(string $version): void
|
|
{
|
|
$result = $this->getAgent()->send('php.set_default', ['version' => $version]);
|
|
|
|
if ($result['success'] ?? false) {
|
|
$this->defaultVersion = $version;
|
|
$this->loadPhpVersions();
|
|
$this->resetTable();
|
|
Notification::make()
|
|
->title(__('PHP :version set as default', ['version' => $version]))
|
|
->success()
|
|
->send();
|
|
} else {
|
|
Notification::make()
|
|
->title(__('Failed to set default PHP version'))
|
|
->body($result['error'] ?? __('Unknown error'))
|
|
->danger()
|
|
->send();
|
|
}
|
|
}
|
|
|
|
public function reloadFpm(string $version): void
|
|
{
|
|
$result = $this->getAgent()->send('php.reload_fpm', ['version' => $version]);
|
|
|
|
if ($result['success'] ?? false) {
|
|
$this->loadPhpVersions();
|
|
$this->resetTable();
|
|
Notification::make()
|
|
->title(__('PHP :version FPM reloaded', ['version' => $version]))
|
|
->success()
|
|
->send();
|
|
} else {
|
|
Notification::make()
|
|
->title(__('Failed to reload PHP-FPM'))
|
|
->body($result['error'] ?? __('Unknown error'))
|
|
->danger()
|
|
->send();
|
|
}
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
];
|
|
}
|
|
}
|