src/Services/AccountingFirmResolver.php line 44

Open in your IDE?
  1. <?php
  2. namespace App\Services;
  3. use App\Entity\AccountingFirm;
  4. use App\Repository\AccountingFirmRepository;
  5. use App\Repository\AliasRepository;
  6. use Symfony\Component\HttpFoundation\RequestStack;
  7. /**
  8.  * Service centralisé pour résoudre l'AccountingFirm à partir du host
  9.  * Évite la duplication des requêtes entre Voter et Controller
  10.  * Utilise un cache en mémoire pour la durée de la requête
  11.  */
  12. class AccountingFirmResolver
  13. {
  14.     private ?AccountingFirm $cachedFirm null;
  15.     private bool $resolved false;
  16.     private ?string $cachedHost null;
  17.     public function __construct(
  18.         private RequestStack $requestStack,
  19.         private AccountingFirmRepository $accountingFirmRepository,
  20.         private AliasRepository $aliasRepository
  21.     ) {
  22.     }
  23.     /**
  24.      * Résout l'AccountingFirm à partir du host de la requête courante
  25.      * Utilise un cache en mémoire - ne fait les requêtes qu'une seule fois
  26.      *
  27.      * @return AccountingFirm|null
  28.      */
  29.     public function resolve(): ?AccountingFirm
  30.     {
  31.         // Si déjà résolu pour ce host, retourner le cache
  32.         $currentHost $this->getCurrentHost();
  33.         if ($this->resolved && $this->cachedHost === $currentHost) {
  34.             return $this->cachedFirm;
  35.         }
  36.         // Résolution avec EAGER loading de Parameters
  37.         $this->cachedHost $currentHost;
  38.         $this->cachedFirm $this->resolveAccountingFirm($currentHost);
  39.         $this->resolved true;
  40.         return $this->cachedFirm;
  41.     }
  42.     /**
  43.      * Récupère le host depuis la requête courante
  44.      * Gère les routes de preview
  45.      *
  46.      * @return string
  47.      */
  48.     private function getCurrentHost(): string
  49.     {
  50.         $request $this->requestStack->getCurrentRequest();
  51.         if (!$request) {
  52.             return '';
  53.         }
  54.         $host $request->getHost();
  55.         $host str_replace('www.'''$host);
  56.         // Gestion des routes de preview
  57.         if (preg_match('/preview/'$request->get('_route') ?? '')) {
  58.             $previewHost $request->attributes->get('host');
  59.             if ($previewHost) {
  60.                 $host $previewHost;
  61.             }
  62.         }
  63.         return $host;
  64.     }
  65.     /**
  66.      * Résout l'AccountingFirm avec EAGER loading de Parameters
  67.      * Gère les alias si nécessaire
  68.      *
  69.      * @param string $host
  70.      * @return AccountingFirm|null
  71.      */
  72.     private function resolveAccountingFirm(string $host): ?AccountingFirm
  73.     {
  74.         // Tentative de résolution directe avec EAGER loading de Parameters
  75.         $qb $this->accountingFirmRepository->createQueryBuilder('a')
  76.             ->select('a, p')  // EAGER loading de Parameters
  77.             ->leftJoin('a.parameters''p')
  78.             ->where('a.host = :host')
  79.             ->setParameter('host'$host);
  80.         $accountingFirm $qb->getQuery()->getOneOrNullResult();
  81.         // Si trouvé, retourner directement
  82.         if ($accountingFirm !== null) {
  83.             return $accountingFirm;
  84.         }
  85.         // Sinon, chercher via un alias
  86.         $alias $this->aliasRepository->findOneBy(['name' => $host]);
  87.         if ($alias === null) {
  88.             return null;
  89.         }
  90.         // Récupérer l'AccountingFirm via l'alias avec EAGER loading
  91.         $acId $alias->getParameter()->getAccountingFirm()->getId();
  92.         $qb $this->accountingFirmRepository->createQueryBuilder('a')
  93.             ->select('a, p')  // EAGER loading de Parameters
  94.             ->leftJoin('a.parameters''p')
  95.             ->where('a.id = :id')
  96.             ->setParameter('id'$acId);
  97.         return $qb->getQuery()->getOneOrNullResult();
  98.     }
  99.     /**
  100.      * Retourne le host actuellement résolu (pour debug)
  101.      *
  102.      * @return string|null
  103.      */
  104.     public function getCurrentResolvedHost(): ?string
  105.     {
  106.         return $this->cachedHost;
  107.     }
  108.     /**
  109.      * Force un reset du cache (utile pour les tests)
  110.      */
  111.     public function reset(): void
  112.     {
  113.         $this->cachedFirm null;
  114.         $this->resolved false;
  115.         $this->cachedHost null;
  116.     }
  117. }