custom/plugins/CrswCleverReachOfficial/src/Subscriber/NewsletterRecipients/NewsletterRecipientSubscriber.php line 176

Open in your IDE?
  1. <?php
  2. namespace Crsw\CleverReachOfficial\Subscriber\NewsletterRecipients;
  3. use Crsw\CleverReachOfficial\Components\EventHandlers\RecipientHandler;
  4. use Crsw\CleverReachOfficial\Components\EventHandlers\TagHandler;
  5. use Crsw\CleverReachOfficial\Components\Utility\Bootstrap;
  6. use Crsw\CleverReachOfficial\Components\Utility\Initializer;
  7. use Crsw\CleverReachOfficial\Core\BusinessLogic\Receiver\DTO\Tag\Special\Subscriber;
  8. use Crsw\CleverReachOfficial\Core\BusinessLogic\Receiver\DTO\Tag\Tag;
  9. use Crsw\CleverReachOfficial\Entity\Customer\Repositories\SubscriberRepository;
  10. use Crsw\CleverReachOfficial\Entity\Tag\Repositories\TagRepository;
  11. use Crsw\CleverReachOfficial\Service\BusinessLogic\SalesChannel\SalesChannelContextService;
  12. use Shopware\Core\Content\Newsletter\Event\NewsletterConfirmEvent;
  13. use Shopware\Core\Content\Newsletter\NewsletterEvents;
  14. use Shopware\Core\Framework\Context;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  17. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  21. use Symfony\Component\HttpKernel\KernelEvents;
  22. /**
  23.  * Class NewsletterRecipientSubscriber
  24.  *
  25.  * @package Crsw\CleverReachOfficial\Subscriber\NewsletterRecipients
  26.  */
  27. class NewsletterRecipientSubscriber implements EventSubscriberInterface
  28. {
  29.     /**
  30.      * Emails stored before newsletter recipient is deleted/changed
  31.      *
  32.      * @var array
  33.      */
  34.     private static $previousEmails = [];
  35.     /**
  36.      * Emails that have been changed on newsletter recipient update.
  37.      *
  38.      * @var array
  39.      */
  40.     private static $newEmails = [];
  41.     /**
  42.      * Emails of customer that unsubscribed.
  43.      *
  44.      * @var array
  45.      */
  46.     private static $deactivatedEmails = [];
  47.     /**
  48.      * @var RecipientHandler
  49.      */
  50.     private $recipientHandler;
  51.     /**
  52.      * @var SubscriberRepository
  53.      */
  54.     private $subscriberRepository;
  55.     /**
  56.      * @var TagHandler
  57.      */
  58.     private $tagHandler;
  59.     /**
  60.      * @var TagRepository
  61.      */
  62.     private $tagRepository;
  63.     /**
  64.      * @var SalesChannelContextService
  65.      */
  66.     private $salesChannelContextService;
  67.     /**
  68.      * NewsletterRecipientSubscriber constructor.
  69.      *
  70.      * @param RecipientHandler $recipientHandler
  71.      * @param SubscriberRepository $subscriberRepository
  72.      * @param Initializer $initializer
  73.      * @param TagHandler $tagHandler
  74.      * @param TagRepository $tagRepository
  75.      * @param SalesChannelContextService $salesChannelContextService
  76.      */
  77.     public function __construct(
  78.         RecipientHandler $recipientHandler,
  79.         SubscriberRepository $subscriberRepository,
  80.         Initializer $initializer,
  81.         TagHandler $tagHandler,
  82.         TagRepository $tagRepository,
  83.         SalesChannelContextService $salesChannelContextService
  84.     ) {
  85.         Bootstrap::register();
  86.         $initializer->registerServices();
  87.         $this->recipientHandler $recipientHandler;
  88.         $this->subscriberRepository $subscriberRepository;
  89.         $this->tagHandler $tagHandler;
  90.         $this->tagRepository $tagRepository;
  91.         $this->salesChannelContextService $salesChannelContextService;
  92.     }
  93.     /**
  94.      * @inheritDoc
  95.      */
  96.     public static function getSubscribedEvents(): array
  97.     {
  98.         return [
  99.             NewsletterEvents::NEWSLETTER_CONFIRM_EVENT => 'onNewsletterConfirm',
  100.             NewsletterEvents::NEWSLETTER_RECIPIENT_WRITTEN_EVENT => 'onNewsletterSave',
  101.             NewsletterEvents::NEWSLETTER_RECIPIENT_DELETED_EVENT => 'onNewsletterDelete',
  102.             KernelEvents::CONTROLLER => 'saveDataForDelete',
  103.             'newsletter_recipient_tag.deleted' => 'onNewsletterTagDelete',
  104.         ];
  105.     }
  106.     /**
  107.      * Newsletter confirmation by email.
  108.      *
  109.      * @param NewsletterConfirmEvent $event
  110.      */
  111.     public function onNewsletterConfirm(NewsletterConfirmEvent $event): void
  112.     {
  113.         if (!$this->recipientHandler->canHandle()) {
  114.             return;
  115.         }
  116.         $recipient $event->getNewsletterRecipient();
  117.         $this->recipientHandler->recipientSubscribedEvent($recipient->getEmail());
  118.     }
  119.     /**
  120.      * Newsletter recipient updated by administrator.
  121.      *
  122.      * @param EntityWrittenEvent $event
  123.      */
  124.     public function onNewsletterSave(EntityWrittenEvent $event): void
  125.     {
  126.         if (!$this->recipientHandler->canHandle()) {
  127.             return;
  128.         }
  129.         $writeResults $event->getWriteResults();
  130.         $this->handleSubscriberChangeEvent($writeResults$event);
  131.         $this->tagHandler->tagCreated();
  132.     }
  133.     /**
  134.      * Newsletter deleted by administrator.
  135.      *
  136.      * @param EntityDeletedEvent $event
  137.      */
  138.     public function onNewsletterDelete(EntityDeletedEvent $event): void
  139.     {
  140.         if (!$this->recipientHandler->canHandle()) {
  141.             return;
  142.         }
  143.         $ids $event->getIds();
  144.         $subscribers $this->subscriberRepository->getByIds($ids$event->getContext());
  145.         static::$previousEmails array_merge(static::$previousEmails, static::$deactivatedEmails);
  146.         foreach ($subscribers as $subscriber) {
  147.             static::$previousEmails[] = $subscriber->getEmail();
  148.         }
  149.         foreach (static::$previousEmails as $email) {
  150.             $this->recipientHandler->resyncRecipient([$email], [new Subscriber('Shopware 6')]);
  151.             $this->recipientHandler->recipientDeletedEvent($email);
  152.         }
  153.         static::$previousEmails = [];
  154.     }
  155.     /**
  156.      * @param ControllerEvent $event
  157.      */
  158.     public function saveDataForDelete(ControllerEvent $event): void
  159.     {
  160.         $request $event->getRequest();
  161.         if ($request->get('_route') === 'frontend.account.newsletter' &&
  162.             !$request->get('option'false)) {
  163.             $this->savePreviousEmailFromContext($request);
  164.             return;
  165.         }
  166.         if (in_array(
  167.             $request->get('_route'),
  168.             ['api.newsletter_recipient.delete''api.newsletter_recipient.update'],
  169.             true
  170.         )) {
  171.             $path $request->get('path');
  172.             // check if route contains subpaths
  173.             if (!strpos($path'/')) {
  174.                 $this->saveEmailForDelete(
  175.                     $path,
  176.                     $event->getRequest()->get('sw-context') ?: Context::createDefaultContext()
  177.                 );
  178.             }
  179.         }
  180.     }
  181.     /**
  182.      * Newsletter tag deleted.
  183.      *
  184.      * @param EntityDeletedEvent $event
  185.      */
  186.     public function onNewsletterTagDelete(EntityDeletedEvent $event): void
  187.     {
  188.         $newsletterIds = [];
  189.         $payloads $event->getPayloads();
  190.         $tagsForDelete = [];
  191.         foreach ($payloads as $payload) {
  192.             if (array_key_exists('newsletterRecipientId'$payload)) {
  193.                 $newsletterIds[] = $payload['newsletterRecipientId'];
  194.                 $tagsForDelete[$payload['newsletterRecipientId']] = array_key_exists('tagId'$payload)
  195.                     ? $payload['tagId'] : '';
  196.             }
  197.         }
  198.         $this->updateRecipients($newsletterIds$event->getContext(), $tagsForDelete);
  199.     }
  200.     /**
  201.      * Check if email changed and deactivates recipients with old email address
  202.      *
  203.      * @param array $sourceIds
  204.      */
  205.     private function deactivateOldEmails(array $sourceIds): void
  206.     {
  207.         $emailsForDeactivation = static::$deactivatedEmails;
  208.         foreach ($sourceIds as $id) {
  209.             if ($this->isEmailChanged($id)) {
  210.                 $emailsForDeactivation[] = static::$previousEmails[$id];
  211.             }
  212.         }
  213.         foreach ($emailsForDeactivation as $email) {
  214.             $this->recipientHandler->recipientDeletedEvent($email);
  215.         }
  216.     }
  217.     /**
  218.      * Check if newsletter recipient email changed
  219.      *
  220.      * @param string $id
  221.      *
  222.      * @return bool
  223.      */
  224.     private function isEmailChanged(string $id): bool
  225.     {
  226.         return !empty(self::$previousEmails)
  227.             && !empty(self::$newEmails)
  228.             && self::$previousEmails[$id] !== self::$newEmails[$id];
  229.     }
  230.     /**
  231.      * @param array $sourceIds
  232.      * @param Context $context
  233.      * @param array|null $tagIds
  234.      */
  235.     private function updateRecipients(array $sourceIdsContext $context, ?array $tagIds): void
  236.     {
  237.         $emailsForCreate = [];
  238.         $newsletterRecipients $this->subscriberRepository->getByIds($sourceIds$context);
  239.         foreach ($newsletterRecipients as $entity) {
  240.             if ($entity->getStatus() === 'optOut') {
  241.                 $this->recipientHandler->recipientUnsubscribedEvent($entity->getEmail());
  242.                 continue;
  243.             }
  244.             if ($this->isEmailChanged($entity->getId())) {
  245.                 $this->recipientHandler->recipientUnsubscribedEvent(self::$previousEmails[$entity->getId()]);
  246.                 $emailsForCreate[$entity->getId()] = self::$newEmails[$entity->getId()];
  247.                 unset(
  248.                     self::$newEmails[$entity->getId()],
  249.                     self::$previousEmails[$entity->getId()]
  250.                 );
  251.             } else {
  252.                 $emailsForCreate[$entity->getId()] = $entity->getEmail();
  253.             }
  254.         }
  255.         foreach ($emailsForCreate as $key => $email) {
  256.             $crTag '';
  257.             if (!empty($tagIds[$key])) {
  258.                 $tag $this->tagRepository->getTagById($tagIds[$key], $context);
  259.                 $crTag = new Tag('Shopware 6'$tag->getName());
  260.                 $crTag->setType('Tag');
  261.             }
  262.             $this->recipientHandler->resyncRecipient([$email], $crTag ? [$crTag] : []);
  263.         }
  264.     }
  265.     /**
  266.      * @param Request $request
  267.      */
  268.     private function savePreviousEmailFromContext(Request $request): void
  269.     {
  270.         /** @var SalesChannelContext $salesChannelContext */
  271.         $salesChannelContext $request->get('sw-sales-channel-context') ?:
  272.             $this->salesChannelContextService->getSalesChannelContext($request);
  273.         if ($salesChannelContext) {
  274.             $customer $salesChannelContext->getCustomer();
  275.             if ($customer) {
  276.                 $id $this->subscriberRepository->getByEmail($customer->getEmail())['subscriberId'];
  277.                 static::$deactivatedEmails[bin2hex($id)] = $customer->getEmail();
  278.             }
  279.         }
  280.     }
  281.     /**
  282.      * @param string|null $id
  283.      * @param Context $context
  284.      */
  285.     private function saveEmailForDelete(?string $idContext $context): void
  286.     {
  287.         if (!$id) {
  288.             return;
  289.         }
  290.         $newsletterRecipient $this->subscriberRepository->getByIds([$id], $context)->first();
  291.         if ($newsletterRecipient) {
  292.             static::$previousEmails[$id] = $newsletterRecipient->getEmail();
  293.         }
  294.     }
  295.     /**
  296.      * @param array $writeResults
  297.      * @param EntityWrittenEvent $event
  298.      */
  299.     private function handleSubscriberChangeEvent(array $writeResultsEntityWrittenEvent $event): void
  300.     {
  301.         $emailsForCreate = [];
  302.         foreach ($writeResults as $writeResult) {
  303.             $payload $writeResult->getPayload();
  304.             if (!array_key_exists('id'$payload)) {
  305.                 continue;
  306.             }
  307.             $id $payload['id'];
  308.             if (empty($payload['email'])) {
  309.                 continue;
  310.             }
  311.             $email $payload['email'];
  312.             self::$newEmails[$id] = $email;
  313.             if (array_key_exists('status'$payload) && $payload['status'] === 'optOut') {
  314.                 $this->recipientHandler->recipientUnsubscribedEvent($email);
  315.                 continue;
  316.             }
  317.             if ($this->isEmailChanged($id)) {
  318.                 $this->recipientHandler->recipientUnsubscribedEvent(self::$previousEmails[$id]);
  319.                 $emailsForCreate[$id] = self::$newEmails[$id];
  320.                 unset(
  321.                     self::$newEmails[$id],
  322.                     self::$previousEmails[$id]
  323.                 );
  324.             } else {
  325.                 $emailsForCreate[$id] = $email;
  326.             }
  327.         }
  328.         $sourceIds $event->getIds();
  329.         $this->deactivateOldEmails($sourceIds);
  330.         if (!$emailsForCreate) {
  331.             $this->updateRecipients($sourceIds$event->getContext(), null);
  332.         }
  333.         foreach ($emailsForCreate as $email) {
  334.             $this->recipientHandler->resyncRecipient([$email]);
  335.         }
  336.     }
  337. }