book_id); $law = Law::find($book?->law_id); if ($this->isLockedForCurrentUser($law)) { return $this->failed([], ['title' => 'Subscription Required', 'message' => 'This content requires an active subscription.'], 403); } $arts = Art::with(['chapter', 'part', 'volum', 'law', 'book', 'section', 'gate'])->where('book_id', $request->book_id)->orderBy('number')->get(); $arts = $arts->map(function ($art) { return [ 'id' => $art->id, 'text' => $art->text, 'number' => $art->number, 'chapter' => $art->chapter != null ? [ 'id' => $art->chapter->id, 'title' => $art->chapter->title, 'number' => $art->chapter->number, ] : null, 'part' => $art->part != null ? [ 'id' => $art->part->id, 'title' => $art->part->title, 'number' => $art->part->number, ] : null, 'volum' => $art->volum != null ? [ 'id' => $art->volum->id, 'title' => $art->volum->title, 'number' => $art->volum->number, ] : null, 'law' => $art->law != null ? [ 'id' => $art->law->id, 'title' => $art->law->title, 'number' => $art->law->number, ] : null, 'book' => $art->book != null ? [ 'id' => $art->book->id, 'title' => $art->book->title, 'number' => $art->book->number, ] : null, 'section' => $art->section != null ? [ 'id' => $art->section->id, 'title' => $art->section->title, 'number' => $art->section->number, ] : null, 'gate' => $art->gate != null ? [ 'id' => $art->gate->id, 'title' => $art->gate->title, 'number' => $art->gate->number, ] : null, ]; }); return response()->json(['arts' => $arts]); } public function single($id) { $art = Art::select('id', 'title', 'number', 'text', 'law_id')->find($id); if (!$art) { return $this->failed([], 'Art not found'); } $law = Law::find($art?->law_id); if ($this->isLockedForCurrentUser($law)) { return $this->failed([], ['title' => 'Subscription Required', 'message' => 'This content requires an active subscription.'], 403); } $art->is_like = $this->isLiked($art->id); $art->note = Note::select('id', 'note', 'color_code','created_at')->where('user_id', auth()->user()->id)->where('art_id', $id)->get(); $art->category = $law?->category?->name; $art->route = array_values($this->route(Art::class, $art)); $previousArt = Art::select('id', 'title', 'number', 'text', 'law_id') ->where('law_id',$art->law_id) ->where('number', '<', $art->number) ->orderBy('number', 'desc') ->first(); if ($previousArt) { $previousLaw = Law::find($previousArt->law_id); $previousArt->is_like = $this->isLiked($previousArt->id); $previousArt->note = Note::select('id', 'note', 'color_code')->where('user_id', auth()->user()->id)->where('art_id', $previousArt->id)->get(); $previousArt->category = $previousLaw?->category?->name; $previousArt->route = array_values($this->route(Art::class, $previousArt)); } $nextArt = Art::select('id', 'title', 'number', 'text', 'law_id') ->where('law_id',$art->law_id) ->where('number', '>', $art->number) ->orderBy('number') ->first(); if ($nextArt) { $nextLaw = Law::find($nextArt->law_id); $nextArt->is_like = $this->isLiked($nextArt->id); $nextArt->note = Note::select('id', 'note', 'color_code')->where('user_id', auth()->user()->id)->where('art_id', $nextArt->id)->get(); $nextArt->category = $nextLaw?->category?->name; $nextArt->route = array_values($this->route(Art::class, $nextArt)); } $results = array_values(array_filter([$previousArt, $art, $nextArt])); return $this->success($results); } public function like(Art $art) { $userId = auth()->id(); $existingLike = LikeArt::query()->where('art_id', $art->id) ->where('user_id', $userId) ->first(); if ($existingLike) { $existingLike->delete(); return $this->success(null, 'Success', 'Art unliked successfully'); } LikeArt::create([ 'art_id' => $art->id, 'user_id' => $userId, ]); return $this->success(null, 'Success', 'Art liked successfully'); } private function isLiked($art_id): bool { return LikeArt::query()->where('art_id', $art_id) ->where('user_id', auth()->user()->id) ->exists(); } private function isLockedForCurrentUser(?Law $law): bool { return !auth()->user()->isSubscriber() && (bool) $law?->is_locked; } public function likes() { $likes = LikeArt::query()->where('user_id', auth()->user()->id) ->with('art.law') ->get() ->map(function ($q) { $isLocked = $this->isLockedForCurrentUser($q->art?->law); return [ 'id' => $q->art->id, 'title' => $q->art->title, 'text' => $isLocked ? null : $q->art->text ]; }); return $this->success($likes); } public function search(Request $request) { $validated = $request->validate([ 'book_id' => 'nullable|array', 'volume_id' => 'nullable|array', 'division_id' => 'nullable|array', 'section_id' => 'nullable|array', 'part_id' => 'nullable|array', 'gate_id' => 'nullable|array', 'law_id' => 'nullable|array', 'chapter_id' => 'nullable|array', 'branch_id' => 'nullable|array', 'category_id' => 'nullable|int', 'per_page' => 'nullable|integer', 'search' => 'nullable|string' ]); $models = [ Law::class, Volum::class, Book::class, Division::class, Section::class, Chapter::class, Part::class, Gate::class, Branch::class, Art::class ]; $results = []; foreach ($models as $modelClass) { $results = array_merge($results, $this->searchModel($modelClass, $validated)); } return $this->success($results); } private function searchModel($modelClass, $validated) { $query = $modelClass::query(); $filters = [ 'law_id', 'volume_id', 'division_id', 'section_id', 'part_id', 'gate_id', 'chapter_id', 'branch_id' ]; $model = new $modelClass; if ($model->getTable() == 'art') { $query->where(function ($query) use ($validated, $filters) { if (!empty($validated['search'])) { $query->where(function ($q) use ($validated) { $q->where('title', 'LIKE', "%{$validated['search']}%") ->orWhere('text', 'LIKE', "%{$validated['search']}%"); }); } foreach ($filters as $filter) { if (!empty($validated[$filter])) { $query->whereIn($filter, $validated[$filter]); } } }); if (!empty($validated['category_id'])) { $query->whereIn('law_id', Category::where('type', $this->convertValueTo($validated['category_id']))->get()->pluck('id')); } $items = $query->paginate($validated['per_page'] ?? 10); return $items->map(function ($item) use ($validated, $modelClass) { $text = $item->text ?? ''; $search = preg_quote($validated['search'] ?? '', '/'); if (!empty($text) && preg_match('/\b(.{0,50})\b(' . $search . ')\b(.{0,50})\b/i', $text, $matches)) { $context = trim($matches[1] ?? '') . ' ' . $matches[2] . ' ' . trim($matches[3] ?? ''); } else { $context = $text; } $law = Law::find($item->law_id); $isLocked = $this->isLockedForCurrentUser($law); return [ 'id' => $item->id, 'title' => $item->title, 'text' => $isLocked ? null : $context, 'is_locked' => $isLocked, 'type' => 'art', 'route' => array_values($this->route($modelClass, $item)), 'category' => optional($law->category)->name, 'law' => $law?->title, 'count_art' => $law->arts->count(), 'count_volums' => $law->volums->count(), 'price' => $law->price, 'image' => $law->image ]; })->toArray(); } else { $query = $query->where('title', 'LIKE', '%' . ($validated['search'] ?? '') . '%'); } $items = $query->paginate($validated['per_page'] ?? 10); return $items->map(function ($item) use ($modelClass) { $law = Law::find($item?->law_id ?? $item->id); if ((new $modelClass)->getTable() == 'laws') { return [ 'id' => $item->id, 'title' => $item->title, 'number' => $item->number, 'type' => (new $modelClass)->getTable(), 'is_locked' => auth()->user()->isSubscriber() !== false ? false : optional($law)->is_locked, 'route' => array_values($this->route($modelClass, $item)), 'category' => optional($law?->category)?->name ?? '', 'image' => $law->image ]; } else if ((new $modelClass)->getTable() == 'art') { return [ 'id' => $item->id, 'title' => $item->title, 'number' => $item->number, 'type' => (new $modelClass)->getTable(), 'is_locked' => auth()->user()->isSubscriber() !== false ? false : optional($law)->is_locked, 'route' => array_values($this->route($modelClass, $item)), 'law' => $law?->title ?? '', 'image' => $law->image ]; } else { return [ 'id' => $item->id, 'title' => $item->title, 'number' => $item->number, 'type' => (new $modelClass)->getTable(), 'is_locked' => auth()->user()->isSubscriber() !== false ? false : optional($law)->is_locked, 'route' => array_values($this->route($modelClass, $item)), 'law' => $law?->title ?? '', ]; } })->toArray(); } private function route($modelClass, $query) { if ((new $modelClass)->getTable() == 'art') { $route = array_filter([ Law::find($query->law_id)?->title, Volum::find($query->volum_id)?->title, Book::find($query->book_id)?->title, Division::find($query->division_id)?->title, Section::find($query->section_id)?->title, Chapter::find($query->chapter_id)?->title, Part::find($query->part_id)?->title, Gate::find($query->gate_id)?->title, Branch::find($query->branch_id)?->title ]); $route = array_values($route); return $route; } return []; } public function fash_search(Request $request) { $search = $request->input('search'); $models = [ Law::class, Art::class ]; $results = []; foreach ($models as $modelClass) { $results = array_merge($results, $this->searchModelFastSearch($modelClass, $search)); } $models_other = [ Volum::class, Book::class, Division::class, Section::class, Chapter::class, Part::class, Gate::class, Branch::class, ]; $found = false; foreach ($models_other as $modelClass) { if (count($this->searchModelFastSearch($modelClass, $search)) > 0 && !$found) { $results = array_merge($results, $this->searchModelFastSearch($modelClass, $search)); $found = true; } } $models = [ Law::class, Volum::class, Book::class, Division::class, Section::class, Chapter::class, Part::class, Gate::class, Branch::class, Art::class ]; $count_all = 0; foreach ($models as $modelClass) { $count_all += count($this->searchModel($modelClass, $search)); } return $this->success(['items' => $results, 'count' => $count_all]); } private function searchModelFastSearch($modelClass, $search) { $results = $modelClass::searchLimit($search); return $results->map(function ($q) use ($modelClass, $search) { $instance = new $modelClass; $table = $instance->getTable(); if ($table === 'art') { return $this->formatArtResult($q, $search); } return $this->formatGenericResult($q, $table); })->toArray(); } private function formatGenericResult($q, $table) { $category = null; if ($table === 'laws') { $category = Law::where('id', $q->id)->first()?->category?->name; } else { $category = Law::where('id', $q->law_id)->first()?->category?->name; } if ($table !== 'laws') { return [ 'id' => $q->id, 'title' => $q->title, 'type' => $table === 'section' ? 'sections' : $table, 'category' => $category, 'law' => Law::where('id', $q->law_id)->first()?->title ]; } return [ 'id' => $q->id, 'title' => $q->title, 'type' => $table === 'section' ? 'sections' : $table, 'category' => $category, 'image' => Law::where('id', $q->id)->first()?->image ]; } private function formatArtResult($q, $search) { $law = Law::where('id', $q->law_id)->first(); $route = array_filter([ $law?->title, Volum::find($q->volum_id)?->title, Book::find($q->book_id)?->title, Division::find($q->division_id)?->title, Section::find($q->section_id)?->title, Chapter::find($q->chapter_id)?->title, Part::find($q->part_id)?->title, Gate::find($q->gate_id)?->title, Branch::find($q->branch_id)?->title ]); $text = $q->text; $search = preg_quote($search, '/'); if (preg_match('/\b(.{0,50})\b(' . $search . ')\b(.{0,50})\b/i', $text, $matches)) { $context = trim($matches[1]) . ' ' . $matches[2] . ' ' . trim($matches[3]); } else { $context = $text; } $isLocked = $this->isLockedForCurrentUser($law); return [ 'id' => $q->id, 'title' => $q->title, 'text' => $isLocked ? null : $context, 'is_locked' => $isLocked, 'type' => 'art', 'route' => $route, 'category' => $law?->category?->name, 'law' => $law?->title, 'count_art' => $law->arts->count(), 'count_volum' => $law->volums->count(), 'price' => $law->price, 'image' => $law->image ]; } private function convertValueTo($var) { switch ($var) { case 1: return 'hagigi'; break; case 2: return 'kifari'; break; default: return 'kifari'; break; } } }