feat: add image upload trait

This commit is contained in:
2026-06-03 03:05:11 +03:30
parent 6f01c783fd
commit 79303de0fb
3 changed files with 62 additions and 8 deletions
+16 -5
View File
@@ -7,12 +7,15 @@
use App\Models\Category; use App\Models\Category;
use App\Models\SubCategory; use App\Models\SubCategory;
use App\Models\Tag; use App\Models\Tag;
use App\Traits\HandlesImageUpload;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
class MediaController extends Controller class MediaController extends Controller
{ {
use HandlesImageUpload;
// CREATE media // CREATE media
public function store(Request $request) public function store(Request $request)
{ {
@@ -25,6 +28,7 @@ public function store(Request $request)
'subcategory_ids' => 'nullable|array', 'subcategory_ids' => 'nullable|array',
'subcategory_ids.*' => 'integer|exists:sub_categories,id', 'subcategory_ids.*' => 'integer|exists:sub_categories,id',
'image_id' => 'nullable|exists:images,id', 'image_id' => 'nullable|exists:images,id',
'image' => 'nullable|image|max:8192',
'duration' => 'nullable|integer', 'duration' => 'nullable|integer',
'is_premium' => 'nullable|boolean', 'is_premium' => 'nullable|boolean',
'file' => 'nullable|mimes:mp3,wav,mp4,mov|max:512000', 'file' => 'nullable|mimes:mp3,wav,mp4,mov|max:512000',
@@ -40,6 +44,9 @@ public function store(Request $request)
$path = $request->file('file')->store('media', 'public'); $path = $request->file('file')->store('media', 'public');
} }
// An uploaded image file takes precedence over a provided image_id.
$imageId = $this->uploadedImageId($request) ?? ($data['image_id'] ?? null);
$media = Media::create([ $media = Media::create([
'user_id' => auth()->id(), 'user_id' => auth()->id(),
'title' => $data['title'], 'title' => $data['title'],
@@ -47,7 +54,7 @@ public function store(Request $request)
'type' => $data['type'], 'type' => $data['type'],
'file_path' => $path, 'file_path' => $path,
'external_url' => $data['external_url'] ?? null, 'external_url' => $data['external_url'] ?? null,
'image_id' => $data['image_id'] ?? null, 'image_id' => $imageId,
'duration' => $data['duration'] ?? null, 'duration' => $data['duration'] ?? null,
'visibility' => $data['visibility'] ?? 'public', 'visibility' => $data['visibility'] ?? 'public',
'is_premium'=> $data['is_premium'] ?? false 'is_premium'=> $data['is_premium'] ?? false
@@ -469,6 +476,7 @@ public function update(Request $request, $id)
'subcategory_ids.*' => 'integer|exists:sub_categories,id', 'subcategory_ids.*' => 'integer|exists:sub_categories,id',
'is_premium' => 'nullable|boolean', 'is_premium' => 'nullable|boolean',
'image_id' => 'nullable|exists:images,id', 'image_id' => 'nullable|exists:images,id',
'image' => 'nullable|image|max:8192',
'duration' => 'nullable|integer', 'duration' => 'nullable|integer',
'file' => 'nullable|mimes:mp3,wav,mp4,mov|max:512000', 'file' => 'nullable|mimes:mp3,wav,mp4,mov|max:512000',
'external_url' => 'nullable|string', 'external_url' => 'nullable|string',
@@ -495,10 +503,13 @@ public function update(Request $request, $id)
'file_path' => $data['file_path'] ?? $media->file_path, 'file_path' => $data['file_path'] ?? $media->file_path,
]; ];
// --- Handle image_id specifically --- // --- Handle image ---
// If image_id is provided in request, use it (even if null to remove association) // An uploaded image file wins; otherwise an explicit image_id (even null to
// If not provided, keep the existing value // clear) is honored; otherwise the existing value is kept.
if (array_key_exists('image_id', $data)) { $uploadedImageId = $this->uploadedImageId($request);
if ($uploadedImageId !== null) {
$updateData['image_id'] = $uploadedImageId;
} elseif (array_key_exists('image_id', $data)) {
$updateData['image_id'] = $data['image_id']; $updateData['image_id'] = $data['image_id'];
} else { } else {
$updateData['image_id'] = $media->image_id; $updateData['image_id'] = $media->image_id;
+17 -3
View File
@@ -5,10 +5,12 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\MusicPlaylist; use App\Models\MusicPlaylist;
use App\Models\Music; use App\Models\Music;
use App\Traits\HandlesImageUpload;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
class MusicController extends Controller class MusicController extends Controller
{ {
use HandlesImageUpload;
// Add this new method to your MusicController // Add this new method to your MusicController
public function getAllMusic() public function getAllMusic()
@@ -135,6 +137,7 @@ public function store(Request $request)
'file' => 'required|mimes:mp3,wav,ogg,flac|max:20971520', 'file' => 'required|mimes:mp3,wav,ogg,flac|max:20971520',
'type' => 'nullable|in:public,private', 'type' => 'nullable|in:public,private',
'image_id' => 'nullable|exists:images,id', 'image_id' => 'nullable|exists:images,id',
'image' => 'nullable|image|max:8192',
'playlist_id' => 'nullable|exists:music_playlists,id', // single (backward compatible) 'playlist_id' => 'nullable|exists:music_playlists,id', // single (backward compatible)
'playlist_ids' => 'nullable|array', // multiple 'playlist_ids' => 'nullable|array', // multiple
'playlist_ids.*' => 'integer|exists:music_playlists,id', 'playlist_ids.*' => 'integer|exists:music_playlists,id',
@@ -165,13 +168,16 @@ public function store(Request $request)
], 500); ], 500);
} }
// An uploaded image file takes precedence over a provided image_id.
$imageId = $this->uploadedImageId($request) ?? ($data['image_id'] ?? null);
$music = Music::create([ $music = Music::create([
'user_id' => auth()->id(), 'user_id' => auth()->id(),
'title' => $data['title'], 'title' => $data['title'],
'artist' => $data['artist'] ?? null, 'artist' => $data['artist'] ?? null,
'file_path' => $path, 'file_path' => $path,
'type' => $data['type'] ?? 'private', 'type' => $data['type'] ?? 'private',
'image_id' => $data['image_id'] ?? null, 'image_id' => $imageId,
'duration' => $data['duration'] ?? null, // Store as string 'duration' => $data['duration'] ?? null, // Store as string
'is_active' => true, 'is_active' => true,
]); ]);
@@ -234,6 +240,7 @@ public function update(Request $request, $id)
'type' => 'nullable|in:public,private', 'type' => 'nullable|in:public,private',
'file' => 'nullable|mimes:mp3,wav,ogg,flac|max:20971520', 'file' => 'nullable|mimes:mp3,wav,ogg,flac|max:20971520',
'image_id' => 'nullable|exists:images,id', 'image_id' => 'nullable|exists:images,id',
'image' => 'nullable|image|max:8192',
'duration' => 'nullable|integer|min:1', 'duration' => 'nullable|integer|min:1',
'is_active' => 'nullable|boolean', 'is_active' => 'nullable|boolean',
]); ]);
@@ -245,8 +252,15 @@ public function update(Request $request, $id)
$music->file_path = $path; $music->file_path = $path;
} }
// Update only provided fields // Update only provided fields (drop the raw file input from mass-assign).
$music->fill($data); $music->fill(collect($data)->except('image')->toArray());
// An uploaded image file takes precedence over a provided image_id.
$uploadedImageId = $this->uploadedImageId($request);
if ($uploadedImageId !== null) {
$music->image_id = $uploadedImageId;
}
$music->save(); $music->save();
return response()->json([ return response()->json([
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace App\Traits;
use App\Models\Image;
use Illuminate\Http\Request;
trait HandlesImageUpload
{
/**
* If the request carries an uploaded image file, store it, create an Image
* record for it, and return that record's id. Returns null when no file is
* present so callers can fall back to a provided image_id.
*/
protected function uploadedImageId(Request $request, string $field = 'image'): ?int
{
if (!$request->hasFile($field)) {
return null;
}
$path = $request->file($field)->store('images', 'public');
return Image::create([
'user_id' => auth()->id(),
'path' => $path,
'type' => 'public',
])->id;
}
}