From 00d8b9687bb987632a4fbb1e3f0372bfacccda81 Mon Sep 17 00:00:00 2001 From: AmirmahdiNourkazemi Date: Sat, 13 Jun 2026 13:16:17 +0330 Subject: [PATCH] feat: add similar_media --- app/Http/Controllers/MediaController.php | 49 +++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/MediaController.php b/app/Http/Controllers/MediaController.php index 7042d04..4c913c6 100644 --- a/app/Http/Controllers/MediaController.php +++ b/app/Http/Controllers/MediaController.php @@ -377,13 +377,15 @@ public function show($id) // Get user's specific comment $userComment = $media->userComment(); - + // Get paginated comments $comments = $media->comments() ->with('user') ->latest() ->paginate(15); + $similarMedia = $this->similarMedia($media); + return response()->json([ 'id' => $media->id, 'title' => $media->title, @@ -417,8 +419,53 @@ public function show($id) 'user_comment_id' => $media->user_comment_id, ], 'comments' => $comments, + 'similar_media' => $similarMedia, ]); } + +// Media that shares categories / subcategories / tags with the given one, +// ranked by how much they overlap. Excludes the media itself. +private function similarMedia(Media $media, int $limit = 5) +{ + $categoryIds = $media->categories->pluck('id')->all(); + $subCategoryIds = $media->subCategories->pluck('id')->all(); + $tagIds = $media->tags->pluck('id')->all(); + + if (!$categoryIds && !$subCategoryIds && !$tagIds) { + return collect(); + } + + $userId = auth()->id(); + + return Media::query() + ->where('media.id', '!=', $media->id) + ->where('media.type', $media->type) + ->where(function ($q) use ($userId) { + $q->where('visibility', 'public')->orWhere('user_id', $userId); + }) + ->where(function ($q) use ($categoryIds, $subCategoryIds, $tagIds) { + if ($categoryIds) { + $q->orWhereHas('categories', fn ($c) => $c->whereIn('categories.id', $categoryIds)); + } + if ($subCategoryIds) { + $q->orWhereHas('subCategories', fn ($s) => $s->whereIn('sub_categories.id', $subCategoryIds)); + } + if ($tagIds) { + $q->orWhereHas('tags', fn ($t) => $t->whereIn('tags.id', $tagIds)); + } + }) + ->withCount([ + 'categories as category_matches' => fn ($c) => $c->whereIn('categories.id', $categoryIds ?: [0]), + 'subCategories as subcategory_matches' => fn ($s) => $s->whereIn('sub_categories.id', $subCategoryIds ?: [0]), + 'tags as tag_matches' => fn ($t) => $t->whereIn('tags.id', $tagIds ?: [0]), + ]) + ->with(['image', 'detailImage', 'categories', 'subCategories', 'tags']) + ->orderByRaw('(category_matches + subcategory_matches + tag_matches) desc') + ->orderByDesc('created_at') + ->limit($limit) + ->get(); +} + public function rate(Request $request, $mediaId) { $request->validate([