This commit is contained in:
Vehikl 2025-05-22 17:07:49 -04:00
parent 1dc1b13e8e
commit d9257fdb4f
9 changed files with 87 additions and 60 deletions

View File

@ -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<string, static>
*/
protected static array $providers = [];
public static function getProvider(string $id): ?self
{
return Arr::get(static::$providers, $id);
}
/** @var AvatarSchemaInterface[] */
private array $providers = [];
/**
* @return array<string, static>
* @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;
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace App\Extensions\Avatar;
use App\Models\User;
interface AvatarSchemaInterface
{
public function getId(): string;
public function getName(): string;
public function get(User $user): ?string;
}

View File

@ -1,24 +1,24 @@
<?php
namespace App\Extensions\Avatar\Providers;
namespace App\Extensions\Avatar\Schemas;
use App\Extensions\Avatar\AvatarProvider;
use App\Extensions\Avatar\AvatarSchemaInterface;
use App\Models\User;
class GravatarProvider extends AvatarProvider
class GravatarSchema implements AvatarSchemaInterface
{
public function getId(): string
{
return 'gravatar';
}
public function getName(): string
{
return 'Gravatar';
}
public function get(User $user): string
{
return 'https://gravatar.com/avatar/' . md5($user->email);
}
public static function register(): self
{
return new self();
}
}

View File

@ -1,11 +1,11 @@
<?php
namespace App\Extensions\Avatar\Providers;
namespace App\Extensions\Avatar\Schemas;
use App\Extensions\Avatar\AvatarProvider;
use App\Extensions\Avatar\AvatarSchemaInterface;
use App\Models\User;
class UiAvatarsProvider extends AvatarProvider
class UiAvatarsSchema implements AvatarSchemaInterface
{
public function getId(): string
{
@ -22,9 +22,4 @@ class UiAvatarsProvider extends AvatarProvider
// UI Avatars is the default of filament so just return null here
return null;
}
public static function register(): self
{
return new self();
}
}

View File

@ -54,6 +54,8 @@ class Settings extends Page implements HasForms
protected OAuthProvider $oauthProvider;
protected AvatarProvider $avatarProvider;
/** @var array<mixed>|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')

View File

@ -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

View File

@ -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,

View File

@ -0,0 +1,24 @@
<?php
namespace App\Providers\Extensions;
use App\Extensions\Avatar\AvatarProvider;
use App\Extensions\Avatar\Schemas\GravatarSchema;
use App\Extensions\Avatar\Schemas\UiAvatarsSchema;
use Illuminate\Support\ServiceProvider;
class AvatarServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(AvatarProvider::class, function ($app) {
$provider = new AvatarProvider();
// Default Avatar providers
$provider->register(new GravatarSchema());
$provider->register(new UiAvatarsSchema());
return $provider;
});
}
}

View File

@ -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,