137 lines
4.1 KiB
PHP
137 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Post;
|
|
use App\Models\Thread;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class PostController extends Controller
|
|
{
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$query = Post::query()->withoutTrashed()->with([
|
|
'user' => fn ($query) => $query
|
|
->withCount(['posts', 'threads', 'thanksGiven', 'thanksReceived'])
|
|
->with(['rank', 'roles']),
|
|
]);
|
|
|
|
$threadParam = $request->query('thread');
|
|
if (is_string($threadParam)) {
|
|
$threadId = $this->parseIriId($threadParam);
|
|
if ($threadId !== null) {
|
|
$query->where('thread_id', $threadId);
|
|
}
|
|
}
|
|
|
|
$posts = $query
|
|
->oldest('created_at')
|
|
->get()
|
|
->map(fn (Post $post) => $this->serializePost($post));
|
|
|
|
return response()->json($posts);
|
|
}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'body' => ['required', 'string'],
|
|
'thread' => ['required', 'string'],
|
|
]);
|
|
|
|
$threadId = $this->parseIriId($data['thread']);
|
|
$thread = Thread::findOrFail($threadId);
|
|
|
|
$post = Post::create([
|
|
'thread_id' => $thread->id,
|
|
'user_id' => $request->user()?->id,
|
|
'body' => $data['body'],
|
|
]);
|
|
|
|
$post->loadMissing([
|
|
'user' => fn ($query) => $query
|
|
->withCount(['posts', 'threads', 'thanksGiven', 'thanksReceived'])
|
|
->with(['rank', 'roles']),
|
|
]);
|
|
|
|
return response()->json($this->serializePost($post), 201);
|
|
}
|
|
|
|
public function destroy(Request $request, Post $post): JsonResponse
|
|
{
|
|
$post->deleted_by = $request->user()?->id;
|
|
$post->save();
|
|
$post->delete();
|
|
|
|
return response()->json(null, 204);
|
|
}
|
|
|
|
private function parseIriId(?string $value): ?int
|
|
{
|
|
if (!$value) {
|
|
return null;
|
|
}
|
|
|
|
if (preg_match('#/threads/(\d+)$#', $value, $matches)) {
|
|
return (int) $matches[1];
|
|
}
|
|
|
|
if (is_numeric($value)) {
|
|
return (int) $value;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function serializePost(Post $post): array
|
|
{
|
|
return [
|
|
'id' => $post->id,
|
|
'body' => $post->body,
|
|
'thread' => "/api/threads/{$post->thread_id}",
|
|
'user_id' => $post->user_id,
|
|
'user_name' => $post->user?->name,
|
|
'user_avatar_url' => $post->user?->avatar_path
|
|
? Storage::url($post->user->avatar_path)
|
|
: null,
|
|
'user_posts_count' => ($post->user?->posts_count ?? 0) + ($post->user?->threads_count ?? 0),
|
|
'user_created_at' => $post->user?->created_at?->toIso8601String(),
|
|
'user_location' => $post->user?->location,
|
|
'user_thanks_given_count' => $post->user?->thanks_given_count ?? 0,
|
|
'user_thanks_received_count' => $post->user?->thanks_received_count ?? 0,
|
|
'user_rank_name' => $post->user?->rank?->name,
|
|
'user_rank_badge_type' => $post->user?->rank?->badge_type,
|
|
'user_rank_badge_text' => $post->user?->rank?->badge_text,
|
|
'user_rank_badge_url' => $post->user?->rank?->badge_image_path
|
|
? Storage::url($post->user->rank->badge_image_path)
|
|
: null,
|
|
'user_rank_color' => $post->user?->rank?->color,
|
|
'user_group_color' => $this->resolveGroupColor($post->user),
|
|
'created_at' => $post->created_at?->toIso8601String(),
|
|
'updated_at' => $post->updated_at?->toIso8601String(),
|
|
];
|
|
}
|
|
|
|
private function resolveGroupColor(?\App\Models\User $user): ?string
|
|
{
|
|
if (!$user) {
|
|
return null;
|
|
}
|
|
|
|
$roles = $user->roles;
|
|
if (!$roles) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($roles->sortBy('name') as $role) {
|
|
if (!empty($role->color)) {
|
|
return $role->color;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|