src/App/Service/Affiliate/AffiliateIdTracker.php line 45

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Service\Affiliate;
  3. use App\Entity\User;
  4. use App\RabbitMq\Writer\LandingPageWriter;
  5. use App\Transliterator\Transliterator;
  6. use Doctrine\Persistence\ManagerRegistry;
  7. use Psr\Log\LoggerInterface;
  8. use RuntimeException;
  9. use Sindrive\RabbitMqTaskBundle\Service\TaskHandler;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\Cookie;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  14. use Symfony\Component\HttpKernel\KernelEvents;
  15. class AffiliateIdTracker implements EventSubscriberInterface
  16. {
  17.     public const AFFILIATE_KEY 'atid';
  18.     public const AFFILIATE_HASH 'htid';
  19.     private TaskHandler $taskHandler;
  20.     private LoggerInterface $logger;
  21.     private ReferralTokenManager $referralTokenManager;
  22.     private ManagerRegistry $doctrine;
  23.     public function __construct(
  24.         LoggerInterface $logger,
  25.         ReferralTokenManager $referralTokenManager,
  26.         ManagerRegistry $doctrine,
  27.         TaskHandler $taskHandler
  28.     )
  29.     {
  30.         $this->logger $logger;
  31.         $this->referralTokenManager $referralTokenManager;
  32.         $this->doctrine $doctrine;
  33.         $this->taskHandler $taskHandler;
  34.     }
  35.     public function onKernelResponse(ResponseEvent $event): void
  36.     {
  37.         $request $event->getRequest();
  38.         if (!$request->query->has(self::AFFILIATE_KEY)) {
  39.             return;
  40.         }
  41.         $requestToken $request->query->get(self::AFFILIATE_KEY);
  42.         $cookieToken $request->cookies->get(self::AFFILIATE_KEY);
  43.         if ($cookieToken === $requestToken) {
  44.             return;
  45.         }
  46.         $trackingHash hash('sha512'date('y-m-d-h-i-s') . $requestToken);
  47.         $this->taskHandler->sendTask(
  48.             LandingPageWriter::QUEUE,
  49.             serialize([
  50.                 'new' => true,
  51.                 'referrer' => $request->headers->get('referer'),
  52.                 'landedOn' => $request->getUri(),
  53.                 'trackingHash' => $trackingHash,
  54.                 'referee_key' => $this->referralTokenManager->resolveId($requestToken),
  55.             ])
  56.         );
  57.         $response $event->getResponse();
  58.         $response->headers->setCookie(Cookie::create(self::AFFILIATE_KEY$requestTokentime() + 24 60 60'/'));
  59.         $response->headers->setCookie(Cookie::create(self::AFFILIATE_HASH$trackingHashtime() + 30 24 60 60'/'));
  60.     }
  61.     public function setUserAffiliate(Request $requestUser $user): void
  62.     {
  63.         if (null === $user->getEmail()) {
  64.             throw new RuntimeException('User must have an email to be tracked.');
  65.         }
  66.         if (!$request->cookies->has(self::AFFILIATE_KEY) || !$request->cookies->has(self::AFFILIATE_HASH)) {
  67.             return;
  68.         }
  69.         $cookieToken $request->cookies->get(self::AFFILIATE_KEY);
  70.         $referrerId $this->referralTokenManager->resolveId($cookieToken);
  71.         if (null === $referrerId) {
  72.             $this->logger->info(
  73.                 'AffiliateIdTracker: Not numeric token ' $cookieToken
  74.             );
  75.             return;
  76.         }
  77.         if (null !== $user->getReferral()) {
  78.             $this->logger->info(
  79.                 'AffiliateIdTracker: User ' $user->getId() . ' already have a referral.',
  80.             );
  81.             return;
  82.         }
  83.         $referee $this->doctrine->getRepository(User::class)->find($referrerId);
  84.         if (null === $referee || $referee->isLocked()) {
  85.             $this->logger->info(
  86.                 'AffiliateIdTracker: Referral is not enabled or locked ' . ($referee !== null $referee->getId() : ''),
  87.             );
  88.             return;
  89.         }
  90.         $this->logger->info(
  91.             'AffiliateIdTracker: Assigning referral ' $referee->getId() . ' to user ' Transliterator::hideEmail($user->getEmail()),
  92.         );
  93.         $referral $user->addReferral($referee);
  94.         $this->doctrine->getManager()->persist($referral);
  95.         $trackingHash $request->cookies->get(self::AFFILIATE_HASH);
  96.         $user->setTrackingHash($trackingHash);
  97.         $this->logger->info(
  98.             'AffiliateIdTracker::setUserAffiliate conversion with hash: ' $user->getTrackingHash(),
  99.         );
  100.         $msg = [
  101.             'new' => false,
  102.             'trackingHash' => $user->getTrackingHash(),
  103.             'user' => $user->getId(),
  104.         ];
  105.         $this->taskHandler->sendTask(LandingPageWriter::QUEUEserialize($msg));
  106.     }
  107.     /**
  108.      * @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
  109.      */
  110.     public static function getSubscribedEvents(): array
  111.     {
  112.         return [
  113.             KernelEvents::RESPONSE => 'onKernelResponse',
  114.         ];
  115.     }
  116. }