Files
mesreleves-php/app/Http/Controllers/ExportController.php
T
yann64 d064f8d28e Étapes 6-9 + types de lieux + picker + filtres
- Étape 6 : formulaire de saisie dynamique des relevés (piloté par source_type_fields, calendriers grégorien/julien/républicain)
- Étape 7 : workflow de statut des sources + notifications mail+DB (SourceAValider, SourceRejetee)
- Étape 8 : recherche fulltext PostgreSQL avec filtres type/lieu/années et CTE récursive pour les subdivisions de lieux
- Étape 9 : export GEDCOM 5.5.1 (GedcomExportService + DateConversionService)
- Types de lieux : CRUD admin (LieuTypeController) avec champ ordre
- Composant lieu-picker : modale Alpine.js avec recherche AJAX + debounce
- Filtres sources : statut, type, lieu (CTE récursive), période annee_debut/annee_fin
- Filtres lieux : type, texte, lieu parent avec descendants (CTE récursive)
- Migration : lieu_id + annee_debut + annee_fin sur sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:17:53 +02:00

112 lines
4.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\SourceStatus;
use App\Models\Releve;
use App\Models\Source;
use App\Services\GedcomExportService;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
class ExportController extends Controller
{
public function __construct(
private readonly GedcomExportService $gedcom,
) {}
/** Export de tous les relevés d'une source */
public function source(Source $source): Response
{
$this->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);
}
}