<?php
declare(strict_types=1);
namespace App\EventSubscriber;
use App\Helper\Partner\PartnerHelper;
use Croisiland\CommonBundle\Entity\Partner\Partner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
readonly class PartnerAuthSubscriber implements EventSubscriberInterface
{
// Liste des routes qui ne nécessitent PAS d'authentification partenaire
private const array PUBLIC_ROUTES = [
'website_partner_auth.login',
'website_partner_auth.logout',
'_wdt',
'_profiler',
'_preview_error',
'sulu_media.website',
];
public function __construct(
private PartnerHelper $partnerHelper,
private SessionInterface $session,
private UrlGeneratorInterface $urlGenerator,
) {}
public static function getSubscribedEvents(): array
{
// Priorité légèrement inférieure au resolver pour être sûr que le partenaire est là
return [
KernelEvents::REQUEST => ['onKernelRequest', 10],
];
}
public function onKernelRequest(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$routeName = $request->attributes->get('_route');
// 1. Vérification immédiate : route publique ?
if ($this->isPublicRoute($routeName)) {
return;
}
// 2. Récupération du partenaire résolu par l'autre subscriber
/** @var Partner|null $partner */
$partner = $request->attributes->get('partner');
// Si pas de partenaire (pas de sous-domaine ou sous-domaine inconnu), on ne fait rien
// (Ou vous pouvez décider de rediriger vers une page 404/erreur ici)
if ($partner === null) {
return;
}
// 3. Vérification de la session
$sessionKey = $this->partnerHelper->getPartnerSessionKey($partner);
if (!$this->session->get($sessionKey, false) && $_ENV['APP_SERV_ENV'] !== 'dev') {
// Redirection vers le login
$loginUrl = $this->urlGenerator->generate('website_partner_auth.login', $request->query->all());
$event->setResponse(new RedirectResponse($loginUrl));
$event->stopPropagation();
}
}
private function isPublicRoute(?string $routeName): bool
{
if ($routeName === null) {
return false;
}
foreach (self::PUBLIC_ROUTES as $publicRoute) {
// Utilisation de str_starts_with pour plus de clarté et de performance que fnmatch
if (str_starts_with($routeName, $publicRoute)) {
return true;
}
}
return false;
}
}