authorize('viewAny', Lieu::class); // Arbre complet trié par nom_long pour l'affichage $lieux = Lieu::with('parent') ->orderBy('nom_long') ->paginate(50); return view('lieux.index', compact('lieux')); } public function create(): View { $this->authorize('create', Lieu::class); $parents = Lieu::orderBy('nom_long')->get(['id', 'nom_long']); return view('lieux.create', compact('parents')); } 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'); return view('lieux.show', compact('lieu')); } public function edit(Lieu $lieu): View { $this->authorize('update', $lieu); // Exclure le lieu lui-même et ses descendants pour éviter les cycles $descendants = $this->getDescendantIds($lieu); $parents = Lieu::whereNotIn('id', [...$descendants, $lieu->id]) ->orderBy('nom_long') ->get(['id', 'nom_long']); return view('lieux.edit', compact('lieu', 'parents')); } public function update(UpdateLieuRequest $request, Lieu $lieu): RedirectResponse { $lieu->update($request->validated()); // Recalculer nom_long des enfants en cascade $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 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([]); // déclenche le booted() hook qui recalcule nom_long $this->recalculerEnfants($enfant); } } }