From d9257fdb4f9672525efbde3b10762fc5a14732fa Mon Sep 17 00:00:00 2001 From: Vehikl Date: Thu, 22 May 2025 17:07:49 -0400 Subject: [PATCH] Avatars --- app/Extensions/Avatar/AvatarProvider.php | 51 ++++++++++--------- .../Avatar/AvatarSchemaInterface.php | 14 +++++ .../GravatarSchema.php} | 16 +++--- .../UiAvatarsSchema.php} | 11 ++-- app/Filament/Admin/Pages/Settings.php | 7 ++- app/Models/User.php | 17 ++----- app/Providers/AppServiceProvider.php | 6 --- .../Extensions/AvatarServiceProvider.php | 24 +++++++++ bootstrap/providers.php | 1 + 9 files changed, 87 insertions(+), 60 deletions(-) create mode 100644 app/Extensions/Avatar/AvatarSchemaInterface.php rename app/Extensions/Avatar/{Providers/GravatarProvider.php => Schemas/GravatarSchema.php} (54%) rename app/Extensions/Avatar/{Providers/UiAvatarsProvider.php => Schemas/UiAvatarsSchema.php} (61%) create mode 100644 app/Providers/Extensions/AvatarServiceProvider.php diff --git a/app/Extensions/Avatar/AvatarProvider.php b/app/Extensions/Avatar/AvatarProvider.php index 978c95eba..e983f4452 100644 --- a/app/Extensions/Avatar/AvatarProvider.php +++ b/app/Extensions/Avatar/AvatarProvider.php @@ -3,40 +3,45 @@ namespace App\Extensions\Avatar; use App\Models\User; -use Illuminate\Support\Arr; -use Illuminate\Support\Str; +use Illuminate\Support\Facades\Storage; -abstract class AvatarProvider +class AvatarProvider { - /** - * @var array - */ - protected static array $providers = []; - - public static function getProvider(string $id): ?self - { - return Arr::get(static::$providers, $id); - } + /** @var AvatarSchemaInterface[] */ + private array $providers = []; /** - * @return array + * @return AvatarSchemaInterface[] | AvatarSchemaInterface | null */ - public static function getAll(): array + public function get(?string $id = null): array|AvatarSchemaInterface|null { - return static::$providers; + return $id ? array_get($this->providers, $id) : $this->providers; } - public function __construct() + public function getActiveSchema(): ?AvatarSchemaInterface { - static::$providers[$this->getId()] = $this; + return $this->get(config('panel.filament.avatar-provider')); } - abstract public function getId(): string; - - abstract public function get(User $user): ?string; - - public function getName(): string + public function getAvatarUrl(User $user): ?string { - return Str::title($this->getId()); + if (config('panel.filament.uploadable-avatars')) { + $path = "avatars/$user->id.png"; + + if (Storage::disk('public')->exists($path)) { + return Storage::url($path); + } + } + + return $this->getActiveSchema()?->get($user); + } + + public function register(AvatarSchemaInterface $provider): void + { + if (array_key_exists($provider->getId(), $this->providers)) { + return; + } + + $this->providers[$provider->getId()] = $provider; } } diff --git a/app/Extensions/Avatar/AvatarSchemaInterface.php b/app/Extensions/Avatar/AvatarSchemaInterface.php new file mode 100644 index 000000000..fc1ab9b00 --- /dev/null +++ b/app/Extensions/Avatar/AvatarSchemaInterface.php @@ -0,0 +1,14 @@ +email); } - - public static function register(): self - { - return new self(); - } } diff --git a/app/Extensions/Avatar/Providers/UiAvatarsProvider.php b/app/Extensions/Avatar/Schemas/UiAvatarsSchema.php similarity index 61% rename from app/Extensions/Avatar/Providers/UiAvatarsProvider.php rename to app/Extensions/Avatar/Schemas/UiAvatarsSchema.php index 4ee211cdb..2fe28191c 100644 --- a/app/Extensions/Avatar/Providers/UiAvatarsProvider.php +++ b/app/Extensions/Avatar/Schemas/UiAvatarsSchema.php @@ -1,11 +1,11 @@ |null */ public ?array $data = []; @@ -62,9 +64,10 @@ class Settings extends Page implements HasForms $this->form->fill(); } - public function boot(OAuthProvider $oauthProvider): void + public function boot(OAuthProvider $oauthProvider, AvatarProvider $avatarProvider): void { $this->oauthProvider = $oauthProvider; + $this->avatarProvider = $avatarProvider; } public static function canAccess(): bool @@ -174,7 +177,7 @@ class Settings extends Page implements HasForms Select::make('FILAMENT_AVATAR_PROVIDER') ->label(trans('admin/setting.general.avatar_provider')) ->native(false) - ->options(collect(AvatarProvider::getAll())->mapWithKeys(fn ($provider) => [$provider->getId() => $provider->getName()])) + ->options(collect($this->avatarProvider->get())->mapWithKeys(fn ($provider) => [$provider->getId() => $provider->getName()])) ->selectablePlaceholder(false) ->default(env('FILAMENT_AVATAR_PROVIDER', config('panel.filament.avatar-provider'))), Toggle::make('FILAMENT_UPLOADABLE_AVATARS') diff --git a/app/Models/User.php b/app/Models/User.php index c8d8800b8..b70b40559 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,7 +6,6 @@ use App\Contracts\Validatable; use App\Exceptions\DisplayException; use App\Extensions\Avatar\AvatarProvider; use App\Rules\Username; -use App\Facades\Activity; use App\Traits\HasValidation; use DateTimeZone; use Filament\Models\Contracts\FilamentUser; @@ -18,6 +17,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\App; use Illuminate\Support\Str; use Illuminate\Validation\Rules\In; use Illuminate\Auth\Authenticatable; @@ -32,7 +32,6 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; -use Illuminate\Support\Facades\Storage; use ResourceBundle; use Spatie\Permission\Traits\HasRoles; @@ -393,17 +392,9 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac public function getFilamentAvatarUrl(): ?string { - if (config('panel.filament.uploadable-avatars')) { - $path = "avatars/$this->id.png"; - - if (Storage::disk('public')->exists($path)) { - return Storage::url($path); - } - } - - $provider = AvatarProvider::getProvider(config('panel.filament.avatar-provider')); - - return $provider?->get($this); + return App::call(function (AvatarProvider $provider) { + return $provider->getAvatarUrl($this); + }); } public function canTarget(Model $model): bool diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 963b792e7..9a0721956 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -10,8 +10,6 @@ use App\Checks\NodeVersionsCheck; use App\Checks\PanelVersionCheck; use App\Checks\ScheduleCheck; use App\Checks\UsedDiskSpaceCheck; -use App\Extensions\Avatar\Providers\GravatarProvider; -use App\Extensions\Avatar\Providers\UiAvatarsProvider; use App\Extensions\Captcha\Providers\TurnstileProvider; use App\Models; use App\Services\Helpers\SoftwareVersionService; @@ -97,10 +95,6 @@ class AppServiceProvider extends ServiceProvider // Default Captcha provider TurnstileProvider::register($app); - // Default Avatar providers - GravatarProvider::register(); - UiAvatarsProvider::register(); - FilamentColor::register([ 'danger' => Color::Red, 'gray' => Color::Zinc, diff --git a/app/Providers/Extensions/AvatarServiceProvider.php b/app/Providers/Extensions/AvatarServiceProvider.php new file mode 100644 index 000000000..395e275e9 --- /dev/null +++ b/app/Providers/Extensions/AvatarServiceProvider.php @@ -0,0 +1,24 @@ +app->singleton(AvatarProvider::class, function ($app) { + $provider = new AvatarProvider(); + + // Default Avatar providers + $provider->register(new GravatarSchema()); + $provider->register(new UiAvatarsSchema()); + + return $provider; + }); + } +} diff --git a/bootstrap/providers.php b/bootstrap/providers.php index caf780b48..59ee09abf 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -8,6 +8,7 @@ return [ App\Providers\Filament\AdminPanelProvider::class, App\Providers\Filament\AppPanelProvider::class, App\Providers\Filament\ServerPanelProvider::class, + App\Providers\Extensions\AvatarServiceProvider::class, App\Providers\Extensions\FeatureServiceProvider::class, App\Providers\Extensions\OAuthServiceProvider::class, App\Providers\RouteServiceProvider::class,