messages implemented
This commit is contained in:
113
app/Http/Controllers/Api/LatestCommentsApiController.php
Normal file
113
app/Http/Controllers/Api/LatestCommentsApiController.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use App\Models\ArtworkComment;
|
||||
use App\Support\AvatarUrl;
|
||||
use App\Services\ThumbnailPresenter;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class LatestCommentsApiController extends Controller
|
||||
{
|
||||
private const PER_PAGE = 20;
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$type = $request->query('type', 'all');
|
||||
|
||||
// Validate filter type
|
||||
if (! in_array($type, ['all', 'following', 'mine'], true)) {
|
||||
$type = 'all';
|
||||
}
|
||||
|
||||
// 'mine' and 'following' require auth
|
||||
if (in_array($type, ['mine', 'following'], true) && ! $request->user()) {
|
||||
return response()->json(['error' => 'Unauthenticated'], 401);
|
||||
}
|
||||
|
||||
$query = ArtworkComment::with(['user', 'user.profile', 'artwork'])
|
||||
->whereHas('artwork', function ($q) {
|
||||
$q->public()->published()->whereNull('deleted_at');
|
||||
})
|
||||
->orderByDesc('artwork_comments.created_at');
|
||||
|
||||
switch ($type) {
|
||||
case 'mine':
|
||||
$query->where('artwork_comments.user_id', $request->user()->id);
|
||||
break;
|
||||
|
||||
case 'following':
|
||||
$followingIds = $request->user()
|
||||
->following()
|
||||
->pluck('users.id');
|
||||
$query->whereIn('artwork_comments.user_id', $followingIds);
|
||||
break;
|
||||
|
||||
default:
|
||||
// 'all' — cache the first page only
|
||||
if ((int) $request->query('page', 1) === 1) {
|
||||
$cacheKey = 'comments.latest.all.page1';
|
||||
$ttl = 120; // 2 minutes
|
||||
|
||||
$paginator = Cache::remember($cacheKey, $ttl, fn () => $query->paginate(self::PER_PAGE));
|
||||
} else {
|
||||
$paginator = $query->paginate(self::PER_PAGE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (! isset($paginator)) {
|
||||
$paginator = $query->paginate(self::PER_PAGE);
|
||||
}
|
||||
|
||||
$items = $paginator->getCollection()->map(function (ArtworkComment $c) {
|
||||
$art = $c->artwork;
|
||||
$user = $c->user;
|
||||
|
||||
$present = $art ? ThumbnailPresenter::present($art, 'md') : null;
|
||||
$thumb = $present ? ($present['url'] ?? null) : null;
|
||||
|
||||
$userId = (int) ($c->user_id ?? 0);
|
||||
$avatarHash = $user?->profile?->avatar_hash ?? null;
|
||||
|
||||
return [
|
||||
'comment_id' => $c->getKey(),
|
||||
'comment_text' => e(strip_tags($c->content ?? '')),
|
||||
'created_at' => $c->created_at?->toIso8601String(),
|
||||
'time_ago' => $c->created_at ? Carbon::parse($c->created_at)->diffForHumans() : null,
|
||||
|
||||
'commenter' => [
|
||||
'id' => $userId,
|
||||
'username' => $user?->username ?? null,
|
||||
'display' => $user?->username ?? $user?->name ?? 'User',
|
||||
'profile_url' => $user?->username ? '/@' . $user->username : '/profile/' . $userId,
|
||||
'avatar_url' => AvatarUrl::forUser($userId, $avatarHash, 64),
|
||||
],
|
||||
|
||||
'artwork' => $art ? [
|
||||
'id' => $art->id,
|
||||
'title' => $art->title,
|
||||
'slug' => $art->slug ?? Str::slug($art->title ?? ''),
|
||||
'url' => '/art/' . $art->id . '/' . ($art->slug ?? Str::slug($art->title ?? '')),
|
||||
'thumb' => $thumb,
|
||||
] : null,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'data' => $items,
|
||||
'meta' => [
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'total' => $paginator->total(),
|
||||
'has_more' => $paginator->hasMorePages(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user