src/EventSubscriber/PremiumExpirationSubscriber.php line 34

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\User;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  7. use Symfony\Component\HttpKernel\KernelEvents;
  8. use Symfony\Component\Security\Core\Security;
  9. use Symfony\Component\HttpFoundation\Request;
  10. /**
  11.  * Désactive l'abonnement premium à la volée (sans cron) dès qu'une requête arrive
  12.  * et que la date d'expiration est dépassée.
  13.  */
  14. class PremiumExpirationSubscriber implements EventSubscriberInterface
  15. {
  16.     public function __construct(
  17.         private readonly Security $security,
  18.         private readonly EntityManagerInterface $em,
  19.         private readonly bool $premiumFemaleDefault
  20.     ) {
  21.     }
  22.     public static function getSubscribedEvents(): array
  23.     {
  24.         return [
  25.             // Après le firewall (token déjà résolu), avant l’exécution du contrôleur.
  26.             KernelEvents::CONTROLLER => ['onKernelController'0],
  27.         ];
  28.     }
  29.     public function onKernelController(ControllerEvent $event): void
  30.     {
  31.         if (!$event->isMainRequest()) {
  32.             return;
  33.         }
  34.         $request $event->getRequest();
  35.         if ($this->isStaticAsset($request)) {
  36.             return;
  37.         }
  38.         /** @var User|null $user */
  39.         $user $this->security->getUser();
  40.         if (!$user) {
  41.             return;
  42.         }
  43.         $isFemale \in_array('ROLE_FEMALE'$user->getRoles(), true);
  44.         if ($this->premiumFemaleDefault && $isFemale) {
  45.             if (!$user->isPremium()) {
  46.                 $this->updatePremiumStatus($usertrue);
  47.             }
  48.             return;
  49.         }
  50.         if (!$user->isPremium()) {
  51.             return;
  52.         }
  53.         // payData peut être stocké en array (doctrine json) ou en JSON string :
  54.         $payDataRaw $user->getPayData();
  55.         $payData \is_array($payDataRaw) ? $payDataRaw json_decode((string) $payDataRawtrue);
  56.         if (!\is_array($payData)) {
  57.             // Donnée corrompue ou absente : désactive par sécurité
  58.             $this->updatePremiumStatus($userfalse);
  59.             return;
  60.         }
  61.         $nowTs  time();
  62.         $endTs  = isset($payData['dateAbonnementEnd']) ? (int) $payData['dateAbonnementEnd'] : 0;
  63.         $isPaid filter_var($payData['isPaid'] ?? falseFILTER_VALIDATE_BOOL);
  64.         $shouldBePremium $isPaid && $endTs !== && $nowTs $endTs;
  65.         if (!$user->isPremium() && $shouldBePremium) {
  66.             $this->updatePremiumStatus($usertrue);
  67.         }
  68.         $shouldBeDeniedPremium $endTs === || $endTs $nowTs;
  69.         if ($user->isPremium() && $shouldBeDeniedPremium) {
  70.             $this->updatePremiumStatus($userfalse);
  71.         }
  72.     }
  73.     private function isStaticAsset(Request $request): bool
  74.     {
  75.         $path $request->getPathInfo();
  76.         return (bool) preg_match('#^/(build|assets|css|js|fonts|img|images|favicon\\.ico|robots\\.txt|_wdt|_profiler)#'$path);
  77.     }
  78.     private function updatePremiumStatus(User $userbool $isPremium): void
  79.     {
  80.         $user->setIsPremium($isPremium);
  81.         $this->em->persist($user);
  82.         $this->em->flush();
  83.         $this->em->refresh($user);
  84.     }
  85. }