optimizations
This commit is contained in:
117
app/Services/NovaCards/NovaCardCommentService.php
Normal file
117
app/Services/NovaCards/NovaCardCommentService.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\NovaCards;
|
||||
|
||||
use App\Jobs\UpdateNovaCardStatsJob;
|
||||
use App\Models\NovaCard;
|
||||
use App\Models\NovaCardComment;
|
||||
use App\Models\User;
|
||||
use App\Services\NotificationService;
|
||||
use App\Support\AvatarUrl;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class NovaCardCommentService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly NotificationService $notifications,
|
||||
) {
|
||||
}
|
||||
|
||||
public function create(NovaCard $card, User $actor, string $body, ?NovaCardComment $parent = null): NovaCardComment
|
||||
{
|
||||
if (! $card->canReceiveCommentsFrom($actor)) {
|
||||
throw ValidationException::withMessages([
|
||||
'card' => 'Comments are unavailable for this card.',
|
||||
]);
|
||||
}
|
||||
|
||||
$comment = NovaCardComment::query()->create([
|
||||
'card_id' => $card->id,
|
||||
'user_id' => $actor->id,
|
||||
'parent_id' => $parent?->id,
|
||||
'body' => trim($body),
|
||||
'rendered_body' => nl2br(e(trim($body))),
|
||||
'status' => 'visible',
|
||||
]);
|
||||
|
||||
if (! $card->isOwnedBy($actor)) {
|
||||
$this->notifications->notifyNovaCardComment($card->user, $actor, $card, $comment);
|
||||
}
|
||||
|
||||
UpdateNovaCardStatsJob::dispatch($card->id);
|
||||
|
||||
return $comment->fresh(['user.profile', 'replies.user.profile', 'card.user']);
|
||||
}
|
||||
|
||||
public function delete(NovaCardComment $comment, User $actor): void
|
||||
{
|
||||
if ((int) $comment->user_id !== (int) $actor->id && ! $comment->card->isOwnedBy($actor) && ! $this->isModerator($actor)) {
|
||||
throw ValidationException::withMessages([
|
||||
'comment' => 'You are not allowed to remove this comment.',
|
||||
]);
|
||||
}
|
||||
|
||||
if ($comment->trashed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$comment->delete();
|
||||
UpdateNovaCardStatsJob::dispatch($comment->card_id);
|
||||
}
|
||||
|
||||
public function mapComments(NovaCard $card, ?User $viewer = null): array
|
||||
{
|
||||
$comments = $card->comments()
|
||||
->whereNull('parent_id')
|
||||
->where('status', 'visible')
|
||||
->with(['user.profile', 'replies.user.profile', 'card.user'])
|
||||
->latest()
|
||||
->limit(30)
|
||||
->get();
|
||||
|
||||
return $comments->map(fn (NovaCardComment $comment) => $this->mapComment($comment, $viewer))->all();
|
||||
}
|
||||
|
||||
private function mapComment(NovaCardComment $comment, ?User $viewer = null): array
|
||||
{
|
||||
$user = $comment->user;
|
||||
|
||||
return [
|
||||
'id' => (int) $comment->id,
|
||||
'body' => (string) $comment->body,
|
||||
'rendered_content' => (string) $comment->rendered_body,
|
||||
'time_ago' => $comment->created_at?->diffForHumans(),
|
||||
'created_at' => $comment->created_at?->toISOString(),
|
||||
'can_delete' => $viewer !== null && ((int) $viewer->id === (int) $comment->user_id || $comment->card->isOwnedBy($viewer) || $this->isModerator($viewer)),
|
||||
'can_report' => $viewer !== null && (int) $viewer->id !== (int) $comment->user_id,
|
||||
'user' => [
|
||||
'id' => (int) $user->id,
|
||||
'display' => (string) ($user->name ?: $user->username),
|
||||
'username' => (string) $user->username,
|
||||
'avatar_url' => AvatarUrl::forUser((int) $user->id, $user->profile?->avatar_hash, 64),
|
||||
'profile_url' => '/@' . Str::lower((string) $user->username),
|
||||
],
|
||||
'replies' => $comment->replies
|
||||
->where('status', 'visible')
|
||||
->map(fn (NovaCardComment $reply) => $this->mapComment($reply, $viewer))
|
||||
->values()
|
||||
->all(),
|
||||
];
|
||||
}
|
||||
|
||||
private function isModerator(User $user): bool
|
||||
{
|
||||
if (method_exists($user, 'isModerator')) {
|
||||
return (bool) $user->isModerator();
|
||||
}
|
||||
|
||||
if (method_exists($user, 'hasRole')) {
|
||||
return (bool) $user->hasRole('moderator') || (bool) $user->hasRole('admin');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user