get('q', '')); $lieux = Lieu::with('lieuType') ->where(function ($query) use ($q) { $query->where('nom_long', DbCompat::like(), "%{$q}%") ->orWhere('nom', DbCompat::like(), "%{$q}%") ->orWhere('code', DbCompat::like(), "%{$q}%"); }) ->orderBy('nom_long') ->limit(25) ->get(); return response()->json($lieux->map(fn ($l) => [ 'id' => $l->id, 'nom_long' => $l->nom_long ?? $l->nom, 'code' => $l->code, 'type' => $l->lieuType?->nom, ])); } public function index(Request $request): View { $this->authorize('viewAny', Lieu::class); $query = Lieu::with(['parent', 'lieuType'])->orderBy('nom_long'); if ($request->filled('lieu_type_id')) { $query->where('lieu_type_id', $request->integer('lieu_type_id')); } if ($request->filled('q')) { $q = trim($request->get('q')); $query->where(function ($wq) use ($q) { $wq->where('nom_long', DbCompat::like(), "%{$q}%") ->orWhere('nom', DbCompat::like(), "%{$q}%") ->orWhere('code', DbCompat::like(), "%{$q}%"); }); } if ($request->filled('lieu_id')) { $ids = $this->getDescendantAndSelfIds($request->integer('lieu_id')); $query->whereIn('id', $ids); } $lieuTypes = LieuType::orderBy('ordre')->get(['id', 'nom']); $lieuSelectionne = $request->filled('lieu_id') ? Lieu::find($request->integer('lieu_id'), ['id', 'nom', 'nom_long']) : null; $lieux = $query->paginate(50)->withQueryString(); return view('lieux.index', compact('lieux', 'lieuTypes', 'lieuSelectionne')); } public function create(): View { $this->authorize('create', Lieu::class); $lieuTypes = LieuType::orderBy('ordre')->get(['id', 'nom']); return view('lieux.create', compact('lieuTypes')); } public function store(StoreLieuRequest $request): RedirectResponse { $lieu = Lieu::create($request->validated()); return redirect()->route('lieux.show', $lieu) ->with('success', 'Lieu créé avec succès.'); } public function show(Lieu $lieu): View { $this->authorize('view', $lieu); $lieu->load('parent', 'enfants', 'lieuType'); return view('lieux.show', compact('lieu')); } public function edit(Lieu $lieu): View { $this->authorize('update', $lieu); $lieu->load('parent', 'lieuType'); $lieuTypes = LieuType::orderBy('ordre')->get(['id', 'nom']); return view('lieux.edit', compact('lieu', 'lieuTypes')); } public function update(UpdateLieuRequest $request, Lieu $lieu): RedirectResponse { $lieu->update($request->validated()); $this->recalculerEnfants($lieu); return redirect()->route('lieux.show', $lieu) ->with('success', 'Lieu mis à jour.'); } public function destroy(Lieu $lieu): RedirectResponse { $this->authorize('delete', $lieu); if ($lieu->enfants()->exists()) { return back()->with('error', 'Impossible de supprimer un lieu qui a des enfants.'); } $lieu->delete(); return redirect()->route('lieux.index') ->with('success', 'Lieu supprimé.'); } private function getDescendantAndSelfIds(int $lieuId): array { $rows = DB::select(" WITH RECURSIVE descendants AS ( SELECT id FROM lieux WHERE id = ? UNION ALL SELECT l.id FROM lieux l INNER JOIN descendants d ON l.lieu_parent_id = d.id ) SELECT id FROM descendants ", [$lieuId]); return collect($rows)->pluck('id')->toArray(); } private function getDescendantIds(Lieu $lieu): array { $ids = []; foreach ($lieu->enfants as $enfant) { $ids[] = $enfant->id; $ids = array_merge($ids, $this->getDescendantIds($enfant)); } return $ids; } private function recalculerEnfants(Lieu $lieu): void { $lieu->load('enfants'); foreach ($lieu->enfants as $enfant) { $enfant->update([]); $this->recalculerEnfants($enfant); } } }