- {{ $this->comment->commentator }}
+ {{ $this->getCommentator() }}
diff --git a/resources/views/livewire/comments.blade.php b/resources/views/livewire/comments.blade.php
index 8444736..09abd1f 100644
--- a/resources/views/livewire/comments.blade.php
+++ b/resources/views/livewire/comments.blade.php
@@ -17,7 +17,8 @@
@foreach($this->comments as $comment)
+ :comment="$comment"
+ />
@endforeach
diff --git a/src/Concerns/HasComments.php b/src/Concerns/HasComments.php
index 707dc3b..2233269 100644
--- a/src/Concerns/HasComments.php
+++ b/src/Concerns/HasComments.php
@@ -5,10 +5,15 @@
use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedComments;
use Exception;
+use FilamentTiptapEditor\Data\MentionItem;
+use Illuminate\Contracts\Auth\Authenticatable;
+use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Collection;
+use function auth;
+
/**
* @mixin Model
*/
@@ -97,7 +102,7 @@ public function editComment(Comment $comment, string $body, ?string $name = null
app(NestedComments::class)->setGuestName($name);
}
- if (\auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
+ if (auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
throw new Exception('You are not authorized to edit this comment.');
}
@@ -123,7 +128,7 @@ public function deleteComment(Comment $comment): ?bool
throw new Exception('You must be logged in to edit your comment.');
}
- if (\auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
+ if (auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
throw new Exception('You are not authorized to edit this comment.');
}
@@ -136,4 +141,50 @@ public function deleteComment(Comment $comment): ?bool
return $comment->delete();
}
+
+ final public function getUserNameUsing(Comment $comment): string
+ {
+ return $this->getUserName($comment->getAttribute('user'));
+ }
+
+ final public function getUserAvatarUsing(Comment $comment): ?string
+ {
+ $user = $comment->user ?? $comment->guest_name ?? 'Guest';
+
+ return $this->getUserAvatar($user);
+ }
+
+ public function getUserName(Model | Authenticatable | null $user): string
+ {
+ return app(NestedComments::class)->getUserName($user);
+ }
+
+ public function getUserAvatar(Model | Authenticatable | string | null $user): ?string
+ {
+ return app(NestedComments::class)->getDefaultUserAvatar($user);
+ }
+
+ /**
+ * @return array
+ */
+ public function getMentionsUsing(string $query): array
+ {
+ return $this->getMentionsQuery($query)
+// ->where('username', 'like', "%{$query}%")
+ ->take(50)
+ ->get()
+ ->map(function ($user) {
+ return new MentionItem(
+ id: $user->getKey(),
+ label: $this->getUserName($user),
+ image: $this->getUserAvatar($user),
+ roundedImage: true,
+ );
+ })->toArray();
+ }
+
+ public function getMentionsQuery(string $query): Builder
+ {
+ return app(NestedComments::class)->getUserMentionsQuery($query);
+ }
}
diff --git a/src/Filament/Infolists/CommentCardEntry.php b/src/Filament/Infolists/CommentCardEntry.php
new file mode 100644
index 0000000..1d8d6bf
--- /dev/null
+++ b/src/Filament/Infolists/CommentCardEntry.php
@@ -0,0 +1,59 @@
+ 'full'];
+
+ public static function make(?string $name = null): static
+ {
+ $name = $name ?? 'body';
+
+ return parent::make($name); // TODO: Change the autogenerated stub
+ }
+
+ public function getUserNameUsing(Closure | string | null $callback = null): static
+ {
+ $this->userNameUsingClosure = $callback;
+
+ return $this;
+ }
+
+ public function getUserAvatarUsing(Closure | string | null $callback = null): static
+ {
+ $this->userAvatarUsingClosure = $callback;
+
+ return $this;
+ }
+
+ public function evaluateUserAvatar(): ?string
+ {
+ return $this->evaluate($this->userAvatarUsingClosure
+ ?? fn (Comment | Model $record) => app(NestedComments::class)
+ ->getDefaultUserAvatar($record->getAttribute('user')
+ ?? $record->getAttribute('guest_name') ?? 'Guest'));
+ }
+
+ public function evaluateUserName(): ?string
+ {
+ return $this->evaluate($this->userNameUsingClosure
+ ?? fn (Comment | Model | null $record) => $record?->getAttribute('user')?->getAttribute('name')
+ ?? $record->getAttribute('guest_name'));
+ }
+}
diff --git a/src/Livewire/AddComment.php b/src/Livewire/AddComment.php
index 1a4fce2..6a4ebce 100644
--- a/src/Livewire/AddComment.php
+++ b/src/Livewire/AddComment.php
@@ -2,9 +2,11 @@
namespace Coolsam\NestedComments\Livewire;
+use Coolsam\NestedComments\Concerns\HasComments;
use Coolsam\NestedComments\Models\Comment;
-use Coolsam\NestedComments\NestedComments;
use Coolsam\NestedComments\NestedCommentsServiceProvider;
+use Error;
+use Exception;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
@@ -30,10 +32,10 @@ class AddComment extends Component implements HasForms
public ?Comment $replyTo = null;
- public function mount(?Model $commentable = null, ?Comment $replyTo = null): void
+ public function mount(?Model $commentable, ?Comment $replyTo): void
{
if (! $commentable) {
- throw new \Error('The $commentable property is required.');
+ throw new Error('The $commentable property is required.');
}
$this->commentable = $commentable;
$this->replyTo = $replyTo;
@@ -43,7 +45,7 @@ public function mount(?Model $commentable = null, ?Comment $replyTo = null): voi
public function getCommentable(): Model
{
if (! $this->commentable) {
- throw new \Error('The $commentable property is required.');
+ throw new Error('The $commentable property is required.');
}
return $this->commentable;
@@ -51,7 +53,12 @@ public function getCommentable(): Model
public function form(Form $form): Form
{
- $mentionsClosure = config('nested-comments.closures.getMentionsUsing', fn (string $query, Model $commentable) => app(NestedComments::class)->getUserMentions($query));
+ /**
+ * @var Model|HasComments $commentable
+ *
+ * @phpstan-ignore-next-line
+ */
+ $commentable = $this->getCommentable();
return $form
->schema([
@@ -61,7 +68,11 @@ public function form(Form $form): Form
->extraInputAttributes(['style' => 'min-height: 12rem;'])
->mentionItemsPlaceholder(config('nested-comments.mentions.items-placeholder', __('Search users by name or email address')))
->emptyMentionItemsMessage(config('nested-comments.mentions.empty-items-message', __('No users found')))
- ->getMentionItemsUsing(fn (string $query) => $mentionsClosure($query, $this->getCommentable()))
+ /**
+ * @phpstan-ignore-next-line
+ */
+ ->getMentionItemsUsing(fn (string $query) => $commentable->getMentionsUsing($query))
+ ->maxContentWidth('full')
->required()
->autofocus(),
])
@@ -70,12 +81,17 @@ public function form(Form $form): Form
}
/**
- * @throws \Exception
+ * @throws Exception
*/
public function create(): void
{
$data = $this->form->getState();
+ /**
+ * @var Model|HasComments $commentable
+ *
+ * @phpstan-ignore-next-line
+ */
$commentable = $this->getCommentable();
/**
diff --git a/src/Livewire/CommentCard.php b/src/Livewire/CommentCard.php
index d566b6e..873a6f5 100644
--- a/src/Livewire/CommentCard.php
+++ b/src/Livewire/CommentCard.php
@@ -4,14 +4,22 @@
use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedCommentsServiceProvider;
+use Error;
+use Filament\Support\Concerns\EvaluatesClosures;
use Livewire\Component;
class CommentCard extends Component
{
+ use EvaluatesClosures;
+
public ?Comment $comment = null;
public bool $showReplies = false;
+ public ?string $userAvatar = null;
+
+ public ?string $userName = null;
+
protected $listeners = [
'refresh' => 'refreshReplies',
];
@@ -19,7 +27,7 @@ class CommentCard extends Component
public function mount(?Comment $comment = null): void
{
if (! $comment) {
- throw new \Error('The $comment property is required.');
+ throw new Error('The $comment property is required.');
}
$this->comment = $comment;
@@ -48,6 +56,21 @@ public function getAvatar()
return '';
}
- return call_user_func(config('nested-comments.closures.getUserAvatarUsing'), $this->comment->commentator);
+ /**
+ * @phpstan-ignore-next-line
+ */
+ return $this->comment->commentable?->getUserAvatarUsing($this->comment);
+ }
+
+ public function getCommentator(): string
+ {
+ if (! $this->comment) {
+ return '';
+ }
+
+ /**
+ * @phpstan-ignore-next-line
+ */
+ return $this->comment->commentable?->getUserNameUsing($this->comment);
}
}
diff --git a/src/Livewire/Comments.php b/src/Livewire/Comments.php
index dfbbe05..e67dd33 100644
--- a/src/Livewire/Comments.php
+++ b/src/Livewire/Comments.php
@@ -29,6 +29,7 @@ class Comments extends Component
public function mount(): void
{
$this->comments = collect();
+
if (! $this->record) {
throw new \Error('Record model (Commentable) is required');
}
diff --git a/src/Models/Comment.php b/src/Models/Comment.php
index 339e20e..b163d44 100644
--- a/src/Models/Comment.php
+++ b/src/Models/Comment.php
@@ -27,10 +27,6 @@ public function user(): BelongsTo
public function getCommentatorAttribute()
{
- if ($this->user) {
- return call_user_func(config('nested-comments.closures.getUserNameUsing'), $this->user);
- }
-
return $this->getAttribute('guest_name');
}
diff --git a/src/NestedComments.php b/src/NestedComments.php
index 14df329..cac52eb 100644
--- a/src/NestedComments.php
+++ b/src/NestedComments.php
@@ -25,13 +25,15 @@ public function getGuestId(): ?string
return session(self::GUEST_ID_FIELD);
}
+ public function getUserName(Authenticatable | Model | null $user): string
+ {
+ return $user?->getAttribute('name') ?? $user?->getAttribute('guest_name') ?? 'Guest';
+ }
+
public function getGuestName(): string
{
if (Auth::check()) {
- return call_user_func(config(
- 'nested-comments.closures.getUserNameUsing',
- fn (Authenticatable | Model $user) => $user->getAttribute('name')
- ), Auth::user());
+ return $this->getUserName(Auth::user());
}
return session(self::GUEST_NAME_FIELD, 'Guest');
@@ -66,7 +68,7 @@ public function classHasTrait(object | string $classInstance, string $trait): bo
return in_array($trait, class_uses_recursive($classInstance));
}
- public function geDefaultUserAvatar(Authenticatable | Model | string $user)
+ public function getDefaultUserAvatar(Authenticatable | Model | string $user)
{
if (is_string($user)) {
$name = str($user)
@@ -83,25 +85,30 @@ public function geDefaultUserAvatar(Authenticatable | Model | string $user)
}
}
- public function getUserMentions(string $query)
+ public function getUserMentions(string $query): array
{
- $userModel = config('nested-comments.models.user', config('auth.providers.users.model', 'App\\Models\\User'));
-
- return $userModel::query()
- ->where('name', 'like', "%{$query}%")
- ->orWhere('email', 'like', "%{$query}%")
+ return $this->getUserMentionsQuery($query)
->take(20)
->get()
->map(function ($user) {
return new MentionItem(
id: $user->getKey(),
- label: call_user_func(config('nested-comments.closures.getUserNameUsing'), $user),
- image: call_user_func(config('nested-comments.closures.getUserAvatarUsing'), $user),
+ label: $this->getUserName($user),
+ image: $this->getDefaultUserAvatar($user),
roundedImage: true,
);
})->toArray();
}
+ public function getUserMentionsQuery(string $query): \Illuminate\Database\Eloquent\Builder
+ {
+ $userModel = config('nested-comments.models.user', config('auth.providers.users.model', 'App\\Models\\User'));
+
+ return $userModel::query()
+ ->where('name', 'like', "%{$query}%")
+ ->orWhere('email', 'like', "%{$query}%");
+ }
+
public function getCurrentThreadUsers(string $searchQuery, $commentable): mixed
{
$userModel = config('nested-comments.models.user', config('auth.providers.users.model', 'App\\Models\\User'));
@@ -122,8 +129,8 @@ public function getCurrentThreadUsers(string $searchQuery, $commentable): mixed
->map(function ($user) {
return new MentionItem(
id: $user->getKey(),
- label: call_user_func(config('nested-comments.closures.getUserNameUsing'), $user),
- image: call_user_func(config('nested-comments.closures.getUserAvatarUsing'), $user),
+ label: $this->getUserName($user),
+ image: $this->getDefaultUserAvatar($user),
roundedImage: true,
);
})->toArray();