refactor: rename for Laravel conventions and better DX

- Rename IsCommenter trait to CanComment, Commenter interface to Commentator
- Move models to Models/ namespace (Comment, Reaction, Attachment, Subscription)
- Rename user_type/user_id polymorphic columns to commenter_type/commenter_id
- Rename Config class to CommentsConfig, update config key tables->table_names
- Rename getCommentName() to getCommentDisplayName() on commentator models
- Add column_names config section for commenter morph customization
- Add table_names config with all 5 tables individually configurable
- Expand translation file with structured i18n groups
- Update all Blade views, Livewire components, events, listeners, and tests
This commit is contained in:
manukminasyan
2026-03-27 14:53:12 +04:00
parent 43b66f60f3
commit fd5bc5271b
62 changed files with 733 additions and 653 deletions

View File

@@ -5,9 +5,10 @@ namespace Relaticle\Comments;
use App\Models\User;
use Closure;
use Relaticle\Comments\Mentions\DefaultMentionResolver;
use Relaticle\Comments\Models\Comment;
use Relaticle\Comments\Policies\CommentPolicy;
class Config
class CommentsConfig
{
protected static ?Closure $resolveAuthenticatedUser = null;
@@ -23,7 +24,25 @@ class Config
public static function getCommentTable(): string
{
return config('comments.tables.comments', 'comments');
return static::getTableName('comments');
}
public static function getTableName(string $table): string
{
$defaults = [
'comments' => 'comments',
'reactions' => 'comment_reactions',
'mentions' => 'comment_mentions',
'subscriptions' => 'comment_subscriptions',
'attachments' => 'comment_attachments',
];
return config("comments.table_names.{$table}", $defaults[$table] ?? $table);
}
public static function getCommenterMorphName(): string
{
return config('comments.column_names.commenter_morph', 'commenter');
}
public static function getMaxDepth(): int

View File

@@ -42,20 +42,20 @@ class CommentsServiceProvider extends PackageServiceProvider
public function packageRegistered(): void
{
Relation::morphMap([
'comment' => Config::getCommentModel(),
'comment' => CommentsConfig::getCommentModel(),
]);
$this->app->bind(
MentionResolver::class,
fn () => new (Config::getMentionResolver())
fn () => new (CommentsConfig::getMentionResolver())
);
}
public function packageBooted(): void
{
Gate::policy(
Config::getCommentModel(),
Config::getPolicyClass(),
CommentsConfig::getCommentModel(),
CommentsConfig::getPolicyClass(),
);
Event::listen(CommentCreated::class, SendCommentRepliedNotification::class);

View File

@@ -5,9 +5,9 @@ namespace Relaticle\Comments\Concerns;
use Filament\Models\Contracts\HasAvatar;
use Filament\Models\Contracts\HasName;
trait IsCommenter
trait CanComment
{
public function getCommentName(): string
public function getCommentDisplayName(): string
{
if ($this instanceof HasName) {
return $this->getFilamentName();

View File

@@ -3,13 +3,13 @@
namespace Relaticle\Comments\Concerns;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
trait HasComments
{
public function comments(): MorphMany
{
return $this->morphMany(Config::getCommentModel(), 'commentable');
return $this->morphMany(CommentsConfig::getCommentModel(), 'commentable');
}
public function topLevelComments(): MorphMany

View File

@@ -2,13 +2,13 @@
namespace Relaticle\Comments\Contracts;
interface Commenter
interface Commentator
{
public function getKey();
public function getMorphClass();
public function getCommentName(): string;
public function getCommentDisplayName(): string;
public function getCommentAvatarUrl(): ?string;
}

View File

@@ -8,8 +8,8 @@ use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class CommentCreated implements ShouldBroadcast
{
@@ -27,7 +27,7 @@ class CommentCreated implements ShouldBroadcast
/** @return array<int, PrivateChannel> */
public function broadcastOn(): array
{
$prefix = Config::getBroadcastChannelPrefix();
$prefix = CommentsConfig::getBroadcastChannelPrefix();
return [
new PrivateChannel("{$prefix}.{$this->comment->commentable_type}.{$this->comment->commentable_id}"),
@@ -36,7 +36,7 @@ class CommentCreated implements ShouldBroadcast
public function broadcastWhen(): bool
{
return Config::isBroadcastingEnabled();
return CommentsConfig::isBroadcastingEnabled();
}
/** @return array{comment_id: int|string, commentable_type: string, commentable_id: int|string} */

View File

@@ -8,8 +8,8 @@ use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class CommentDeleted implements ShouldBroadcast
{
@@ -27,7 +27,7 @@ class CommentDeleted implements ShouldBroadcast
/** @return array<int, PrivateChannel> */
public function broadcastOn(): array
{
$prefix = Config::getBroadcastChannelPrefix();
$prefix = CommentsConfig::getBroadcastChannelPrefix();
return [
new PrivateChannel("{$prefix}.{$this->comment->commentable_type}.{$this->comment->commentable_id}"),
@@ -36,7 +36,7 @@ class CommentDeleted implements ShouldBroadcast
public function broadcastWhen(): bool
{
return Config::isBroadcastingEnabled();
return CommentsConfig::isBroadcastingEnabled();
}
/** @return array{comment_id: int|string, commentable_type: string, commentable_id: int|string} */

View File

@@ -7,8 +7,8 @@ use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class CommentReacted implements ShouldBroadcast
{
@@ -26,7 +26,7 @@ class CommentReacted implements ShouldBroadcast
/** @return array<int, PrivateChannel> */
public function broadcastOn(): array
{
$prefix = Config::getBroadcastChannelPrefix();
$prefix = CommentsConfig::getBroadcastChannelPrefix();
return [
new PrivateChannel("{$prefix}.{$this->comment->commentable_type}.{$this->comment->commentable_id}"),
@@ -35,7 +35,7 @@ class CommentReacted implements ShouldBroadcast
public function broadcastWhen(): bool
{
return Config::isBroadcastingEnabled();
return CommentsConfig::isBroadcastingEnabled();
}
/** @return array{comment_id: int|string, reaction: string, action: string} */

View File

@@ -8,8 +8,8 @@ use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class CommentUpdated implements ShouldBroadcast
{
@@ -27,7 +27,7 @@ class CommentUpdated implements ShouldBroadcast
/** @return array<int, PrivateChannel> */
public function broadcastOn(): array
{
$prefix = Config::getBroadcastChannelPrefix();
$prefix = CommentsConfig::getBroadcastChannelPrefix();
return [
new PrivateChannel("{$prefix}.{$this->comment->commentable_type}.{$this->comment->commentable_id}"),
@@ -36,7 +36,7 @@ class CommentUpdated implements ShouldBroadcast
public function broadcastWhen(): bool
{
return Config::isBroadcastingEnabled();
return CommentsConfig::isBroadcastingEnabled();
}
/** @return array{comment_id: int|string, commentable_type: string, commentable_id: int|string} */

View File

@@ -5,7 +5,7 @@ namespace Relaticle\Comments\Events;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Models\Comment;
class UserMentioned
{

View File

@@ -3,35 +3,35 @@
namespace Relaticle\Comments\Listeners;
use Illuminate\Support\Facades\Notification;
use Relaticle\Comments\CommentSubscription;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Events\CommentCreated;
use Relaticle\Comments\Models\Subscription;
use Relaticle\Comments\Notifications\CommentRepliedNotification;
class SendCommentRepliedNotification
{
public function handle(CommentCreated $event): void
{
if (! Config::areNotificationsEnabled()) {
if (! CommentsConfig::areNotificationsEnabled()) {
return;
}
$comment = $event->comment;
$commentable = $event->commentable;
if (Config::shouldAutoSubscribe()) {
CommentSubscription::subscribe($commentable, $comment->user);
if (CommentsConfig::shouldAutoSubscribe()) {
Subscription::subscribe($commentable, $comment->commenter);
}
if (! $comment->isReply()) {
return;
}
$subscribers = CommentSubscription::subscribersFor($commentable);
$subscribers = Subscription::subscribersFor($commentable);
$recipients = $subscribers->filter(function ($user) use ($comment) {
return ! ($user->getMorphClass() === $comment->user->getMorphClass()
&& $user->getKey() === $comment->user->getKey());
return ! ($user->getMorphClass() === $comment->commenter->getMorphClass()
&& $user->getKey() === $comment->commenter->getKey());
});
if ($recipients->isEmpty()) {

View File

@@ -2,33 +2,33 @@
namespace Relaticle\Comments\Listeners;
use Relaticle\Comments\CommentSubscription;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Events\UserMentioned;
use Relaticle\Comments\Models\Subscription;
use Relaticle\Comments\Notifications\UserMentionedNotification;
class SendUserMentionedNotification
{
public function handle(UserMentioned $event): void
{
if (! Config::areNotificationsEnabled()) {
if (! CommentsConfig::areNotificationsEnabled()) {
return;
}
$comment = $event->comment;
$mentionedUser = $event->mentionedUser;
if (Config::shouldAutoSubscribe()) {
CommentSubscription::subscribe($comment->commentable, $mentionedUser);
if (CommentsConfig::shouldAutoSubscribe()) {
Subscription::subscribe($comment->commentable, $mentionedUser);
}
$isSelf = $mentionedUser->getMorphClass() === $comment->user->getMorphClass()
&& $mentionedUser->getKey() === $comment->user->getKey();
$isSelf = $mentionedUser->getMorphClass() === $comment->commenter->getMorphClass()
&& $mentionedUser->getKey() === $comment->commenter->getKey();
if ($isSelf) {
return;
}
$mentionedUser->notify(new UserMentionedNotification($comment, $comment->user));
$mentionedUser->notify(new UserMentionedNotification($comment, $comment->commenter));
}
}

View File

@@ -6,13 +6,13 @@ use Illuminate\Contracts\View\View;
use Livewire\Component;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Livewire\WithFileUploads;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Contracts\MentionResolver;
use Relaticle\Comments\Events\CommentCreated;
use Relaticle\Comments\Events\CommentDeleted;
use Relaticle\Comments\Events\CommentUpdated;
use Relaticle\Comments\Mentions\MentionParser;
use Relaticle\Comments\Models\Comment;
class CommentItem extends Component
{
@@ -106,25 +106,25 @@ class CommentItem extends Component
$rules = ['replyBody' => ['required', 'string', 'min:1']];
if (Config::areAttachmentsEnabled()) {
$maxSize = Config::getAttachmentMaxSize();
$allowedTypes = implode(',', Config::getAttachmentAllowedTypes());
if (CommentsConfig::areAttachmentsEnabled()) {
$maxSize = CommentsConfig::getAttachmentMaxSize();
$allowedTypes = implode(',', CommentsConfig::getAttachmentAllowedTypes());
$rules['replyAttachments.*'] = ['nullable', 'file', "max:{$maxSize}", "mimetypes:{$allowedTypes}"];
}
$this->validate($rules);
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
$reply = $this->comment->commentable->comments()->create([
'body' => $this->replyBody,
'parent_id' => $this->comment->id,
'user_id' => $user->getKey(),
'user_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
]);
if (Config::areAttachmentsEnabled() && ! empty($this->replyAttachments)) {
$disk = Config::getAttachmentDisk();
if (CommentsConfig::areAttachmentsEnabled() && ! empty($this->replyAttachments)) {
$disk = CommentsConfig::getAttachmentDisk();
foreach ($this->replyAttachments as $file) {
$path = $file->store("comments/attachments/{$reply->id}", $disk);
@@ -169,7 +169,7 @@ class CommentItem extends Component
return $resolver->search($query)
->map(fn ($user) => [
'id' => $user->getKey(),
'name' => $user->getCommentName(),
'name' => $user->getCommentDisplayName(),
'avatar_url' => $user->getCommentAvatarUrl(),
])
->values()

View File

@@ -9,12 +9,12 @@ use Livewire\Attributes\Computed;
use Livewire\Component;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Livewire\WithFileUploads;
use Relaticle\Comments\Comment;
use Relaticle\Comments\CommentSubscription;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Contracts\MentionResolver;
use Relaticle\Comments\Events\CommentCreated;
use Relaticle\Comments\Mentions\MentionParser;
use Relaticle\Comments\Models\Comment;
use Relaticle\Comments\Models\Subscription;
class Comments extends Component
{
@@ -36,7 +36,7 @@ class Comments extends Component
public function mount(Model $model): void
{
$this->model = $model;
$this->perPage = Config::getPerPage();
$this->perPage = CommentsConfig::getPerPage();
$this->loadedCount = $this->perPage;
}
@@ -46,7 +46,7 @@ class Comments extends Component
{
return $this->model
->topLevelComments()
->with(['user', 'mentions', 'attachments', 'reactions.user', 'replies.user', 'replies.mentions', 'replies.attachments', 'replies.reactions.user'])
->with(['commenter', 'mentions', 'attachments', 'reactions.commenter', 'replies.commenter', 'replies.mentions', 'replies.attachments', 'replies.reactions.commenter'])
->orderBy('created_at', $this->sortDirection)
->take($this->loadedCount)
->get();
@@ -67,27 +67,27 @@ class Comments extends Component
#[Computed]
public function isSubscribed(): bool
{
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
if (! $user) {
return false;
}
return CommentSubscription::isSubscribed($this->model, $user);
return Subscription::isSubscribed($this->model, $user);
}
public function toggleSubscription(): void
{
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
if (! $user) {
return;
}
if ($this->isSubscribed) {
CommentSubscription::unsubscribe($this->model, $user);
Subscription::unsubscribe($this->model, $user);
} else {
CommentSubscription::subscribe($this->model, $user);
Subscription::subscribe($this->model, $user);
}
unset($this->isSubscribed);
@@ -97,26 +97,26 @@ class Comments extends Component
{
$rules = ['newComment' => ['required', 'string', 'min:1']];
if (Config::areAttachmentsEnabled()) {
$maxSize = Config::getAttachmentMaxSize();
$allowedTypes = implode(',', Config::getAttachmentAllowedTypes());
if (CommentsConfig::areAttachmentsEnabled()) {
$maxSize = CommentsConfig::getAttachmentMaxSize();
$allowedTypes = implode(',', CommentsConfig::getAttachmentAllowedTypes());
$rules['attachments.*'] = ['nullable', 'file', "max:{$maxSize}", "mimetypes:{$allowedTypes}"];
}
$this->validate($rules);
$this->authorize('create', Config::getCommentModel());
$this->authorize('create', CommentsConfig::getCommentModel());
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
$comment = $this->model->comments()->create([
'body' => $this->newComment,
'user_id' => $user->getKey(),
'user_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
]);
if (Config::areAttachmentsEnabled() && ! empty($this->attachments)) {
$disk = Config::getAttachmentDisk();
if (CommentsConfig::areAttachmentsEnabled() && ! empty($this->attachments)) {
$disk = CommentsConfig::getAttachmentDisk();
foreach ($this->attachments as $file) {
$path = $file->store("comments/attachments/{$comment->id}", $disk);
@@ -163,8 +163,8 @@ class Comments extends Component
'commentUpdated' => 'refreshComments',
];
if (Config::isBroadcastingEnabled()) {
$prefix = Config::getBroadcastChannelPrefix();
if (CommentsConfig::isBroadcastingEnabled()) {
$prefix = CommentsConfig::getBroadcastChannelPrefix();
$type = $this->model->getMorphClass();
$id = $this->model->getKey();
$channel = "echo-private:{$prefix}.{$type}.{$id}";
@@ -195,7 +195,7 @@ class Comments extends Component
return $resolver->search($query)
->map(fn ($user) => [
'id' => $user->getKey(),
'name' => $user->getCommentName(),
'name' => $user->getCommentDisplayName(),
'avatar_url' => $user->getCommentAvatarUrl(),
])
->values()

View File

@@ -5,9 +5,9 @@ namespace Relaticle\Comments\Livewire;
use Illuminate\Contracts\View\View;
use Livewire\Attributes\Computed;
use Livewire\Component;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Events\CommentReacted;
use Relaticle\Comments\Models\Comment;
class Reactions extends Component
{
@@ -22,19 +22,19 @@ class Reactions extends Component
public function toggleReaction(string $reaction): void
{
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
if (! $user) {
return;
}
if (! in_array($reaction, Config::getAllowedReactions())) {
if (! in_array($reaction, CommentsConfig::getAllowedReactions())) {
return;
}
$existing = $this->comment->reactions()
->where('user_id', $user->getKey())
->where('user_type', $user->getMorphClass())
->where('commenter_id', $user->getKey())
->where('commenter_type', $user->getMorphClass())
->where('reaction', $reaction)
->first();
@@ -44,8 +44,8 @@ class Reactions extends Component
event(new CommentReacted($this->comment, $user, $reaction, 'removed'));
} else {
$this->comment->reactions()->create([
'user_id' => $user->getKey(),
'user_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
'reaction' => $reaction,
]);
@@ -66,13 +66,13 @@ class Reactions extends Component
#[Computed]
public function reactionSummary(): array
{
$user = Config::resolveAuthenticatedUser();
$user = CommentsConfig::resolveAuthenticatedUser();
$userId = $user?->getKey();
$userType = $user?->getMorphClass();
$reactions = $this->comment->reactions()->with('user')->get();
$reactions = $this->comment->reactions()->with('commenter')->get();
$emojiSet = Config::getReactionEmojiSet();
$emojiSet = CommentsConfig::getReactionEmojiSet();
return $reactions
->groupBy('reaction')
@@ -81,10 +81,10 @@ class Reactions extends Component
'reaction' => $key,
'emoji' => $emojiSet[$key] ?? $key,
'count' => $group->count(),
'names' => $group->pluck('user.name')->filter()->take(3)->values()->all(),
'names' => $group->pluck('commenter.name')->filter()->take(3)->values()->all(),
'total_reactors' => $group->count(),
'reacted_by_user' => $group->contains(
fn ($r) => $r->user_id == $userId && $r->user_type === $userType
fn ($r) => $r->commenter_id == $userId && $r->commenter_type === $userType
),
];
})

View File

@@ -4,7 +4,7 @@ namespace Relaticle\Comments\Mentions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Contracts\MentionResolver;
class DefaultMentionResolver implements MentionResolver
@@ -12,18 +12,18 @@ class DefaultMentionResolver implements MentionResolver
/** @return Collection<int, Model> */
public function search(string $query): Collection
{
$model = Config::getCommenterModel();
$model = CommentsConfig::getCommenterModel();
return $model::query()
->where('name', 'like', "{$query}%")
->limit(Config::getMentionMaxResults())
->limit(CommentsConfig::getMentionMaxResults())
->get();
}
/** @return Collection<int, Model> */
public function resolveByNames(array $names): Collection
{
$model = Config::getCommenterModel();
$model = CommentsConfig::getCommenterModel();
return $model::query()
->whereIn('name', $names)

View File

@@ -3,10 +3,10 @@
namespace Relaticle\Comments\Mentions;
use Illuminate\Support\Collection;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Contracts\MentionResolver;
use Relaticle\Comments\Events\UserMentioned;
use Relaticle\Comments\Models\Comment;
class MentionParser
{
@@ -33,13 +33,13 @@ class MentionParser
public function syncMentions(Comment $comment): void
{
$newMentionIds = $this->parse($comment->body);
$existingMentionIds = $comment->mentions()->pluck('comment_mentions.user_id');
$existingMentionIds = $comment->mentions()->pluck('comment_mentions.commenter_id');
$addedIds = $newMentionIds->diff($existingMentionIds);
$comment->mentions()->sync($newMentionIds->all());
$commenterModel = Config::getCommenterModel();
$commenterModel = CommentsConfig::getCommenterModel();
$addedIds->each(function ($userId) use ($comment, $commenterModel) {
$mentionedUser = $commenterModel::find($userId);

View File

@@ -1,13 +1,14 @@
<?php
namespace Relaticle\Comments;
namespace Relaticle\Comments\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Number;
use Relaticle\Comments\CommentsConfig;
class CommentAttachment extends Model
class Attachment extends Model
{
protected $fillable = [
'comment_id',
@@ -20,12 +21,12 @@ class CommentAttachment extends Model
public function getTable(): string
{
return 'comment_attachments';
return CommentsConfig::getTableName('attachments');
}
public function comment(): BelongsTo
{
return $this->belongsTo(Config::getCommentModel());
return $this->belongsTo(CommentsConfig::getCommentModel());
}
public function isImage(): bool

View File

@@ -1,6 +1,6 @@
<?php
namespace Relaticle\Comments;
namespace Relaticle\Comments\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Database\Factories\CommentFactory;
class Comment extends Model
@@ -35,14 +36,14 @@ class Comment extends Model
protected $fillable = [
'body',
'parent_id',
'user_id',
'user_type',
'commenter_id',
'commenter_type',
'edited_at',
];
public function getTable(): string
{
return Config::getCommentTable();
return CommentsConfig::getCommentTable();
}
/** @return array<string, string> */
@@ -63,39 +64,39 @@ class Comment extends Model
return $this->morphTo();
}
public function user(): MorphTo
public function commenter(): MorphTo
{
return $this->morphTo();
}
public function parent(): BelongsTo
{
return $this->belongsTo(Config::getCommentModel(), 'parent_id');
return $this->belongsTo(CommentsConfig::getCommentModel(), 'parent_id');
}
public function replies(): HasMany
{
return $this->hasMany(Config::getCommentModel(), 'parent_id');
return $this->hasMany(CommentsConfig::getCommentModel(), 'parent_id');
}
public function reactions(): HasMany
{
return $this->hasMany(CommentReaction::class);
return $this->hasMany(Reaction::class);
}
public function attachments(): HasMany
{
return $this->hasMany(CommentAttachment::class);
return $this->hasMany(Attachment::class);
}
public function mentions(): MorphToMany
{
return $this->morphedByMany(
Config::getCommenterModel(),
'user',
'comment_mentions',
CommentsConfig::getCommenterModel(),
'commenter',
CommentsConfig::getTableName('mentions'),
'comment_id',
'user_id',
'commenter_id',
);
}
@@ -121,7 +122,7 @@ class Comment extends Model
public function canReply(): bool
{
return $this->depth() < Config::getMaxDepth();
return $this->depth() < CommentsConfig::getMaxDepth();
}
public function depth(): int
@@ -133,8 +134,8 @@ class Comment extends Model
$comment = $comment->parent;
$depth++;
if ($depth >= Config::getMaxDepth()) {
return Config::getMaxDepth();
if ($depth >= CommentsConfig::getMaxDepth()) {
return CommentsConfig::getMaxDepth();
}
}

View File

@@ -1,31 +1,32 @@
<?php
namespace Relaticle\Comments;
namespace Relaticle\Comments\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Relaticle\Comments\CommentsConfig;
class CommentReaction extends Model
class Reaction extends Model
{
protected $fillable = [
'comment_id',
'user_id',
'user_type',
'commenter_id',
'commenter_type',
'reaction',
];
public function getTable(): string
{
return 'comment_reactions';
return CommentsConfig::getTableName('reactions');
}
public function comment(): BelongsTo
{
return $this->belongsTo(Config::getCommentModel());
return $this->belongsTo(CommentsConfig::getCommentModel());
}
public function user(): MorphTo
public function commenter(): MorphTo
{
return $this->morphTo();
}

View File

@@ -1,25 +1,26 @@
<?php
namespace Relaticle\Comments;
namespace Relaticle\Comments\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Collection;
use Relaticle\Comments\CommentsConfig;
class CommentSubscription extends Model
class Subscription extends Model
{
public const UPDATED_AT = null;
protected $fillable = [
'commentable_type',
'commentable_id',
'user_type',
'user_id',
'commenter_type',
'commenter_id',
];
public function getTable(): string
{
return 'comment_subscriptions';
return CommentsConfig::getTableName('subscriptions');
}
public function commentable(): MorphTo
@@ -27,7 +28,7 @@ class CommentSubscription extends Model
return $this->morphTo();
}
public function user(): MorphTo
public function commenter(): MorphTo
{
return $this->morphTo();
}
@@ -37,8 +38,8 @@ class CommentSubscription extends Model
return static::where([
'commentable_type' => $commentable->getMorphClass(),
'commentable_id' => $commentable->getKey(),
'user_type' => $user->getMorphClass(),
'user_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
])->exists();
}
@@ -47,8 +48,8 @@ class CommentSubscription extends Model
static::firstOrCreate([
'commentable_type' => $commentable->getMorphClass(),
'commentable_id' => $commentable->getKey(),
'user_type' => $user->getMorphClass(),
'user_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
]);
}
@@ -57,8 +58,8 @@ class CommentSubscription extends Model
static::where([
'commentable_type' => $commentable->getMorphClass(),
'commentable_id' => $commentable->getKey(),
'user_type' => $user->getMorphClass(),
'user_id' => $user->getKey(),
'commenter_type' => $user->getMorphClass(),
'commenter_id' => $user->getKey(),
])->delete();
}
@@ -68,6 +69,6 @@ class CommentSubscription extends Model
return static::where([
'commentable_type' => $commentable->getMorphClass(),
'commentable_id' => $commentable->getKey(),
])->with('user')->get()->pluck('user')->filter()->values();
])->with('commenter')->get()->pluck('commenter')->filter()->values();
}
}

View File

@@ -5,8 +5,8 @@ namespace Relaticle\Comments\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class CommentRepliedNotification extends Notification
{
@@ -15,7 +15,7 @@ class CommentRepliedNotification extends Notification
/** @return array<int, string> */
public function via(mixed $notifiable): array
{
return Config::getNotificationChannels();
return CommentsConfig::getNotificationChannels();
}
/** @return array<string, mixed> */
@@ -25,14 +25,14 @@ class CommentRepliedNotification extends Notification
'comment_id' => $this->comment->id,
'commentable_type' => $this->comment->commentable_type,
'commentable_id' => $this->comment->commentable_id,
'commenter_name' => $this->comment->user->getCommentName(),
'commenter_name' => $this->comment->commenter->getCommentDisplayName(),
'body' => Str::limit(strip_tags($this->comment->body), 100),
];
}
public function toMail(mixed $notifiable): MailMessage
{
$commenterName = $this->comment->user->getCommentName();
$commenterName = $this->comment->commenter->getCommentDisplayName();
return (new MailMessage)
->subject('New reply to your comment')

View File

@@ -6,8 +6,8 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Config;
use Relaticle\Comments\CommentsConfig;
use Relaticle\Comments\Models\Comment;
class UserMentionedNotification extends Notification
{
@@ -19,7 +19,7 @@ class UserMentionedNotification extends Notification
/** @return array<int, string> */
public function via(mixed $notifiable): array
{
return Config::getNotificationChannels();
return CommentsConfig::getNotificationChannels();
}
/** @return array<string, mixed> */
@@ -29,14 +29,14 @@ class UserMentionedNotification extends Notification
'comment_id' => $this->comment->id,
'commentable_type' => $this->comment->commentable_type,
'commentable_id' => $this->comment->commentable_id,
'mentioner_name' => $this->mentionedBy->getCommentName(),
'mentioner_name' => $this->mentionedBy->getCommentDisplayName(),
'body' => Str::limit(strip_tags($this->comment->body), 100),
];
}
public function toMail(mixed $notifiable): MailMessage
{
$mentionerName = $this->mentionedBy->getCommentName();
$mentionerName = $this->mentionedBy->getCommentDisplayName();
return (new MailMessage)
->subject('You were mentioned in a comment')

View File

@@ -3,7 +3,7 @@
namespace Relaticle\Comments\Policies;
use Illuminate\Contracts\Auth\Authenticatable;
use Relaticle\Comments\Comment;
use Relaticle\Comments\Models\Comment;
class CommentPolicy
{
@@ -19,14 +19,14 @@ class CommentPolicy
public function update(Authenticatable $user, Comment $comment): bool
{
return $user->getKey() === $comment->user_id
&& $user->getMorphClass() === $comment->user_type;
return $user->getKey() === $comment->commenter_id
&& $user->getMorphClass() === $comment->commenter_type;
}
public function delete(Authenticatable $user, Comment $comment): bool
{
return $user->getKey() === $comment->user_id
&& $user->getMorphClass() === $comment->user_type;
return $user->getKey() === $comment->commenter_id
&& $user->getMorphClass() === $comment->commenter_type;
}
public function reply(Authenticatable $user, Comment $comment): bool