validate([ 'stars' => 'required|integer|min:1|max:5', ]); $model = $this->getModel($type, $id); $this->checkAccess($model); $rating = $model->ratings()->updateOrCreate( ['user_id' => auth()->id()], ['stars' => $request->stars] ); return response()->json([ 'message' => 'Rating submitted successfully', 'rating' => $rating, 'average_rating' => $model->fresh()->average_rating, 'user_rating' => $rating->stars, 'total_ratings' => $model->fresh()->ratings_count, ]); } /** * Get user's rating for a model */ public function getUserRating($type, $id) { $model = $this->getModel($type, $id); $rating = $model->ratings() ->where('user_id', auth()->id()) ->first(); return response()->json([ 'rating' => $rating ? $rating->stars : null, ]); } /** * Delete user's rating */ public function deleteRating($type, $id) { $model = $this->getModel($type, $id); $deleted = $model->ratings() ->where('user_id', auth()->id()) ->delete(); return response()->json([ 'message' => $deleted ? 'Rating deleted successfully' : 'No rating found', ]); } /** * Get all ratings for a model */ public function getRatings($type, $id) { $model = $this->getModel($type, $id); $this->checkAccess($model); $ratings = $model->ratings() ->with('user') ->latest() ->paginate(20); return response()->json([ 'average' => $model->average_rating, 'total' => $model->ratings_count, 'ratings' => $ratings, ]); } /** * Get top rated items */ public function topRated($type) { $modelClass = $this->getModelClass($type); $userId = auth()->id(); $items = $modelClass::with(['image', 'user']) ->withAvg('ratings', 'stars') ->where(function($query) use ($modelClass, $userId) { if (method_exists($modelClass, 'isAccessible')) { // Use model-specific access logic } elseif (property_exists($modelClass, 'type')) { $query->where('type', 'public') ->orWhere(function($q) use ($userId) { $q->where('type', 'private') ->where('user_id', $userId); }); } }) ->having('ratings_avg_stars', '>', 0) ->orderBy('ratings_avg_stars', 'desc') ->limit(10) ->get(); return response()->json($items); } private function getModel($type, $id) { $modelClass = $this->getModelClass($type); $model = $modelClass::findOrFail($id); return $model; } private function getModelClass($type) { $models = [ 'music' => \App\Models\Music::class, 'media' => \App\Models\Media::class, ]; if (!isset($models[$type])) { abort(404, 'Invalid model type'); } return $models[$type]; } private function checkAccess($model) { // Check if model has 'type' property (public/private) if (property_exists($model, 'type') && $model->type === 'private') { if (auth()->id() !== $model->user_id) { abort(403, 'You do not have access to this item'); } } } }