Files
jabali-panel/app/Filament/Jabali/Pages/ImageOptimization.php
2026-01-28 04:19:30 +02:00

156 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Filament\Jabali\Pages;
use App\Models\Domain;
use App\Services\Agent\AgentClient;
use BackedEnum;
use Exception;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Facades\Auth;
class ImageOptimization extends Page implements HasActions, HasForms
{
use InteractsWithActions;
use InteractsWithForms;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-photo';
protected static ?int $navigationSort = 21;
protected static ?string $slug = 'image-optimization';
protected string $view = 'filament.jabali.pages.image-optimization';
protected ?AgentClient $agent = null;
public array $imageFormData = [];
public function getTitle(): string|Htmlable
{
return __('Image Optimization');
}
public static function getNavigationLabel(): string
{
return __('Image Optimization');
}
protected function getAgent(): AgentClient
{
if ($this->agent === null) {
$this->agent = new AgentClient;
}
return $this->agent;
}
protected function getUsername(): string
{
return Auth::user()->username;
}
protected function getDomainOptions(): array
{
return Domain::query()
->where('user_id', Auth::id())
->orderBy('domain')
->pluck('domain', 'id')
->toArray();
}
protected function getForms(): array
{
return ['imageForm'];
}
public function imageForm(Schema $schema): Schema
{
return $schema
->statePath('imageFormData')
->schema([
Section::make(__('Optimization Settings'))
->schema([
Select::make('domain_id')
->label(__('Domain'))
->options($this->getDomainOptions())
->searchable()
->required(),
TextInput::make('path')
->label(__('Custom Path (optional)'))
->helperText(__('Leave empty to optimize the selected domain root')),
Toggle::make('convert_webp')
->label(__('Generate WebP copies'))
->default(false),
TextInput::make('quality')
->label(__('Quality (40-95)'))
->numeric()
->default(82),
])
->columns(2),
]);
}
public function runOptimization(): void
{
$data = $this->imageForm->getState();
$domainId = $data['domain_id'] ?? null;
if (! $domainId) {
Notification::make()->title(__('Select a domain'))->danger()->send();
return;
}
$domain = Domain::where('id', $domainId)->where('user_id', Auth::id())->first();
if (! $domain) {
Notification::make()->title(__('Domain not found'))->danger()->send();
return;
}
$path = trim((string) ($data['path'] ?? ''));
if ($path === '') {
$path = $domain->document_root;
}
try {
$result = $this->getAgent()->imageOptimize(
$this->getUsername(),
$path,
(bool) ($data['convert_webp'] ?? false),
(int) ($data['quality'] ?? 82)
);
if ($result['success'] ?? false) {
$optimized = $result['optimized'] ?? [];
$message = __('Optimization complete');
if (! empty($optimized)) {
$message .= ' · JPG: '.($optimized['jpg'] ?? 0).', PNG: '.($optimized['png'] ?? 0).', WebP: '.($optimized['webp'] ?? 0);
}
Notification::make()->title($message)->success()->send();
return;
}
Notification::make()->title(__('Optimization failed'))->body($result['error'] ?? '')->danger()->send();
} catch (Exception $e) {
Notification::make()->title(__('Optimization failed'))->body($e->getMessage())->danger()->send();
}
}
}