fix: music test apis
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
use App\Models\MusicPlaylist;
|
use App\Models\MusicPlaylist;
|
||||||
|
use App\Models\MusicCategory;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public function index()
|
|||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
@@ -26,14 +28,54 @@ public function store(Request $request)
|
|||||||
'is_active' => 'nullable|boolean',
|
'is_active' => 'nullable|boolean',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data['slug'] = Str::slug($data['name']);
|
// Check for duplicate name
|
||||||
|
$slug = Str::slug($data['name']);
|
||||||
|
$existingCategory = MusicCategory::where('slug', $slug)->first();
|
||||||
|
|
||||||
|
if ($existingCategory) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'A category with this name already exists',
|
||||||
|
'errors' => [
|
||||||
|
'name' => ['The category name "' . $data['name'] . '" is already taken. Please use a different name.']
|
||||||
|
]
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: Check for duplicate name with case-insensitive comparison
|
||||||
|
$existingName = MusicCategory::whereRaw('LOWER(name) = ?', [strtolower($data['name'])])->first();
|
||||||
|
if ($existingName) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'A category with a similar name already exists',
|
||||||
|
'errors' => [
|
||||||
|
'name' => ['Category "' . $existingName->name . '" already exists. Please use a different name.']
|
||||||
|
]
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['slug'] = $slug;
|
||||||
$category = MusicCategory::create($data);
|
$category = MusicCategory::create($data);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Category created successfully',
|
'message' => 'Category created successfully',
|
||||||
'category' => $category->load('image')
|
'category' => $category->load('image')
|
||||||
], 201);
|
], 201);
|
||||||
|
|
||||||
|
} catch (\Illuminate\Database\QueryException $e) {
|
||||||
|
// Handle database duplicate entry error (if unique constraint exists)
|
||||||
|
if ($e->errorInfo[1] == 1062) { // MySQL duplicate entry error code
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'A category with this name already exists',
|
||||||
|
'errors' => [
|
||||||
|
'name' => ['The category name must be unique.']
|
||||||
|
]
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'An error occurred while creating the category',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($id)
|
public function show($id)
|
||||||
|
|||||||
@@ -8,7 +8,28 @@
|
|||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class MusicController extends Controller
|
class MusicController extends Controller
|
||||||
{ public function getMusicByPlaylist($playlistId)
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$userId = auth()->id();
|
||||||
|
|
||||||
|
$music = Music::with(['image', 'playlist'])
|
||||||
|
->where('type', 'public')
|
||||||
|
->orWhere(function($query) use ($userId) {
|
||||||
|
$query->where('type', 'private')
|
||||||
|
->where('user_id', $userId);
|
||||||
|
})
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $music,
|
||||||
|
'total' => $music->count()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMusicByPlaylist($playlistId)
|
||||||
{
|
{
|
||||||
$playlist = MusicPlaylist::findOrFail($playlistId);
|
$playlist = MusicPlaylist::findOrFail($playlistId);
|
||||||
|
|
||||||
@@ -79,15 +100,40 @@ public function updateOrder(Request $request)
|
|||||||
// ✅ Upload music
|
// ✅ Upload music
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'artist' => 'nullable|string|max:255',
|
'artist' => 'nullable|string|max:255',
|
||||||
'file' => 'required|mimes:mp3,wav,ogg|max:10240', // max 10MB
|
'file' => 'required|mimes:mp3,wav,ogg|max:20971520',
|
||||||
'type' => 'nullable|in:public,private',
|
'type' => 'nullable|in:public,private',
|
||||||
'image_id' => 'nullable|exists:images,id',
|
'image_id' => 'nullable|exists:images,id',
|
||||||
|
'playlist_id' => 'nullable|exists:music_playlists,id',
|
||||||
|
'duration' => 'nullable|string|regex:/^(?:\d+:)?[0-5]?\d:[0-5]\d$/', // validates mm:ss or hh:mm:ss
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$path = $request->file('file')->store('music', 'public');
|
// Handle file upload
|
||||||
|
if (!$request->hasFile('file')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'No file was uploaded'
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $request->file('file');
|
||||||
|
|
||||||
|
// Validate file size
|
||||||
|
if ($file->getSize() > 20971520) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'File size exceeds 10MB limit'
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $file->store('music', 'public');
|
||||||
|
|
||||||
|
if (!$path) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Failed to store the file'
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
|
||||||
$music = Music::create([
|
$music = Music::create([
|
||||||
'user_id' => auth()->id(),
|
'user_id' => auth()->id(),
|
||||||
@@ -96,39 +142,46 @@ public function store(Request $request)
|
|||||||
'file_path' => $path,
|
'file_path' => $path,
|
||||||
'type' => $data['type'] ?? 'private',
|
'type' => $data['type'] ?? 'private',
|
||||||
'image_id' => $data['image_id'] ?? null,
|
'image_id' => $data['image_id'] ?? null,
|
||||||
|
'playlist_id' => $data['playlist_id'] ?? null,
|
||||||
|
'duration' => $data['duration'] ?? null, // Store as string
|
||||||
|
'order' => $this->getNextOrderInPlaylist($data['playlist_id'] ?? null),
|
||||||
|
'is_active' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Music uploaded successfully',
|
'message' => 'Music uploaded successfully',
|
||||||
'music' => $music->load('image'),
|
'music' => $music->load(['image', 'playlist', 'tags']),
|
||||||
'url' => asset('storage/' . $path),
|
'url' => asset('storage/' . $path),
|
||||||
]);
|
], 201);
|
||||||
|
|
||||||
|
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Validation failed',
|
||||||
|
'errors' => $e->errors()
|
||||||
|
], 422);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'An error occurred while uploading the music',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Get all public + user private music
|
// Helper method to get next order number in playlist
|
||||||
public function all()
|
private function getNextOrderInPlaylist($playlistId)
|
||||||
{
|
{
|
||||||
$userId = auth()->id();
|
if (!$playlistId) {
|
||||||
|
return 0;
|
||||||
$music = Music::where('type', 'public')
|
|
||||||
->orWhere(function($query) use ($userId) {
|
|
||||||
$query->where('type', 'private')->where('user_id', $userId);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$music = Music::with('image') // eager load image
|
|
||||||
->where('type', 'public')
|
|
||||||
->orWhere(function($query) use ($userId) {
|
|
||||||
$query->where('type', 'private')->where('user_id', $userId);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return response()->json($music);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Update music
|
$maxOrder = Music::where('playlist_id', $playlistId)->max('order');
|
||||||
|
return ($maxOrder ?? -1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Update music with string duration
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
$music = Music::where('id', $id)->where('user_id', auth()->id())->firstOrFail();
|
$music = Music::where('id', $id)->where('user_id', auth()->id())->firstOrFail();
|
||||||
|
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
@@ -137,23 +190,54 @@ public function update(Request $request, $id)
|
|||||||
'type' => 'nullable|in:public,private',
|
'type' => 'nullable|in:public,private',
|
||||||
'file' => 'nullable|mimes:mp3,wav,ogg|max:10240',
|
'file' => 'nullable|mimes:mp3,wav,ogg|max:10240',
|
||||||
'image_id' => 'nullable|exists:images,id',
|
'image_id' => 'nullable|exists:images,id',
|
||||||
|
'playlist_id' => 'nullable|exists:music_playlists,id',
|
||||||
|
'duration' => 'nullable|string|regex:/^(?:\d+:)?[0-5]?\d:[0-5]\d$/',
|
||||||
|
'order' => 'nullable|integer',
|
||||||
|
'is_active' => 'nullable|boolean',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($request->hasFile('file')) {
|
if ($request->hasFile('file')) {
|
||||||
|
// Delete old file
|
||||||
Storage::disk('public')->delete($music->file_path);
|
Storage::disk('public')->delete($music->file_path);
|
||||||
$path = $request->file('file')->store('music', 'public');
|
$path = $request->file('file')->store('music', 'public');
|
||||||
$music->file_path = $path;
|
$music->file_path = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update only provided fields
|
||||||
$music->fill($data);
|
$music->fill($data);
|
||||||
$music->save();
|
$music->save();
|
||||||
|
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Music updated successfully',
|
'message' => 'Music updated successfully',
|
||||||
'music' => $music->load('image'),
|
'music' => $music->load(['image', 'playlist', 'tags']),
|
||||||
'url' => asset('storage/' . $music->file_path),
|
'url' => asset('storage/' . $music->file_path),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'An error occurred while updating the music',
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ✅ Get all public + user private music
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$userId = auth()->id();
|
||||||
|
|
||||||
|
$music = Music::with(['image', 'playlist', 'tags'])
|
||||||
|
->where(function($query) use ($userId) {
|
||||||
|
$query->where('type', 'public')
|
||||||
|
->orWhere(function($q) use ($userId) {
|
||||||
|
$q->where('type', 'private')
|
||||||
|
->where('user_id', $userId);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
->findOrFail($id);
|
||||||
|
|
||||||
|
return response()->json($music);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Delete music
|
// ✅ Delete music
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo; // ← Add this
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany; // ← Add this
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany; // ← Add this
|
||||||
class Music extends Model
|
class Music extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
@@ -18,6 +21,9 @@ class Music extends Model
|
|||||||
'duration' => 'string',
|
'duration' => 'string',
|
||||||
'order' => 'integer',
|
'order' => 'integer',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
|
];
|
||||||
|
protected $attributes = [
|
||||||
|
'type' => 'public', // Default value
|
||||||
];
|
];
|
||||||
// Relation to user (optional)
|
// Relation to user (optional)
|
||||||
public function user()
|
public function user()
|
||||||
@@ -30,7 +36,7 @@ public function playlist(): BelongsTo
|
|||||||
}
|
}
|
||||||
public function tags(): BelongsToMany
|
public function tags(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Tag::class, 'music_tag');
|
return $this->belongsToMany(Tag::class, 'music_tags');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $appends = ['url', 'image_url'];
|
protected $appends = ['url', 'image_url'];
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo; // ← Add this
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany; // ← Add this
|
||||||
class MusicCategory extends Model
|
class MusicCategory extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'music_categories';
|
protected $table = 'music_categories';
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo; // ← Add this
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany; // ← Add this
|
||||||
class MusicPlaylist extends Model
|
class MusicPlaylist extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'music_playlists';
|
protected $table = 'music_playlists';
|
||||||
|
|||||||
+2
-1
@@ -3,7 +3,8 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo; // ← Add this
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany; // ← Add this
|
||||||
class Tag extends Model
|
class Tag extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = ['name'];
|
protected $fillable = ['name'];
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
|
||||||
|
<IfModule mod_php7.c>
|
||||||
|
php_value post_max_size 128M
|
||||||
|
php_value upload_max_filesize 128M
|
||||||
|
php_value max_execution_time 300
|
||||||
|
php_value max_input_time 300
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_php8.c>
|
||||||
|
php_value post_max_size 128M
|
||||||
|
php_value upload_max_filesize 128M
|
||||||
|
php_value max_execution_time 300
|
||||||
|
php_value max_input_time 300
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
<IfModule mod_negotiation.c>
|
<IfModule mod_negotiation.c>
|
||||||
Options -MultiViews -Indexes
|
Options -MultiViews -Indexes
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
phpinfo();
|
||||||
|
?>
|
||||||
+6
-4
@@ -15,6 +15,8 @@
|
|||||||
use App\Http\Controllers\ImageController;
|
use App\Http\Controllers\ImageController;
|
||||||
use App\Http\Controllers\MusicController;
|
use App\Http\Controllers\MusicController;
|
||||||
use App\Http\Controllers\MediaController;
|
use App\Http\Controllers\MediaController;
|
||||||
|
use App\Http\Controllers\MusicCategoryController;
|
||||||
|
use App\Http\Controllers\MusicPlaylistController;
|
||||||
|
|
||||||
Route::get('/test-hash', function() {
|
Route::get('/test-hash', function() {
|
||||||
$plain = 'amnk1380';
|
$plain = 'amnk1380';
|
||||||
@@ -120,10 +122,10 @@
|
|||||||
|
|
||||||
/// music
|
/// music
|
||||||
|
|
||||||
Route::post('/music', [MusicController::class, 'store']);
|
// Route::post('/music', [MusicController::class, 'store']);
|
||||||
Route::get('/music/all', [MusicController::class, 'all']);
|
// Route::get('/music/all', [MusicController::class, 'all']);
|
||||||
Route::put('/music/{id}', [MusicController::class, 'update']);
|
// Route::put('/music/{id}', [MusicController::class, 'update']);
|
||||||
Route::delete('/music/{id}', [MusicController::class, 'destroy']);
|
// Route::delete('/music/{id}', [MusicController::class, 'destroy']);
|
||||||
|
|
||||||
|
|
||||||
Route::get('/slider', [SliderController::class, 'index']); // list all sliders
|
Route::get('/slider', [SliderController::class, 'index']); // list all sliders
|
||||||
|
|||||||
Reference in New Issue
Block a user