<?php
// src/Controller/SearchController.php
namespace App\Controller;
use App\Entity\Acte;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class SearchController extends AbstractController
{
public function __construct(private EntityManagerInterface $em) {}
// ──────────────────────────────────────────────────────────────────────────
// Route principale SSR
// ──────────────────────────────────────────────────────────────────────────
#[Route('/search', name: 'app_search', methods: ['GET'])]
public function index(Request $request): Response
{
$params = $this->extractParams($request);
$isPremium = $this->getUser()?->hasPremiumAccess() ?? false;
$results = [];
$total = 0;
$totalPages = 0;
if ($params['q'] !== '' || $this->hasActiveFilter($params)) {
[$results, $total] = $this->runSearch($params, $isPremium);
$totalPages = (int) ceil($total / 15);
}
return $this->render('search/index.html.twig', [
'query' => $params['q'],
'results' => $results,
'filters' => $params,
'typeFilter' => $params['type'],
'currentPage' => $params['page'],
'totalPages' => $totalPages,
'isPremium' => $isPremium,
]);
}
// ──────────────────────────────────────────────────────────────────────────
// Route AJAX — JSON (live search + autocomplete)
// ──────────────────────────────────────────────────────────────────────────
#[Route('/munganyo/api', name: 'app_search_ajax', methods: ['GET'])]
public function ajax(Request $request): JsonResponse
{
if (!$request->isXmlHttpRequest() && !$request->query->getBoolean('autocomplete')) {
return $this->json(['error' => 'Requête non autorisée'], 403);
}
$params = $this->extractParams($request);
$isPremium = $this->getUser()?->hasPremiumAccess() ?? false;
// ── Mode autocomplete ─────────────────────────────────────────────────
if ($request->query->getBoolean('autocomplete')) {
$limit = min((int) $request->query->get('limit', 6), 10);
return $this->json(['suggestions' => $this->runAutocomplete($params['q'], $limit)]);
}
// ── Recherche complète ────────────────────────────────────────────────
$perPage = 15;
[$actes, $total] = $this->runSearch($params, $isPremium, $perPage);
return $this->json([
'results' => array_map(fn($a) => $this->serializeActe($a, $isPremium), $actes),
'total' => $total,
'currentPage' => $params['page'],
'totalPages' => (int) ceil($total / $perPage),
'isPremium' => $isPremium,
]);
}
// ──────────────────────────────────────────────────────────────────────────
// Logique de recherche — QueryBuilder inline (pas de repository)
// ──────────────────────────────────────────────────────────────────────────
private function runSearch(array $params, bool $isPremium, int $perPage = 15): array
{
// TODO: décommenter quand les entités seront créées
return [[], 0];
}
// ──────────────────────────────────────────────────────────────────────────
// Autocomplete inline
// ──────────────────────────────────────────────────────────────────────────
private function runAutocomplete(string $query, int $limit): array
{
return [];
}
// ──────────────────────────────────────────────────────────────────────────
// Sérialisation — OCR et pertinence réservés au Premium (CDC)
// ──────────────────────────────────────────────────────────────────────────
private function serializeActe(object $acte, bool $isPremium): array
{
$data = [
'id' => $acte->getId(),
'titre' => $acte->getTitre(),
'numero' => $acte->getNumeroActe(),
'type' => $acte->getTypeActe()?->getCode(),
'typeLabel' => $acte->getTypeActe()?->getLabel(),
'datePublication' => $acte->getDatePublication()?->format('Y-m-d'),
'institution' => $acte->getInstitutionEmettrice()?->getNom(),
'territoire' => $acte->getTerritoireApplicable()?->getNom(),
'statutJuridique' => $acte->getStatutJuridique()?->getCode(),
'resume' => $acte->getResume(),
'pdf_url' => $acte->getPdfUrl(),
];
if ($isPremium) {
$data['extrait'] = $acte->getExtraitPertinent();
$data['relevance'] = $acte->getRelevanceScore();
}
return $data;
}
// ──────────────────────────────────────────────────────────────────────────
// Helpers privés
// ──────────────────────────────────────────────────────────────────────────
private function extractParams(Request $r): array
{
return [
'q' => trim($r->query->get('q', '')),
'institution' => $r->query->get('institution', ''),
'period' => $r->query->get('period', ''),
'date_debut' => $r->query->get('date_debut', ''),
'date_fin' => $r->query->get('date_fin', ''),
'type' => $r->query->get('type', ''),
'statut' => $r->query->get('statut', ''),
'territoire' => $r->query->get('territoire', ''),
'sort' => $r->query->get('sort', 'date_desc'),
'page' => max(1, (int) $r->query->get('page', 1)),
];
}
private function hasActiveFilter(array $params): bool
{
foreach (['institution', 'type', 'statut', 'territoire', 'period'] as $key) {
if ($params[$key] !== '') return true;
}
return false;
}
}