Batch-load comment reaction counts on artwork comments.
Avoid per-comment reaction queries on the deferred comments API by aggregating counts in one service call.
This commit is contained in:
@@ -11,6 +11,7 @@ use App\Models\UserMention;
|
||||
use App\Notifications\ArtworkCommentedNotification;
|
||||
use App\Notifications\ArtworkMentionedNotification;
|
||||
use App\Services\ContentSanitizer;
|
||||
use App\Services\CommentReactionService;
|
||||
use App\Support\AvatarUrl;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -30,6 +31,8 @@ class ArtworkCommentController extends Controller
|
||||
{
|
||||
private const MAX_LENGTH = 10_000;
|
||||
|
||||
public function __construct(private readonly CommentReactionService $commentReactions) {}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// List
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -53,7 +56,9 @@ class ArtworkCommentController extends Controller
|
||||
->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
$userId = $request->user()?->id;
|
||||
$items = $comments->getCollection()->map(fn ($c) => $this->formatComment($c, $userId, true));
|
||||
$commentIds = $this->commentIds($comments->getCollection());
|
||||
$reactionTotals = $this->commentReactions->forComments($commentIds, $userId);
|
||||
$items = $comments->getCollection()->map(fn ($c) => $this->formatComment($c, $userId, true, $reactionTotals));
|
||||
|
||||
return response()->json([
|
||||
'data' => $items,
|
||||
@@ -138,7 +143,9 @@ class ArtworkCommentController extends Controller
|
||||
);
|
||||
} catch (\Throwable) {}
|
||||
|
||||
return response()->json(['data' => $this->formatComment($comment, $request->user()->id, false)], 201);
|
||||
$reactionTotals = $this->commentReactions->forComments([$comment->id], $request->user()->id);
|
||||
|
||||
return response()->json(['data' => $this->formatComment($comment, $request->user()->id, false, $reactionTotals)], 201);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -197,7 +204,7 @@ class ArtworkCommentController extends Controller
|
||||
// Helpers
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
private function formatComment(ArtworkComment $c, ?int $currentUserId, bool $includeReplies = false): array
|
||||
private function formatComment(ArtworkComment $c, ?int $currentUserId, bool $includeReplies = false, array $reactionTotals = []): array
|
||||
{
|
||||
$user = $c->user;
|
||||
$userId = (int) ($c->user_id ?? 0);
|
||||
@@ -221,12 +228,13 @@ class ArtworkCommentController extends Controller
|
||||
'level' => (int) ($user?->level ?? 1),
|
||||
'rank' => (string) ($user?->rank ?? 'Newbie'),
|
||||
],
|
||||
'reactions' => $reactionTotals[(int) $c->id] ?? [],
|
||||
];
|
||||
|
||||
if ($includeReplies && $c->relationLoaded('approvedReplies')) {
|
||||
$data['replies'] = $c->approvedReplies->map(fn ($r) => $this->formatComment($r, $currentUserId, true))->values()->toArray();
|
||||
$data['replies'] = $c->approvedReplies->map(fn ($r) => $this->formatComment($r, $currentUserId, true, $reactionTotals))->values()->toArray();
|
||||
} elseif ($includeReplies && $c->relationLoaded('replies')) {
|
||||
$data['replies'] = $c->replies->map(fn ($r) => $this->formatComment($r, $currentUserId, true))->values()->toArray();
|
||||
$data['replies'] = $c->replies->map(fn ($r) => $this->formatComment($r, $currentUserId, true, $reactionTotals))->values()->toArray();
|
||||
} else {
|
||||
$data['replies'] = [];
|
||||
}
|
||||
@@ -234,6 +242,24 @@ class ArtworkCommentController extends Controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @param iterable<int, ArtworkComment> $comments */
|
||||
private function commentIds(iterable $comments): array
|
||||
{
|
||||
$ids = [];
|
||||
$walk = function (iterable $items) use (&$walk, &$ids): void {
|
||||
foreach ($items as $comment) {
|
||||
$ids[] = (int) $comment->id;
|
||||
if ($comment->relationLoaded('approvedReplies')) {
|
||||
$walk($comment->approvedReplies);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$walk($comments);
|
||||
|
||||
return array_values(array_unique($ids));
|
||||
}
|
||||
|
||||
private function renderCommentContent(ArtworkComment $comment): string
|
||||
{
|
||||
$rawContent = (string) ($comment->raw_content ?? $comment->content ?? '');
|
||||
|
||||
Reference in New Issue
Block a user