diff --git a/README.md b/README.md index 354711c..a3c1cf1 100644 --- a/README.md +++ b/README.md @@ -396,6 +396,20 @@ class User extends Authenticatable implements Commenter, HasName, HasAvatar } ``` +If your users do not implement `HasAvatar`, Commentions will consult an avatar provider before falling back to `ui-avatars.com`. By default it uses the current Filament panel's default provider (set via `Panel::defaultAvatarProvider(...)`). To force a specific provider regardless of panel context, set the `avatar_provider` config key: + +```php +// config/commentions.php +use Filament\AvatarProviders\GravatarProvider; + +return [ + // ... + 'avatar_provider' => GravatarProvider::class, +]; +``` + +Any class exposing a `get(Model|Authenticatable $user): string` method works. + ### Customizing TipTap Editor Styles You can customize the TipTap editor CSS classes used using the `Config` class. diff --git a/config/commentions.php b/config/commentions.php index 4267451..6a9a13a 100644 --- a/config/commentions.php +++ b/config/commentions.php @@ -46,6 +46,23 @@ 'allowed' => ['👍', '❤️', '😂', '😮', '😢', '🤔'], ], + /* + |-------------------------------------------------------------------------- + | Avatar provider + |-------------------------------------------------------------------------- + | + | Class name of a Filament-compatible avatar provider used to resolve a + | URL for the comment author when the user does not implement HasAvatar. + | Must expose a `get(Model|Authenticatable $user): string` method. + | Examples: Filament\AvatarProviders\UiAvatarsProvider, + | Filament\AvatarProviders\GravatarProvider. + | + | When null, Commentions falls back to the active Filament panel's + | default avatar provider (if any), and finally to ui-avatars.com. + | + */ + 'avatar_provider' => null, + /* |-------------------------------------------------------------------------- | Subscriptions diff --git a/src/Comment.php b/src/Comment.php index 91eca58..abab6b0 100644 --- a/src/Comment.php +++ b/src/Comment.php @@ -6,6 +6,7 @@ use Carbon\CarbonInterface; use Closure; use DateTime; +use Filament\Facades\Filament; use Filament\Models\Contracts\HasAvatar; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -121,14 +122,18 @@ public function getAuthorName(): string public function getAuthorAvatar(): string { - $avatar = null; - if ($this->author instanceof HasAvatar) { $avatar = $this->author->getFilamentAvatarUrl(); + + if (! is_null($avatar)) { + return $avatar; + } } - if (! is_null($avatar)) { - return $avatar; + $providerAvatar = $this->resolveAvatarFromProvider(); + + if (! is_null($providerAvatar)) { + return $providerAvatar; } $name = str(Manager::getName($this->author)) @@ -183,6 +188,31 @@ public function getContentHash(): string ])); } + protected function resolveAvatarFromProvider(): ?string + { + $providerClass = Config::getAvatarProvider(); + + if ($providerClass === null) { + try { + if (Filament::getCurrentPanel() !== null) { + $providerClass = Filament::getDefaultAvatarProvider(); + } + } catch (\Throwable) { + return null; + } + } + + if ($providerClass === null) { + return null; + } + + try { + return app($providerClass)->get($this->author); + } catch (\Throwable) { + return null; + } + } + protected static function newFactory() { return CommentFactory::new(); diff --git a/src/Config.php b/src/Config.php index 052a2e2..336d169 100644 --- a/src/Config.php +++ b/src/Config.php @@ -82,6 +82,11 @@ public static function getAllowedReactions(): array return config('commentions.reactions.allowed', ['👍']); } + public static function getAvatarProvider(): ?string + { + return config('commentions.avatar_provider'); + } + public static function resolveTipTapCssClassesUsing(Closure $callback): void { static::$resolveTipTapCssClasses = $callback; diff --git a/tests/AvatarProviderTest.php b/tests/AvatarProviderTest.php new file mode 100644 index 0000000..9bf86db --- /dev/null +++ b/tests/AvatarProviderTest.php @@ -0,0 +1,28 @@ +set('commentions.avatar_provider', null); + + $user = User::factory()->create(['name' => 'Jane Doe']); + $post = Post::factory()->create(); + $comment = CommentModel::factory()->author($user)->commentable($post)->create(); + + expect($comment->getAuthorAvatar()) + ->toStartWith('https://ui-avatars.com/api/?'); +}); + +test('uses configured avatar provider when set', function () { + config()->set('commentions.avatar_provider', StubAvatarProvider::class); + + $user = User::factory()->create(['name' => 'Jane Doe']); + $post = Post::factory()->create(); + $comment = CommentModel::factory()->author($user)->commentable($post)->create(); + + expect($comment->getAuthorAvatar()) + ->toBe('https://stub.test/avatar/Jane+Doe'); +}); diff --git a/tests/Models/StubAvatarProvider.php b/tests/Models/StubAvatarProvider.php new file mode 100644 index 0000000..7a13da3 --- /dev/null +++ b/tests/Models/StubAvatarProvider.php @@ -0,0 +1,14 @@ +name); + } +}