authorize('view', $source); $gedcomContent = $this->gedcom->exportSource($source); $filename = $this->sanitizeFilename($source->nom) . '.ged'; return response($gedcomContent, 200, [ 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]); } /** Export depuis les résultats de recherche (avec les mêmes filtres) */ public function recherche(Request $request): Response { $user = auth()->user(); $query = Releve::with(['source.sourceType', 'createur']) ->whereHas('source', function ($q) use ($user, $request) { if (! $user->isSectionManager()) { $assignedIds = $user->sourcesAssignees()->pluck('sources.id'); $q->where(function ($sq) use ($assignedIds) { $sq->where('status', SourceStatus::Termine) ->orWhereIn('id', $assignedIds); }); } if ($request->filled('source_type_id')) { $q->where('source_type_id', $request->integer('source_type_id')); } }); // $request déjà dans le use() if ($request->filled('q')) { $q = trim($request->get('q')); $query->where(function ($wq) use ($q) { $wq->where('nom', 'ilike', "%{$q}%") ->orWhere('prenom','ilike', "%{$q}%") ->orWhere('date_evenement', 'ilike', "%{$q}%") ->orWhereRaw( "to_tsvector('french', data::text) @@ plainto_tsquery('french', ?)", [$q] ); }); } if ($request->filled('lieu_id')) { $rows = DB::select(" WITH RECURSIVE descendants AS ( SELECT id, nom FROM lieux WHERE id = ? UNION ALL SELECT l.id, l.nom FROM lieux l INNER JOIN descendants d ON l.lieu_parent_id = d.id ) SELECT DISTINCT nom FROM descendants WHERE nom IS NOT NULL ", [$request->integer('lieu_id')]); $noms = collect($rows)->pluck('nom')->filter(); if ($noms->isNotEmpty()) { $pattern = $noms->map(fn ($n) => preg_quote($n, '/'))->join('|'); $query->whereRaw("data::text ~* ?", [$pattern]); } } if ($request->filled('annee_debut')) { $query->whereRaw('date_evenement >= ?', [$request->integer('annee_debut') . '-01-01']); } if ($request->filled('annee_fin')) { $query->whereRaw('date_evenement <= ?', [$request->integer('annee_fin') . '-12-31']); } $releves = $query->orderByRaw('nom ASC NULLS LAST')->get(); if ($releves->isEmpty()) { return back()->with('error', 'Aucun relevé à exporter.'); } $titre = $request->filled('q') ? 'Recherche_' . $request->get('q') : 'Export'; $gedcomContent = $this->gedcom->exportReleves($releves, $titre); $filename = $this->sanitizeFilename($titre) . '.ged'; return response($gedcomContent, 200, [ 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]); } private function sanitizeFilename(string $name): string { $name = iconv('UTF-8', 'ASCII//TRANSLIT', $name) ?: $name; return preg_replace('/[^a-zA-Z0-9_-]/', '_', $name); } }