src/Aqarmap/Bundle/ListingBundle/Service/InteractionService.php line 138

  1. <?php
  2. namespace Aqarmap\Bundle\ListingBundle\Service;
  3. use App\Message\Listing\ListingViewsCounterUpdatedMessage;
  4. use Aqarmap\Bundle\ListingBundle\Constant\InteractionTypes;
  5. use Aqarmap\Bundle\ListingBundle\Entity\Interaction;
  6. use Aqarmap\Bundle\ListingBundle\Entity\Listing;
  7. use Aqarmap\Bundle\ListingBundle\Repository\InteractionRepository;
  8. use Aqarmap\Bundle\MainBundle\Contract\ProducerFactoryInterface;
  9. use Aqarmap\Bundle\UserBundle\Entity\User;
  10. use Aqarmap\Bundle\UserBundle\Services\UserInterestManager;
  11. use Aqarmap\Bundle\UserBundle\Services\UserManager;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  14. use Symfony\Component\HttpFoundation\Cookie;
  15. use Symfony\Component\HttpFoundation\RequestStack;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\Messenger\MessageBusInterface;
  18. use Symfony\Component\Security\Core\User\UserInterface;
  19. use Symfony\Contracts\Service\Attribute\Required;
  20. class InteractionService
  21. {
  22. /** @var RequestStack */
  23. private $request;
  24. /** @var ListingManager */
  25. private $listingManager;
  26. /**
  27. * @var EventDispatcherInterface
  28. */
  29. protected $dispatcher;
  30. /**
  31. * @var Storage
  32. */
  33. protected $tokenStorage;
  34. /**
  35. * @var ProducerFactoryInterface
  36. */
  37. protected $buyerAlertProducer;
  38. /**
  39. * @var UserInterestManager
  40. */
  41. protected $interestManager;
  42. /** @var InteractionRepository */
  43. protected $interactionRepository;
  44. /** @var ListingContactRateService */
  45. protected $listingContactRateService;
  46. public function __construct(
  47. private readonly EntityManagerInterface $em,
  48. RequestStack $request,
  49. EventDispatcherInterface $dispatcher,
  50. ProducerFactoryInterface $pokeProducerFactory,
  51. UserInterestManager $interestManager,
  52. protected UserManager $userManager,
  53. InteractionRepository $interactionRepository,
  54. ListingContactRateService $listingContactRateService,
  55. private MessageBusInterface $bus
  56. ) {
  57. $this->request = $request->getCurrentRequest();
  58. $this->dispatcher = $dispatcher;
  59. $this->interestManager = $interestManager;
  60. $this->interactionRepository = $interactionRepository;
  61. $this->listingContactRateService = $listingContactRateService;
  62. }
  63. /**
  64. * @param int $type
  65. * @param User $user
  66. * @param string|null $source
  67. * @param bool $flush
  68. */
  69. public function addInteraction(
  70. $type,
  71. Listing $listing,
  72. $user = null,
  73. $source = null,
  74. $flush = true,
  75. $campaign = null,
  76. ?string $userIp = null
  77. ): ?Interaction {
  78. $isValid = true;
  79. $resolvedIp = $userIp ?? $this->request?->getClientIp();
  80. $interaction = new Interaction();
  81. $interaction
  82. ->setUser($user)
  83. ->setListing($listing)
  84. ->setType($type)
  85. ->setUserIp($resolvedIp)
  86. ->setSource($source)
  87. ->setCampaign($campaign)
  88. ;
  89. if (\in_array($type, [InteractionTypes::LISTING_VIEWS])) {
  90. $isValid = $this->validateInteractionsDuplications($interaction);
  91. }
  92. if (true === $isValid) {
  93. $this->em->persist($interaction);
  94. if ($flush) {
  95. $this->em->flush([$interaction]);
  96. }
  97. $this->listingManager->incrementViewsCounters($listing);
  98. return $interaction;
  99. }
  100. return null;
  101. }
  102. /**
  103. * @return bool
  104. */
  105. private function validateInteractionsDuplications(Interaction $interaction)
  106. {
  107. $duplicates = $this->interactionRepository->checkDuplicateInteraction($interaction);
  108. return $duplicates ? false : true;
  109. }
  110. public function increaseViews(Listing $listing, ?UserInterface $user = null): void
  111. {
  112. if (
  113. $user instanceof User
  114. && $listing->getUser()->getId() === $user->getId()
  115. ) {
  116. return;
  117. }
  118. $response = new Response();
  119. $views = [];
  120. if ($this->request->cookies->has('viewed_listings')) {
  121. $views = unserialize($this->request->cookies->get('viewed_listings'));
  122. if (\count($views) > 100) {
  123. array_pop($views);
  124. }
  125. }
  126. // Prevent duplication using cookies
  127. if (!\in_array($listing->getId(), $views)) {
  128. $views[] = $listing->getId();
  129. $response->headers->setCookie(Cookie::create('viewed_listings', serialize($views), time() + (86400 * 7)));
  130. $response->sendHeaders();
  131. $user = $user instanceof User ? $user : null;
  132. $this->bus->dispatch(
  133. new ListingViewsCounterUpdatedMessage(
  134. $listing->getId(),
  135. new \DateTimeImmutable(),
  136. $user?->getId(),
  137. $this->request->getClientIp(),
  138. 'interaction-service',
  139. $this->request->cookies->get('campaign')
  140. )
  141. );
  142. }
  143. }
  144. #[Required]
  145. public function setListingManager(ListingManager $listingManager): void
  146. {
  147. $this->listingManager = $listingManager;
  148. }
  149. }