added attchments
All checks were successful
CI/CD Pipeline / test (push) Successful in 3s
CI/CD Pipeline / deploy (push) Successful in 24s

This commit is contained in:
2026-01-28 19:34:25 +01:00
parent 2409feb06f
commit c33cde6f04
32 changed files with 4618 additions and 213 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\Forum;
use App\Models\Thread;
use App\Actions\BbcodeFormatter;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -49,6 +50,8 @@ class ThreadController extends Controller
'user' => fn ($query) => $query
->withCount(['posts', 'threads', 'thanksGiven', 'thanksReceived'])
->with(['rank', 'roles']),
'attachments.extension',
'attachments.group',
'latestPost.user.rank',
'latestPost.user.roles',
])->loadCount('posts');
@@ -81,6 +84,8 @@ class ThreadController extends Controller
'user' => fn ($query) => $query
->withCount(['posts', 'threads', 'thanksGiven', 'thanksReceived'])
->with(['rank', 'roles']),
'attachments.extension',
'attachments.group',
'latestPost.user.rank',
'latestPost.user.roles',
])->loadCount('posts');
@@ -120,6 +125,8 @@ class ThreadController extends Controller
'user' => fn ($query) => $query
->withCount(['posts', 'threads', 'thanksGiven', 'thanksReceived'])
->with(['rank', 'roles']),
'attachments.extension',
'attachments.group',
'latestPost.user.rank',
'latestPost.user.roles',
])->loadCount('posts');
@@ -146,10 +153,13 @@ class ThreadController extends Controller
private function serializeThread(Thread $thread): array
{
$attachments = $thread->relationLoaded('attachments') ? $thread->attachments : collect();
$bodyHtml = $this->renderBody($thread->body, $attachments);
return [
'id' => $thread->id,
'title' => $thread->title,
'body' => $thread->body,
'body_html' => $bodyHtml,
'solved' => (bool) $thread->solved,
'forum' => "/api/forums/{$thread->forum_id}",
'user_id' => $thread->user_id,
@@ -184,9 +194,69 @@ class ThreadController extends Controller
?? $this->resolveGroupColor($thread->user),
'created_at' => $thread->created_at?->toIso8601String(),
'updated_at' => $thread->updated_at?->toIso8601String(),
'attachments' => $thread->relationLoaded('attachments')
? $attachments
->map(fn ($attachment) => [
'id' => $attachment->id,
'group' => $attachment->group ? [
'id' => $attachment->group->id,
'name' => $attachment->group->name,
] : null,
'original_name' => $attachment->original_name,
'extension' => $attachment->extension,
'mime_type' => $attachment->mime_type,
'size_bytes' => $attachment->size_bytes,
'download_url' => "/api/attachments/{$attachment->id}/download",
'created_at' => $attachment->created_at?->toIso8601String(),
])
->values()
: [],
];
}
private function renderBody(string $body, $attachments): string
{
$replaced = $this->replaceAttachmentTags($body, $attachments);
return BbcodeFormatter::format($replaced);
}
private function replaceAttachmentTags(string $body, $attachments): string
{
if (!$attachments || count($attachments) === 0) {
return $body;
}
$map = [];
foreach ($attachments as $attachment) {
$name = strtolower($attachment->original_name ?? '');
if ($name !== '') {
$map[$name] = [
'url' => "/api/attachments/{$attachment->id}/download",
'mime' => $attachment->mime_type ?? '',
];
}
}
if (!$map) {
return $body;
}
return preg_replace_callback('/\\[attachment\\](.+?)\\[\\/attachment\\]/i', function ($matches) use ($map) {
$rawName = trim($matches[1]);
$key = strtolower($rawName);
if (!array_key_exists($key, $map)) {
return $matches[0];
}
$entry = $map[$key];
$url = $entry['url'];
$mime = $entry['mime'] ?? '';
if (str_starts_with($mime, 'image/')) {
return "[img]{$url}[/img]";
}
return "[url={$url}]{$rawName}[/url]";
}, $body) ?? $body;
}
private function resolveGroupColor(?\App\Models\User $user): ?string
{
if (!$user) {