Files
pta/app/Controllers/AddressController.php

79 lines
2.7 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Core\Access;
use App\Core\JsonResponse;
use App\Services\AddressApiService;
use PDO;
use Throwable;
/**
* Recherche d'adresses postales (V7.25), relais vers la Base Adresse Nationale.
*
* Sert l'autocomplétion du champ « Adresse personnelle » de la page Agents. Le
* relais est indispensable : la CSP interdit au navigateur d'appeler un domaine
* tiers (`connect-src 'self'`, voir App\Core\Security).
*
* LECTURE PURE : aucune écriture en base, donc ni jeton CSRF ni journalisation
* (CLAUDE.md — « les lectures ne sont jamais journalisées »). Le garde reste
* celui de l'écriture des fiches agent, `requireService()` : c'est le seul rôle
* qui saisit une adresse.
*
* Un échec du service distant ressort en 502 et non en 500 : c'est la BAN qui
* n'a pas répondu, pas PTA qui a échoué. Côté interface, cet échec n'est jamais
* bloquant — l'adresse reste saisissable à la main.
*/
final class AddressController
{
private Access $access;
public function __construct(private PDO $pdo)
{
$this->access = new Access($pdo);
}
/**
* GET api/search_address.php — propositions d'adresses.
* Paramètres GET : q (saisie en cours), limit (facultatif, 1 à 8).
*/
public function search(): void
{
$this->access->requireService();
$query = trim((string) ($_GET['q'] ?? ''));
$length = function_exists('mb_strlen') ? mb_strlen($query, 'UTF-8') : strlen($query);
if ($length < AddressApiService::MIN_QUERY_LENGTH) {
JsonResponse::send(422, [
'error' => sprintf('Saisissez au moins %d caractères.', AddressApiService::MIN_QUERY_LENGTH),
]);
}
// Plafond de saisie : la BAN n'exploite pas au-delà, et cela borne le
// coût d'une requête forgée.
if ($length > 120) {
JsonResponse::send(422, ['error' => 'Saisie trop longue pour une recherche d’adresse.']);
}
$limit = filter_var($_GET['limit'] ?? 5, FILTER_VALIDATE_INT);
if ($limit === false) {
$limit = 5;
}
try {
$suggestions = (new AddressApiService())->search($query, $limit);
} catch (Throwable $e) {
JsonResponse::send(502, [
'error' => 'Le service national des adresses est momentanément indisponible. Vous pouvez saisir l’adresse manuellement.',
'details' => (getenv('PTA_DEBUG') ?: '0') !== '0' ? $e->getMessage() : null,
]);
}
JsonResponse::send(200, [
'query' => $query,
'suggestions' => $suggestions,
]);
}
}