397fb22c62
GET /api/qualimat_carriers?search= pour la saisie assistee du nom (RG-4.01, spec-back § 4.7) : recherche fuzzy sur name (+ siret), restreinte aux lignes actives (is_active = true), triee name ASC, paginee (regle n°13). - QualimatCarrierRepositoryInterface + DoctrineQualimatCarrierRepository : QueryBuilder de recherche (forcage is_active cote serveur, fuzzy multi-champs). - QualimatCarrierSearchProvider : provider de la GetCollection (pagination Hydra + echappatoire ?pagination=false), branche uniquement sur la collection. - ApiResource : provider custom sur GetCollection, retrait des ApiFilter natifs (incapables d'unifier name/siret sous ?search= ni d'imposer l'actif). Mapping ORM inchange (schema:update reste no-op). Aucune ecriture exposee. - Tests : actifs seuls, tri name, match siret, pagination Hydra, 403 sans perm.
58 lines
1.9 KiB
PHP
58 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Transport\Infrastructure\Doctrine;
|
|
|
|
use App\Module\Transport\Domain\Entity\QualimatCarrier;
|
|
use App\Module\Transport\Domain\Repository\QualimatCarrierRepositoryInterface;
|
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
|
use Doctrine\ORM\QueryBuilder;
|
|
use Doctrine\Persistence\ManagerRegistry;
|
|
|
|
/**
|
|
* @extends ServiceEntityRepository<QualimatCarrier>
|
|
*/
|
|
class DoctrineQualimatCarrierRepository extends ServiceEntityRepository implements QualimatCarrierRepositoryInterface
|
|
{
|
|
public function __construct(ManagerRegistry $registry)
|
|
{
|
|
parent::__construct($registry, QualimatCarrier::class);
|
|
}
|
|
|
|
public function createSearchQueryBuilder(?string $search = null): QueryBuilder
|
|
{
|
|
// Saisie assistee (§ 4.7) : on ne propose QUE des transporteurs QUALIMAT
|
|
// actifs (is_active = true), tries par nom. Le forcage de l'actif est une
|
|
// regle serveur (pas un filtre client) — les lignes soft-deletees par la
|
|
// synchro restent invisibles.
|
|
$qb = $this->createQueryBuilder('q')
|
|
->andWhere('q.isActive = true')
|
|
->orderBy('q.name', 'ASC')
|
|
;
|
|
|
|
$this->applySearch($qb, $search);
|
|
|
|
return $qb;
|
|
}
|
|
|
|
/**
|
|
* Recherche fuzzy insensible a la casse sur le nom (+ siret) du transporteur
|
|
* QUALIMAT (§ 4.7 / RG-4.01). Metacaracteres LIKE (%, _, \) echappes pour
|
|
* rester litteraux.
|
|
*/
|
|
private function applySearch(QueryBuilder $qb, ?string $search): void
|
|
{
|
|
if (null === $search || '' === trim($search)) {
|
|
return;
|
|
}
|
|
|
|
$escaped = str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], trim($search));
|
|
$pattern = '%'.mb_strtolower($escaped, 'UTF-8').'%';
|
|
|
|
$qb->andWhere('LOWER(q.name) LIKE :search OR LOWER(q.siret) LIKE :search')
|
|
->setParameter('search', $pattern)
|
|
;
|
|
}
|
|
}
|