user(); if (!$user || !$user->roles()->where('name', 'ROLE_ADMIN')->exists()) { return response()->json(['message' => 'Forbidden'], 403); } return null; } public function index(Request $request): JsonResponse { if ($error = $this->ensureAdmin($request)) { return $error; } $groups = AttachmentGroup::query() ->withCount('extensions') ->orderBy('parent_id') ->orderBy('position') ->orderBy('name') ->get() ->map(fn (AttachmentGroup $group) => $this->serializeGroup($group)); return response()->json($groups); } public function store(Request $request): JsonResponse { if ($error = $this->ensureAdmin($request)) { return $error; } $data = $this->validatePayload($request); $name = trim($data['name']); $parentId = $this->normalizeParentId($data['parent_id'] ?? null); if (AttachmentGroup::query()->whereRaw('LOWER(name) = ?', [strtolower($name)])->exists()) { return response()->json(['message' => 'Attachment group already exists.'], 422); } $position = (AttachmentGroup::query() ->where('parent_id', $parentId) ->max('position') ?? 0) + 1; $group = AttachmentGroup::create([ 'name' => $name, 'parent_id' => $parentId, 'position' => $position, 'max_size_kb' => $data['max_size_kb'], 'is_active' => $data['is_active'], ]); $group->loadCount('extensions'); return response()->json($this->serializeGroup($group), 201); } public function update(Request $request, AttachmentGroup $attachmentGroup): JsonResponse { if ($error = $this->ensureAdmin($request)) { return $error; } $data = $this->validatePayload($request); $name = trim($data['name']); $parentId = $this->normalizeParentId($data['parent_id'] ?? null); $position = $attachmentGroup->position ?? 1; if (AttachmentGroup::query() ->where('id', '!=', $attachmentGroup->id) ->whereRaw('LOWER(name) = ?', [strtolower($name)]) ->exists() ) { return response()->json(['message' => 'Attachment group already exists.'], 422); } if ($attachmentGroup->parent_id !== $parentId) { $position = (AttachmentGroup::query() ->where('parent_id', $parentId) ->max('position') ?? 0) + 1; } $attachmentGroup->update([ 'name' => $name, 'parent_id' => $parentId, 'position' => $position, 'max_size_kb' => $data['max_size_kb'], 'is_active' => $data['is_active'], ]); $attachmentGroup->loadCount('extensions'); return response()->json($this->serializeGroup($attachmentGroup)); } public function destroy(Request $request, AttachmentGroup $attachmentGroup): JsonResponse { if ($error = $this->ensureAdmin($request)) { return $error; } if ($attachmentGroup->extensions()->exists()) { return response()->json(['message' => 'Attachment group has extensions.'], 422); } if (Attachment::query()->where('attachment_group_id', $attachmentGroup->id)->exists()) { return response()->json(['message' => 'Attachment group is in use.'], 422); } $attachmentGroup->delete(); return response()->json(null, 204); } public function reorder(Request $request): JsonResponse { if ($error = $this->ensureAdmin($request)) { return $error; } $data = $request->validate([ 'parentId' => ['nullable'], 'orderedIds' => ['required', 'array'], 'orderedIds.*' => ['integer'], ]); $parentId = $data['parentId'] ?? null; if ($parentId === '' || $parentId === 'null') { $parentId = null; } elseif ($parentId !== null) { $parentId = (int) $parentId; } foreach ($data['orderedIds'] as $index => $groupId) { AttachmentGroup::where('id', $groupId) ->where('parent_id', $parentId) ->update(['position' => $index + 1]); } return response()->json(['status' => 'ok']); } private function validatePayload(Request $request): array { return $request->validate([ 'name' => ['required', 'string', 'max:150'], 'parent_id' => ['nullable', 'integer', 'exists:attachment_groups,id'], 'max_size_kb' => ['required', 'integer', 'min:1', 'max:512000'], 'is_active' => ['required', 'boolean'], ]); } private function serializeGroup(AttachmentGroup $group): array { return [ 'id' => $group->id, 'name' => $group->name, 'parent_id' => $group->parent_id, 'position' => $group->position, 'max_size_kb' => $group->max_size_kb, 'is_active' => $group->is_active, 'extensions_count' => $group->extensions_count ?? null, ]; } private function normalizeParentId($value): ?int { if ($value === '' || $value === 'null') { return null; } if ($value === null) { return null; } return (int) $value; } }