Files
yann64 6a73a2f001 Gestion utilisateurs, limites recherche, filtres lieux/sources, fix logo prod
- Admin : CRUD complet utilisateurs (créer, modifier nom/email/mdp/rôle, supprimer)
  avec garde-fous (dernier admin, compte propre)
- Recherche : limite configurable par l'admin (défaut 200), bannière d'avertissement
  quand la limite est atteinte, plus de pagination (résultats en bloc)
- Lieux : liste non chargée sans filtre actif (performance sur grands volumes)
- Sources : idem pour admin/responsables ; membres voient toujours leurs sources
- Logo 404 prod : +FollowSymLinks dans .htaccess, storage:link dans l'assistant
  d'installation, bouton "Recréer le lien" dans Administration → Paramètres

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 03:39:06 +02:00

124 lines
4.6 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\SourceStatus;
use App\Models\Lieu;
use App\Models\Releve;
use App\Models\SourceType;
use App\Services\SiteSettingsService;
use App\Support\DbCompat;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class RechercheController extends Controller
{
public function index(Request $request): View
{
$sourceTypes = SourceType::orderBy('nom')->get(['id', 'nom']);
$resultats = null;
$total = null;
$limited = false;
// Charger le lieu sélectionné pour pré-remplir le picker
$lieuSelectionne = $request->filled('lieu_id')
? Lieu::find($request->integer('lieu_id'), ['id', 'nom', 'nom_long'])
: null;
if ($request->anyFilled(['q', 'source_type_id', 'lieu_id', 'annee_debut', 'annee_fin'])) {
[$resultats, $total, $limited] = $this->search($request);
}
return view('recherche.index', compact('sourceTypes', 'resultats', 'total', 'limited', 'lieuSelectionne'));
}
private function search(Request $request): array
{
$user = auth()->user();
$query = Releve::with(['source.sourceType', 'source.depot', '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'));
}
});
// ── Recherche textuelle ──────────────────────────────────────────────
if ($request->filled('q')) {
$q = trim($request->get('q'));
$like = DbCompat::like();
$fts = DbCompat::ftsRaw();
$query->where(function ($wq) use ($q, $like, $fts) {
$wq->where('nom', $like, "%{$q}%")
->orWhere('prenom', $like, "%{$q}%")
->orWhere('date_evenement', $like, "%{$q}%");
if ($fts) {
$wq->orWhereRaw($fts, [$q]);
}
});
}
// ── Filtre par lieu (+ descendants via CTE récursive) ────────────────
if ($request->filled('lieu_id')) {
$lieuNoms = $this->getLieuNoms($request->integer('lieu_id'));
if ($lieuNoms->isNotEmpty()) {
$pattern = $lieuNoms
->map(fn ($n) => preg_quote($n, '/'))
->join('|');
$query->whereRaw(DbCompat::jsonRegexRaw('data'), [$pattern]);
}
}
// ── Filtre par plage d'années ────────────────────────────────────────
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']);
}
// ── Limite configurable par l'admin ─────────────────────────────────
$max = SiteSettingsService::searchMaxResults();
$total = $query->count();
$resultats = $query
->orderByRaw(DbCompat::nullsLast('nom'))
->orderByRaw(DbCompat::nullsLast('date_evenement'))
->limit($max)
->get();
return [$resultats, $total, $total > $max];
}
/**
* Retourne les noms du lieu et de tous ses descendants via CTE récursive PostgreSQL.
*/
private function getLieuNoms(int $lieuId): \Illuminate\Support\Collection
{
$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
", [$lieuId]);
return collect($rows)->pluck('nom')->filter();
}
}