validated(); $attachment = $this->attachmentService->upload( file: $request->file('file'), attachmentableType: $validated['attachmentable_type'] ?? null, attachmentableId: $validated['attachmentable_id'] ?? null, collection: $validated['collection'] ?? 'default', sourceType: isset($validated['source_type']) ? AttachmentSourceType::from($validated['source_type']) : AttachmentSourceType::Core, sourceIdentifier: $validated['source_identifier'] ?? null, ); return $this->successWithResource( 'attachment.upload_success', new AttachmentResource($attachment), 201 ); } catch (Exception $e) { return $this->error('attachment.upload_failed', 500, $e->getMessage()); } } /** * 여러 파일 일괄 업로드 * * @param UploadBatchAttachmentRequest $request 일괄 업로드 요청 * @return JsonResponse */ public function uploadBatch(UploadBatchAttachmentRequest $request): JsonResponse { try { $validated = $request->validated(); $attachments = $this->attachmentService->uploadBatch( files: $request->file('files'), attachmentableType: $validated['attachmentable_type'] ?? null, attachmentableId: $validated['attachmentable_id'] ?? null, collection: $validated['collection'] ?? 'default', sourceType: isset($validated['source_type']) ? AttachmentSourceType::from($validated['source_type']) : AttachmentSourceType::Core, sourceIdentifier: $validated['source_identifier'] ?? null, ); return $this->successWithResource( 'attachment.upload_batch_success', AttachmentResource::collection($attachments), 201 ); } catch (Exception $e) { return $this->error('attachment.upload_failed', 500, $e->getMessage()); } } /** * 첨부파일 삭제 * * @param Attachment $attachment 첨부파일 (라우트 모델 바인딩) * @return JsonResponse */ public function destroy(Attachment $attachment): JsonResponse { try { $result = $this->attachmentService->delete($attachment->id); if (! $result) { return $this->error('attachment.delete_failed'); } return $this->success('attachment.delete_success'); } catch (Exception $e) { return $this->error('attachment.delete_failed', 500, $e->getMessage()); } } /** * 순서 변경 * * @param ReorderAttachmentsRequest $request 순서 변경 요청 * @return JsonResponse */ public function reorder(ReorderAttachmentsRequest $request): JsonResponse { try { $this->attachmentService->reorder($request->input('order')); return $this->success('attachment.reorder_success'); } catch (AuthorizationException $e) { // 스코프 밖 첨부가 포함된 경우. 아래 제네릭 catch 보다 앞에 둬야 한다 — // 뒤에 두면 인가 거부가 500 으로 뭉개져 상세 경로(403)와 응답이 갈린다. return $this->error('auth.scope_denied', 403, $e->getMessage()); } catch (Exception $e) { return $this->error('attachment.reorder_failed', 500, $e->getMessage()); } } }