feat: deep link added

This commit is contained in:
2026-09-02 10:30:02 +03:30
parent 3f3b5b1d69
commit a3cda12560
9 changed files with 256 additions and 11 deletions
+54 -1
View File
@@ -23,7 +23,19 @@ public function index(Request $request)
return response()->json($this->playlistCategories($request)->values());
}
$query = Category::query()->withCount('subcategories');
// Admin listing of deep-link (hidden) categories: ?deeplink_only=1
// returns only the hidden records so the admin can manage their links.
if ($request->boolean('deeplink_only')) {
$hidden = Category::query()->withCount('subcategories')
->where('is_deeplink_only', true)
->orderBy('order')
->orderBy('name')
->get();
return response()->json($hidden);
}
$query = Category::query()->withCount('subcategories')->where('is_deeplink_only', false);
if ($request->filled('type')) {
$query->where('type', $type);
@@ -91,6 +103,7 @@ public function store(Request $request)
'order' => 'nullable|integer',
'description' => 'nullable|string',
'icon' => 'nullable|file|extensions:jpg,jpeg,png,gif,webp,bmp,svg|max:8192',
'is_deeplink_only' => 'nullable|boolean',
]);
$category = Category::create([
@@ -101,6 +114,7 @@ public function store(Request $request)
'icon' => $request->hasFile('icon')
? $this->storeUpload($request->file('icon'), 'categories/icons')
: null,
'is_deeplink_only' => $data['is_deeplink_only'] ?? false,
]);
return response()->json([
@@ -111,11 +125,45 @@ public function store(Request $request)
public function show($id)
{
// Includes hidden (deeplink-only) categories too, so a category reached
// through its deep link can still be shown to the app.
$category = Category::with('subcategories')->withCount('subcategories')->findOrFail($id);
return response()->json($category);
}
// Public (no auth) deep link lookup by ID. Hidden (deeplink-only) categories
// are the only ones served here, since they are discovered via the deep link.
public function publicShow($id)
{
$category = Category::with(['subcategories' => function ($q) {
$q->orderBy('name')->with(['media' => function ($m) {
$m->with(['image', 'detailImage', 'tags'])->latest();
}]);
}])->where('id', $id)->where('is_deeplink_only', true)->firstOrFail();
return response()->json([
'category' => [
'id' => $category->id,
'name' => $category->name,
'description' => $category->description,
'icon_url' => $category->icon_url,
'icon' => $category->icon,
'type' => $category->type,
'is_deeplink_only' => $category->is_deeplink_only,
'deep_link' => $category->deep_link,
],
'sub_categories' => $category->subcategories->map(fn ($sub) => [
'sub_category' => [
'id' => $sub->id,
'name' => $sub->name,
'description' => $sub->description,
],
'medias' => $sub->media,
])->values(),
]);
}
// Category with each of its sub-categories and that sub-category's medias.
public function grouped($id)
{
@@ -163,6 +211,7 @@ public function update(Request $request, $id)
'order' => 'nullable|integer',
'description' => 'nullable|string',
'icon' => 'nullable|file|extensions:jpg,jpeg,png,gif,webp,bmp,svg|max:8192',
'is_deeplink_only' => 'nullable|boolean',
]);
if (array_key_exists('type', $data) && $data['type'] !== null) {
@@ -184,6 +233,10 @@ public function update(Request $request, $id)
$category->icon = $this->storeUpload($request->file('icon'), 'categories/icons');
}
if (array_key_exists('is_deeplink_only', $data)) {
$category->is_deeplink_only = $data['is_deeplink_only'];
}
$category->save();
return response()->json([