user()->events() ->where('client_id', $clientId) ->firstOrFail(); return response()->json([ 'data' => EventMediaResource::collection( $event->media()->orderBy('created_at')->get() ), ]); } public function store( StoreEventMediaRequest $request, EventMediaImageProcessor $processor, string $clientId ): JsonResponse { $event = $request->user()->events() ->where('client_id', $clientId) ->firstOrFail(); $collection = $request->validated('collection') ?? 'gallery'; $processed = $processor->process($request->file('file')); $uuid = (string) str()->uuid(); $directory = "event-media/{$request->user()->id}/{$event->client_id}"; $path = "{$directory}/{$uuid}.jpg"; $previewPath = "{$directory}/{$uuid}_preview.jpg"; $thumbnailPath = "{$directory}/{$uuid}_thumb.jpg"; Storage::disk('local')->put($path, $processed['original']); Storage::disk('local')->put($previewPath, $processed['preview']); Storage::disk('local')->put($thumbnailPath, $processed['thumbnail']); if ($collection === 'key_image') { $this->deleteExistingKeyImages($event->media()->where('collection', 'key_image')->get()); } $media = $event->media()->create([ 'uuid' => $uuid, 'user_id' => $request->user()->id, 'collection' => $collection, 'name' => $request->file('file')->getClientOriginalName(), 'mime_type' => $processed['mime_type'], 'disk' => 'local', 'path' => $path, 'thumbnail_path' => $thumbnailPath, 'preview_path' => $previewPath, 'size' => $processed['size'], 'width' => $processed['width'], 'height' => $processed['height'], 'thumbnail_width' => $processed['thumbnail_width'], 'thumbnail_height' => $processed['thumbnail_height'], 'preview_width' => $processed['preview_width'], 'preview_height' => $processed['preview_height'], ]); if ($collection === 'key_image') { $event->update(['image' => "/event-media/{$media->id}/thumb"]); } return (new EventMediaResource($media)) ->response() ->setStatusCode(201); } public function show(Request $request, EventMedia $media, string $variant): Response { abort_unless(in_array($variant, ['thumb', 'preview', 'original'], true), 404); abort_unless((int) $media->user_id === (int) $request->user()->id, 404); $path = match ($variant) { 'thumb' => $media->thumbnail_path, 'preview' => $media->preview_path ?: $media->thumbnail_path, default => $media->path, }; abort_unless(is_string($path) && $path !== '', 404); abort_unless(Storage::disk($media->disk)->exists($path), 404); return response(Storage::disk($media->disk)->get($path), 200, [ 'Content-Type' => 'image/jpeg', 'Cache-Control' => 'private, max-age=604800', ]); } public function destroy(Request $request, string $clientId, EventMedia $media): JsonResponse { $event = $request->user()->events() ->where('client_id', $clientId) ->firstOrFail(); abort_unless((int) $media->event_id === (int) $event->id, 404); $wasKeyImage = $media->collection === 'key_image'; $this->deleteMediaFiles($media); $media->delete(); if ($wasKeyImage) { $event->update(['image' => null]); } return response()->json(null, 204); } private function deleteExistingKeyImages(iterable $mediaItems): void { foreach ($mediaItems as $media) { $this->deleteMediaFiles($media); $media->delete(); } } private function deleteMediaFiles(EventMedia $media): void { Storage::disk($media->disk)->delete(array_filter([ $media->path, $media->preview_path, $media->thumbnail_path, ])); } }