WIP not working Feature Singleton

This commit is contained in:
Vehikl 2025-05-08 17:05:23 -04:00
parent e349f3fc58
commit 43345240c5
12 changed files with 86 additions and 125 deletions

View File

@ -2,50 +2,32 @@
namespace App\Extensions\Features; namespace App\Extensions\Features;
use Filament\Actions\Action; use App\Models\Egg;
use Illuminate\Foundation\Application; use Illuminate\Database\Eloquent\Model;
abstract class FeatureProvider class FeatureProvider
{ {
/** /** @var FeatureSchemaInterface[] */
* @var array<string, static> private array $providers = [];
*/
protected static array $providers = [];
/** /** @return FeatureSchemaInterface[] | FeatureSchemaInterface */
* @param string[] $id public function get(?string $id = null): array|FeatureSchemaInterface
* @return self|static[]
*/
public static function getProviders(string|array|null $id = null): array|self
{ {
if (is_array($id)) { return $id ? $this->providers[$id] : $this->providers;
return array_intersect_key(static::$providers, array_flip($id));
}
return $id ? static::$providers[$id] : static::$providers;
} }
protected function __construct(protected Application $app) /** @return FeatureSchemaInterface[] */
public function getAvailableFeatures(Egg $egg): array
{ {
if (array_key_exists($this->getId(), static::$providers)) { return collect($this->providers)->intersect($egg->features)->all();
if (!$this->app->runningUnitTests()) { }
logger()->warning("Tried to create duplicate Feature provider with id '{$this->getId()}'");
}
public function register(FeatureSchemaInterface $provider): void
{
if (array_key_exists($provider->getId(), $this->providers)) {
return; return;
} }
static::$providers[$this->getId()] = $this; $this->providers[$provider->getId()] = $provider;
} }
abstract public function getId(): string;
/**
* A matching subset string (case-insensitive) from the console output
*
* @return array<string>
*/
abstract public function getListeners(): array;
abstract public function getAction(): Action;
} }

View File

@ -0,0 +1,14 @@
<?php
namespace App\Extensions\Features;
use Filament\Actions\Action;
interface FeatureSchemaInterface
{
public function getListeners(): array;
public function getId(): string;
public function getAction(): Action;
}

View File

@ -1,7 +1,8 @@
<?php <?php
namespace App\Extensions\Features; namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Facades\Activity; use App\Facades\Activity;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Server; use App\Models\Server;
@ -13,16 +14,10 @@ use Filament\Facades\Filament;
use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
class GSLToken extends FeatureProvider class GSLTokenSchema implements FeatureSchemaInterface
{ {
public function __construct(protected Application $app)
{
parent::__construct($app);
}
/** @return array<string> */ /** @return array<string> */
public function getListeners(): array public function getListeners(): array
{ {
@ -114,9 +109,4 @@ class GSLToken extends FeatureProvider
} }
}); });
} }
public static function register(Application $app): self
{
return new self($app);
}
} }

View File

@ -1,7 +1,8 @@
<?php <?php
namespace App\Extensions\Features; namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Facades\Activity; use App\Facades\Activity;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Server; use App\Models\Server;
@ -11,15 +12,9 @@ use Filament\Facades\Filament;
use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Illuminate\Foundation\Application;
class JavaVersion extends FeatureProvider class JavaVersionSchema implements FeatureSchemaInterface
{ {
public function __construct(protected Application $app)
{
parent::__construct($app);
}
/** @return array<string> */ /** @return array<string> */
public function getListeners(): array public function getListeners(): array
{ {
@ -89,9 +84,4 @@ class JavaVersion extends FeatureProvider
} }
}); });
} }
public static function register(Application $app): self
{
return new self($app);
}
} }

View File

@ -1,7 +1,8 @@
<?php <?php
namespace App\Extensions\Features; namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Models\Server; use App\Models\Server;
use App\Repositories\Daemon\DaemonFileRepository; use App\Repositories\Daemon\DaemonFileRepository;
use App\Repositories\Daemon\DaemonPowerRepository; use App\Repositories\Daemon\DaemonPowerRepository;
@ -9,17 +10,11 @@ use Exception;
use Filament\Actions\Action; use Filament\Actions\Action;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
class MinecraftEula extends FeatureProvider class MinecraftEulaSchema implements FeatureSchemaInterface
{ {
public function __construct(protected Application $app)
{
parent::__construct($app);
}
/** @return array<string> */ /** @return array<string> */
public function getListeners(): array public function getListeners(): array
{ {
@ -64,9 +59,4 @@ class MinecraftEula extends FeatureProvider
} }
); );
} }
public static function register(Application $app): self
{
return new self($app);
}
} }

View File

@ -1,19 +1,14 @@
<?php <?php
namespace App\Extensions\Features; namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use Filament\Actions\Action; use Filament\Actions\Action;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
class PIDLimit extends FeatureProvider class PIDLimitSchema implements FeatureSchemaInterface
{ {
public function __construct(protected Application $app)
{
parent::__construct($app);
}
/** @return array<string> */ /** @return array<string> */
public function getListeners(): array public function getListeners(): array
{ {
@ -68,9 +63,4 @@ class PIDLimit extends FeatureProvider
->modalCancelActionLabel('Close') ->modalCancelActionLabel('Close')
->action(fn () => null); ->action(fn () => null);
} }
public static function register(Application $app): self
{
return new self($app);
}
} }

View File

@ -1,19 +1,14 @@
<?php <?php
namespace App\Extensions\Features; namespace App\Extensions\Features\Schemas;
use App\Extensions\Features\FeatureSchemaInterface;
use Filament\Actions\Action; use Filament\Actions\Action;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
class SteamDiskSpace extends FeatureProvider class SteamDiskSpaceSchema implements FeatureSchemaInterface
{ {
public function __construct(protected Application $app)
{
parent::__construct($app);
}
/** @return array<string> */ /** @return array<string> */
public function getListeners(): array public function getListeners(): array
{ {
@ -56,9 +51,4 @@ class SteamDiskSpace extends FeatureProvider
->modalCancelActionLabel('Close') ->modalCancelActionLabel('Close')
->action(fn () => null); ->action(fn () => null);
} }
public static function register(Application $app): self
{
return new self($app);
}
} }

View File

@ -6,23 +6,25 @@ use App\Enums\ConsoleWidgetPosition;
use App\Enums\ContainerStatus; use App\Enums\ContainerStatus;
use App\Exceptions\Http\Server\ServerStateConflictException; use App\Exceptions\Http\Server\ServerStateConflictException;
use App\Extensions\Features\FeatureProvider; use App\Extensions\Features\FeatureProvider;
use App\Extensions\Features\FeatureSchemaInterface;
use App\Filament\Server\Widgets\ServerConsole; use App\Filament\Server\Widgets\ServerConsole;
use App\Filament\Server\Widgets\ServerCpuChart; use App\Filament\Server\Widgets\ServerCpuChart;
use App\Filament\Server\Widgets\ServerMemoryChart; use App\Filament\Server\Widgets\ServerMemoryChart;
// use App\Filament\Server\Widgets\ServerNetworkChart;
use App\Filament\Server\Widgets\ServerOverview; use App\Filament\Server\Widgets\ServerOverview;
use App\Livewire\AlertBanner; use App\Livewire\AlertBanner;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Server; use App\Models\Server;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Actions\Action;
use Filament\Pages\Page; use Filament\Pages\Page;
use Filament\Support\Enums\ActionSize; use Filament\Support\Enums\ActionSize;
use Filament\Widgets\Widget; use Filament\Widgets\Widget;
use Filament\Widgets\WidgetConfiguration; use Filament\Widgets\WidgetConfiguration;
use Livewire\Attributes\On; use Livewire\Attributes\On;
// use App\Filament\Server\Widgets\ServerNetworkChart;
class Console extends Page class Console extends Page
{ {
use InteractsWithActions; use InteractsWithActions;
@ -35,6 +37,8 @@ class Console extends Page
public ContainerStatus $status = ContainerStatus::Offline; public ContainerStatus $status = ContainerStatus::Offline;
protected FeatureProvider $featureProvider;
public function mount(): void public function mount(): void
{ {
/** @var Server $server */ /** @var Server $server */
@ -51,12 +55,12 @@ class Console extends Page
} }
} }
public function boot(): void public function boot(FeatureProvider $featureProvider): void
{ {
$this->featureProvider = $featureProvider;
/** @var Server $server */ /** @var Server $server */
$server = Filament::getTenant(); $server = Filament::getTenant();
/** @var FeatureProvider $feature */ foreach ($featureProvider->getAvailableFeatures($server->egg) as $feature) {
foreach ($server->egg->features() as $feature) {
$this->cacheAction($feature->getAction()); $this->cacheAction($feature->getAction());
} }
} }
@ -67,7 +71,7 @@ class Console extends Page
$data = json_decode($data); $data = json_decode($data);
$feature = data_get($data, 'key'); $feature = data_get($data, 'key');
$feature = FeatureProvider::getProviders($feature); $feature = $this->featureProvider->get($feature);
if ($this->getMountedAction()) { if ($this->getMountedAction()) {
return; return;
} }

View File

@ -5,12 +5,11 @@ namespace App\Models;
use App\Contracts\Validatable; use App\Contracts\Validatable;
use App\Exceptions\Service\Egg\HasChildrenException; use App\Exceptions\Service\Egg\HasChildrenException;
use App\Exceptions\Service\HasActiveServersException; use App\Exceptions\Service\HasActiveServersException;
use App\Extensions\Features\FeatureProvider;
use App\Traits\HasValidation; use App\Traits\HasValidation;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str; use Illuminate\Support\Str;
/** /**
@ -160,12 +159,6 @@ class Egg extends Model implements Validatable
}); });
} }
/** @return array<FeatureProvider> */
public function features(): array
{
return FeatureProvider::getProviders($this->features);
}
/** /**
* Returns the install script for the egg; if egg is copying from another * Returns the install script for the egg; if egg is copying from another
* it will return the copied script. * it will return the copied script.

View File

@ -13,11 +13,6 @@ use App\Checks\UsedDiskSpaceCheck;
use App\Extensions\Avatar\Providers\GravatarProvider; use App\Extensions\Avatar\Providers\GravatarProvider;
use App\Extensions\Avatar\Providers\UiAvatarsProvider; use App\Extensions\Avatar\Providers\UiAvatarsProvider;
use App\Extensions\Captcha\Providers\TurnstileProvider; use App\Extensions\Captcha\Providers\TurnstileProvider;
use App\Extensions\Features\GSLToken;
use App\Extensions\Features\JavaVersion;
use App\Extensions\Features\MinecraftEula;
use App\Extensions\Features\PIDLimit;
use App\Extensions\Features\SteamDiskSpace;
use App\Models; use App\Models;
use App\Services\Helpers\SoftwareVersionService; use App\Services\Helpers\SoftwareVersionService;
use Dedoc\Scramble\Scramble; use Dedoc\Scramble\Scramble;
@ -105,13 +100,6 @@ class AppServiceProvider extends ServiceProvider
GravatarProvider::register(); GravatarProvider::register();
UiAvatarsProvider::register(); UiAvatarsProvider::register();
// Default Feature providers
GSLToken::register($app);
JavaVersion::register($app);
MinecraftEula::register($app);
PIDLimit::register($app);
SteamDiskSpace::register($app);
FilamentColor::register([ FilamentColor::register([
'danger' => Color::Red, 'danger' => Color::Red,
'gray' => Color::Zinc, 'gray' => Color::Zinc,

View File

@ -0,0 +1,29 @@
<?php
namespace App\Providers\Extensions;
use App\Extensions\Features\FeatureProvider;
use App\Extensions\Features\Schemas\GSLTokenSchema;
use App\Extensions\Features\Schemas\JavaVersionSchema;
use App\Extensions\Features\Schemas\MinecraftEulaSchema;
use App\Extensions\Features\Schemas\PIDLimitSchema;
use App\Extensions\Features\Schemas\SteamDiskSpaceSchema;
use Illuminate\Support\ServiceProvider;
class FeatureServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(FeatureProvider::class, function ($app) {
$provider = new FeatureProvider();
$provider->register(new GSLTokenSchema());
$provider->register(new JavaVersionSchema());
$provider->register(new MinecraftEulaSchema());
$provider->register(new PIDLimitSchema());
$provider->register(new SteamDiskSpaceSchema());
return $provider;
});
}
}

View File

@ -8,6 +8,7 @@ return [
App\Providers\Filament\AdminPanelProvider::class, App\Providers\Filament\AdminPanelProvider::class,
App\Providers\Filament\AppPanelProvider::class, App\Providers\Filament\AppPanelProvider::class,
App\Providers\Filament\ServerPanelProvider::class, App\Providers\Filament\ServerPanelProvider::class,
App\Providers\Extensions\FeatureServiceProvider::class,
App\Providers\Extensions\OAuthServiceProvider::class, App\Providers\Extensions\OAuthServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
SocialiteProviders\Manager\ServiceProvider::class, SocialiteProviders\Manager\ServiceProvider::class,