305 lines
9.8 KiB
PHP
305 lines
9.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use App\Models\MusicPlaylist;
|
|
use App\Models\Music;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class MusicController extends Controller
|
|
{
|
|
|
|
// Add this new method to your MusicController
|
|
public function getAllMusic()
|
|
{
|
|
$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 as array directly (not wrapped in 'data' object)
|
|
// to match what your old Flutter app expects
|
|
return response()->json($music);
|
|
}
|
|
|
|
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);
|
|
|
|
$music = Music::where('playlist_id', $playlistId)
|
|
->where('is_active', true)
|
|
->with(['image', 'tags'])
|
|
->orderBy('order')
|
|
->get();
|
|
|
|
return response()->json([
|
|
'playlist' => $playlist->load('image'),
|
|
'musics' => $music
|
|
]);
|
|
}
|
|
|
|
public function addToPlaylist(Request $request, $musicId)
|
|
{
|
|
$music = Music::where('id', $musicId)
|
|
->where(function($q) {
|
|
$q->where('type', 'public')
|
|
->orWhere('user_id', auth()->id());
|
|
})
|
|
->firstOrFail();
|
|
|
|
$data = $request->validate([
|
|
'playlist_id' => 'required|exists:music_playlists,id',
|
|
'order' => 'nullable|integer',
|
|
]);
|
|
|
|
$music->update([
|
|
'playlist_id' => $data['playlist_id'],
|
|
'order' => $data['order'] ?? $music->order,
|
|
]);
|
|
|
|
return response()->json([
|
|
'message' => 'Music added to playlist successfully',
|
|
'music' => $music->load(['image', 'playlist'])
|
|
]);
|
|
}
|
|
|
|
public function removeFromPlaylist($musicId)
|
|
{
|
|
$music = Music::where('id', $musicId)
|
|
->where('user_id', auth()->id())
|
|
->firstOrFail();
|
|
|
|
$music->update(['playlist_id' => null]);
|
|
|
|
return response()->json(['message' => 'Music removed from playlist']);
|
|
}
|
|
|
|
public function updateOrder(Request $request)
|
|
{
|
|
$data = $request->validate([
|
|
'musics' => 'required|array',
|
|
'musics.*.id' => 'required|exists:music,id',
|
|
'musics.*.order' => 'required|integer',
|
|
]);
|
|
|
|
foreach ($data['musics'] as $item) {
|
|
Music::where('id', $item['id'])
|
|
->where('user_id', auth()->id())
|
|
->update(['order' => $item['order']]);
|
|
}
|
|
|
|
return response()->json(['message' => 'Order updated successfully']);
|
|
}
|
|
// ✅ Upload music
|
|
public function store(Request $request)
|
|
{
|
|
try {
|
|
$data = $request->validate([
|
|
'title' => 'required|string|max:255',
|
|
'artist' => 'nullable|string|max:255',
|
|
'file' => 'required|mimes:mp3,wav,ogg,flac|max:20971520',
|
|
'type' => 'nullable|in:public,private',
|
|
'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
|
|
]);
|
|
|
|
// 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([
|
|
'user_id' => auth()->id(),
|
|
'title' => $data['title'],
|
|
'artist' => $data['artist'] ?? null,
|
|
'file_path' => $path,
|
|
'type' => $data['type'] ?? 'private',
|
|
'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([
|
|
'message' => 'Music uploaded successfully',
|
|
'music' => $music->load(['image', 'playlist', 'tags']),
|
|
'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);
|
|
}
|
|
}
|
|
|
|
// Helper method to get next order number in playlist
|
|
private function getNextOrderInPlaylist($playlistId)
|
|
{
|
|
if (!$playlistId) {
|
|
return 0;
|
|
}
|
|
|
|
$maxOrder = Music::where('playlist_id', $playlistId)->max('order');
|
|
return ($maxOrder ?? -1) + 1;
|
|
}
|
|
|
|
// ✅ Update music with string duration
|
|
public function update(Request $request, $id)
|
|
{
|
|
try {
|
|
$music = Music::where('id', $id)->where('user_id', auth()->id())->firstOrFail();
|
|
|
|
$data = $request->validate([
|
|
'title' => 'nullable|string|max:255',
|
|
'artist' => 'nullable|string|max:255',
|
|
'type' => 'nullable|in:public,private',
|
|
'file' => 'nullable|mimes:mp3,wav,ogg,flac|max:20971520',
|
|
'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')) {
|
|
// Delete old file
|
|
Storage::disk('public')->delete($music->file_path);
|
|
$path = $request->file('file')->store('music', 'public');
|
|
$music->file_path = $path;
|
|
}
|
|
|
|
// Update only provided fields
|
|
$music->fill($data);
|
|
$music->save();
|
|
|
|
return response()->json([
|
|
'message' => 'Music updated successfully',
|
|
'music' => $music->load(['image', 'playlist', 'tags']),
|
|
'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',
|
|
'comments' => function($query) {
|
|
$query->with('user')->latest()->limit(10);
|
|
},
|
|
'ratings'
|
|
])
|
|
->where(function($query) use ($userId) {
|
|
$query->where('type', 'public')
|
|
->orWhere(function($q) use ($userId) {
|
|
$q->where('type', 'private')
|
|
->where('user_id', $userId);
|
|
});
|
|
})
|
|
->findOrFail($id);
|
|
|
|
// Get user's specific comment
|
|
$userComment = $music->userComment();
|
|
|
|
// Get paginated comments for the response
|
|
$comments = $music->comments()
|
|
->with('user')
|
|
->latest()
|
|
->paginate(15);
|
|
|
|
return response()->json([
|
|
'music' => $music,
|
|
'statistics' => [
|
|
'average_rating' => $music->average_rating,
|
|
'total_ratings' => $music->ratings_count,
|
|
'total_comments' => $music->comments_count,
|
|
'rating_distribution' => $music->rating_distribution,
|
|
],
|
|
'user_interaction' => [
|
|
'has_rated' => $music->has_user_rated,
|
|
'user_rating' => $music->user_rating,
|
|
'has_commented' => $music->has_user_commented,
|
|
'user_comment' => $music->user_comment,
|
|
'user_comment_id' => $music->user_comment_id,
|
|
],
|
|
'comments' => $comments,
|
|
]);
|
|
}
|
|
|
|
// ✅ Delete music
|
|
public function destroy($id)
|
|
{
|
|
$music = Music::where('id', $id)->where('user_id', auth()->id())->firstOrFail();
|
|
Storage::disk('public')->delete($music->file_path);
|
|
$music->delete();
|
|
|
|
return response()->json(['message' => 'Music deleted successfully']);
|
|
}
|
|
}
|