custom/plugins/CrswCleverReachOfficial/src/Subscriber/Customers/CustomerSubscriber.php line 178

Open in your IDE?
  1. <?php
  2. namespace Crsw\CleverReachOfficial\Subscriber\Customers;
  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\Buyer;
  8. use Crsw\CleverReachOfficial\Core\BusinessLogic\Receiver\DTO\Tag\Special\Contact;
  9. use Crsw\CleverReachOfficial\Core\BusinessLogic\Receiver\DTO\Tag\Tag;
  10. use Crsw\CleverReachOfficial\Core\Infrastructure\Logger\Logger;
  11. use Crsw\CleverReachOfficial\Entity\Customer\Repositories\CustomerRepository;
  12. use Crsw\CleverReachOfficial\Entity\Customer\Repositories\SubscriberRepository;
  13. use Crsw\CleverReachOfficial\Entity\CustomerGroup\Repositories\CustomerGroupRepository;
  14. use Crsw\CleverReachOfficial\Entity\SalesChannel\Repositories\SalesChannelRepository;
  15. use Crsw\CleverReachOfficial\Entity\Tag\Repositories\TagRepository;
  16. use Crsw\CleverReachOfficial\Service\BusinessLogic\SalesChannel\SalesChannelContextService;
  17. use Crsw\CleverReachOfficial\Service\BusinessLogic\Tag\TagService;
  18. use Doctrine\DBAL\DBALException;
  19. use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupEntity;
  20. use Shopware\Core\Checkout\Customer\CustomerEvents;
  21. use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
  22. use Shopware\Core\Framework\Context;
  23. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  24. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  25. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  26. use Shopware\Core\System\SalesChannel\SalesChannelEntity;
  27. use Shopware\Core\System\Tag\TagEntity;
  28. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  31. use Symfony\Component\HttpKernel\KernelEvents;
  32. /**
  33.  * Class CustomerSubscriber
  34.  *
  35.  * @package Crsw\CleverReachOfficial\Subscriber\Customers
  36.  */
  37. class CustomerSubscriber implements EventSubscriberInterface
  38. {
  39.     /**
  40.      * Emails stored before customer is deleted/changed.
  41.      *
  42.      * @var array
  43.      */
  44.     private static $previousEmails = [];
  45.     /**
  46.      * Emails that have been changed on customer update.
  47.      *
  48.      * @var array
  49.      */
  50.     private static $newEmails = [];
  51.     /**
  52.      * @var RecipientHandler
  53.      */
  54.     private $recipientHandler;
  55.     /**
  56.      * @var TagHandler
  57.      */
  58.     private $tagHandler;
  59.     /**
  60.      * @var CustomerRepository
  61.      */
  62.     private $customerRepository;
  63.     /**
  64.      * @var CustomerGroupRepository
  65.      */
  66.     private $customerGroupRepository;
  67.     /**
  68.      * @var SubscriberRepository
  69.      */
  70.     private $subscriberRepository;
  71.     /**
  72.      * @var TagRepository
  73.      */
  74.     private $tagRepository;
  75.     /**
  76.      * @var SalesChannelRepository
  77.      */
  78.     private $salesChannelRepository;
  79.     /**
  80.      * @var SalesChannelContextService
  81.      */
  82.     private $salesChannelContextService;
  83.     /**
  84.      * CustomerSubscriber constructor.
  85.      *
  86.      * @param RecipientHandler $recipientHandler
  87.      * @param CustomerRepository $customerRepository
  88.      * @param Initializer $initializer
  89.      * @param CustomerGroupRepository $customerGroupRepository
  90.      * @param SubscriberRepository $subscriberRepository
  91.      * @param TagHandler $tagHandler
  92.      * @param TagRepository $tagRepository
  93.      * @param SalesChannelRepository $salesChannelRepository
  94.      * @param SalesChannelContextService $salesChannelContextService
  95.      */
  96.     public function __construct(
  97.         RecipientHandler $recipientHandler,
  98.         CustomerRepository $customerRepository,
  99.         Initializer $initializer,
  100.         CustomerGroupRepository $customerGroupRepository,
  101.         SubscriberRepository $subscriberRepository,
  102.         TagHandler $tagHandler,
  103.         TagRepository $tagRepository,
  104.         SalesChannelRepository $salesChannelRepository,
  105.         SalesChannelContextService $salesChannelContextService
  106.     ) {
  107.         Bootstrap::register();
  108.         $initializer->registerServices();
  109.         $this->recipientHandler $recipientHandler;
  110.         $this->customerRepository $customerRepository;
  111.         $this->customerGroupRepository $customerGroupRepository;
  112.         $this->subscriberRepository $subscriberRepository;
  113.         $this->tagHandler $tagHandler;
  114.         $this->tagRepository $tagRepository;
  115.         $this->salesChannelRepository $salesChannelRepository;
  116.         $this->salesChannelContextService $salesChannelContextService;
  117.     }
  118.     /**
  119.      * Returns subscribed events.
  120.      *
  121.      * @return string[]
  122.      */
  123.     public static function getSubscribedEvents(): array
  124.     {
  125.         return [
  126.             CustomerEvents::CUSTOMER_REGISTER_EVENT => 'onCustomerRegister',
  127.             CustomerRegisterEvent::class => 'onCustomerRegister',
  128.             CustomerEvents::CUSTOMER_DELETED_EVENT => 'onCustomerDelete',
  129.             CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerSave',
  130.             CustomerEvents::CUSTOMER_ADDRESS_WRITTEN_EVENT => 'onCustomerAddressSave',
  131.             'customer_tag.deleted' => 'onCustomerTagDelete',
  132.             KernelEvents::CONTROLLER => 'saveDataForDelete',
  133.         ];
  134.     }
  135.     /**
  136.      * Customer registered account.
  137.      *
  138.      * @param CustomerRegisterEvent $event
  139.      */
  140.     public function onCustomerRegister(CustomerRegisterEvent $event): void
  141.     {
  142.         if (!$this->recipientHandler->canHandle()) {
  143.             return;
  144.         }
  145.         $customer $event->getCustomer();
  146.         $this->recipientHandler->resyncRecipient([$customer->getEmail()]);
  147.     }
  148.     /**
  149.      * Customer deleted.
  150.      *
  151.      * @param EntityDeletedEvent $event
  152.      */
  153.     public function onCustomerDelete(EntityDeletedEvent $event): void
  154.     {
  155.         if (!$this->recipientHandler->canHandle()) {
  156.             return;
  157.         }
  158.         $this->syncPreviousEmails($event->getContext());
  159.         static::$previousEmails = [];
  160.     }
  161.     /**
  162.      * Customer created or modified.
  163.      *
  164.      * @param EntityWrittenEvent $event
  165.      */
  166.     public function onCustomerSave(EntityWrittenEvent $event): void
  167.     {
  168.         if (!$this->recipientHandler->canHandle()) {
  169.             return;
  170.         }
  171.         $writeResults $event->getWriteResults();
  172.         foreach ($writeResults as $writeResult) {
  173.             $payload $writeResult->getPayload();
  174.             if (array_key_exists('email'$payload) && array_key_exists('id'$payload)) {
  175.                 $id $payload['id'];
  176.                 self::$newEmails[$id] = $payload['email'];
  177.                 if ($this->isEmailChanged($id)) {
  178.                     $this->recipientHandler->recipientUnsubscribedEvent(self::$previousEmails[$id]);
  179.                     unset(self::$previousEmails[$id]);
  180.                 }
  181.             }
  182.         }
  183.         $sourceIds $event->getIds();
  184.         $this->syncPreviousEmails($event->getContext());
  185.         $this->syncNewRecipients($sourceIds$event->getContext());
  186.         $this->tagHandler->tagCreated();
  187.         static::$previousEmails = [];
  188.         static::$newEmails = [];
  189.     }
  190.     /**
  191.      * Customer address changed.
  192.      *
  193.      * @param EntityWrittenEvent $event
  194.      */
  195.     public function onCustomerAddressSave(EntityWrittenEvent $event): void
  196.     {
  197.         if (!$this->recipientHandler->canHandle()) {
  198.             return;
  199.         }
  200.         $emails $this->getCustomerEmails($event);
  201.         if (empty($emails)) {
  202.             return;
  203.         }
  204.         $this->recipientHandler->resyncRecipient($emails);
  205.     }
  206.     /**
  207.      * Customer tag deleted.
  208.      *
  209.      * @param EntityDeletedEvent $event
  210.      */
  211.     public function onCustomerTagDelete(EntityDeletedEvent $event): void
  212.     {
  213.         if (!$this->recipientHandler->canHandle()) {
  214.             return;
  215.         }
  216.         $emails $this->getCustomerEmails($event);
  217.         if (empty($emails)) {
  218.             return;
  219.         }
  220.         $payloads $event->getPayloads();
  221.         $deletedTags = [];
  222.         foreach ($payloads as $payload) {
  223.             if (array_key_exists('tagId'$payload)) {
  224.                 $tag $this->tagRepository->getTagById($payload['tagId'], $event->getContext());
  225.                 $crTag = new Tag('Shopware 6'$tag->getName());
  226.                 $crTag->setType('Tag');
  227.                 $deletedTags[] = $crTag;
  228.             }
  229.         }
  230.         $this->recipientHandler->resyncRecipient($emails$deletedTags);
  231.     }
  232.     /**
  233.      * Saves data for delete.
  234.      *
  235.      * @param ControllerEvent $event
  236.      */
  237.     public function saveDataForDelete(ControllerEvent $event): void
  238.     {
  239.         $request $event->getRequest();
  240.         $routeName $request->get('_route');
  241.         if (!in_array(
  242.             $routeName,
  243.             ['api.customer.delete''api.customer.update''frontend.account.profile.email.save']
  244.         )) {
  245.             return;
  246.         }
  247.         if (!$this->recipientHandler->canHandle()) {
  248.             return;
  249.         }
  250.         if (in_array($routeName, ['api.customer.delete''api.customer.update'])) {
  251.             $path $request->get('path');
  252.             // check if route contains subpaths
  253.             if (!strpos($path'/')) {
  254.                 $this->savePreviousEmail(
  255.                     $path,
  256.                     $event->getRequest()->get('sw-context') ?: Context::createDefaultContext()
  257.                 );
  258.             }
  259.         } elseif ($routeName === 'frontend.account.profile.email.save') {
  260.             $this->savePreviousEmailFromContext($request);
  261.         }
  262.     }
  263.     private function syncPreviousEmails(Context $context): void
  264.     {
  265.         foreach (static::$previousEmails as $email) {
  266.             if ($this->subscriberRepository->getByEmail($email)) {
  267.                 $this->removeOldTags($email$context);
  268.             } else {
  269.                 $this->recipientHandler->recipientDeletedEvent($email);
  270.             }
  271.         }
  272.     }
  273.     /**
  274.      * @param string $email
  275.      * @param Context $context
  276.      */
  277.     private function removeOldTags(string $emailContext $context): void
  278.     {
  279.         $customerGroups $this->customerGroupRepository->getCustomerGroups($context);
  280.         try {
  281.             $customerTags $this->tagRepository->getTags($context);
  282.         } catch (DBALException $e) {
  283.             Logger::logError('Failed to get tags because: ' $e->getMessage());
  284.             $customerTags = [];
  285.         }
  286.         $salesChannels $this->salesChannelRepository->getSalesChannels($context);
  287.         $tagsForDelete = [new Buyer('Shopware 6'), new Contact('Shopware 6')];
  288.         /** @var CustomerGroupEntity $group */
  289.         foreach ($customerGroups as $group) {
  290.             $tag = new Tag('Shopware 6'trim($group->getTranslation('name')));
  291.             $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  292.             $tagsForDelete[] = $tag;
  293.         }
  294.         /** @var TagEntity $customerTag */
  295.         foreach ($customerTags as $customerTag) {
  296.             $tag = new Tag('Shopware 6'trim($customerTag->getName()));
  297.             $tag->setType(TagService::TAG);
  298.             $tagsForDelete[] = $tag;
  299.         }
  300.         /** @var SalesChannelEntity $channel */
  301.         foreach ($salesChannels as $channel) {
  302.             $tag = new Tag('Shopware 6'trim($channel->getName()));
  303.             $tag->setType(TagService::SHOP_TAG);
  304.             $tagsForDelete[] = $tag;
  305.         }
  306.         $this->recipientHandler->resyncRecipient([$email], $tagsForDelete);
  307.     }
  308.     /**
  309.      * @param Request $request
  310.      */
  311.     private function savePreviousEmailFromContext(Request $request): void
  312.     {
  313.         /** @var SalesChannelContext $salesChannelContext */
  314.         $salesChannelContext $request->get('sw-sales-channel-context') ?:
  315.             $this->salesChannelContextService->getSalesChannelContext($request);
  316.         if ($salesChannelContext) {
  317.             $customer $salesChannelContext->getCustomer();
  318.             if ($customer) {
  319.                 static::$previousEmails[$customer->getId()] = $customer->getEmail();
  320.             }
  321.         }
  322.     }
  323.     /**
  324.      * Saves previous email.
  325.      *
  326.      * @param string|null $id
  327.      * @param Context $context
  328.      */
  329.     private function savePreviousEmail(?string $idContext $context): void
  330.     {
  331.         if (!$id) {
  332.             return;
  333.         }
  334.         $customer $this->customerRepository->getCustomerById($id$context);
  335.         if ($customer) {
  336.             static::$previousEmails[$id] = $customer->getEmail();
  337.         }
  338.     }
  339.     /**
  340.      *
  341.      * @param array $sourceIds
  342.      * @param Context $context
  343.      *
  344.      * @return void
  345.      */
  346.     private function syncNewRecipients(array $sourceIdsContext $context): void
  347.     {
  348.         $emailsAndGroupsForResync $this->getEmailsAndTagsForResync($sourceIds$context);
  349.         $newsletterEmailsForSync $emailsAndGroupsForResync['newsletterEmailsForSync'];
  350.         $customerGroups $emailsAndGroupsForResync['customerGroups'];
  351.         foreach ($newsletterEmailsForSync as $id => $email) {
  352.             $tags = !empty($customerGroups[$id]) ? [$customerGroups[$id]] : [];
  353.             $this->recipientHandler->resyncRecipient([$email], $tags);
  354.         }
  355.     }
  356.     /**
  357.      * @param array $sourceIds
  358.      * @param Context $context
  359.      *
  360.      * @return array
  361.      *
  362.      * @noinspection NullPointerExceptionInspection
  363.      */
  364.     private function getEmailsAndTagsForResync(array $sourceIdsContext $context): array
  365.     {
  366.         $newsletterEmailsForSync = [];
  367.         $customerGroups = [];
  368.         foreach ($sourceIds as $id) {
  369.             $customer $this->customerRepository->getCustomerById($id$context);
  370.             $newsletterEmailsForSync[$id] = !empty(static::$newEmails[$id]) ?
  371.                 static::$newEmails[$id] : $customer->getEmail();
  372.             if ($customer->getGroup()) {
  373.                 $tag = new Tag(TagService::SOURCE$customer->getGroup()->getName());
  374.                 $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  375.                 $customerGroups[$id] = $tag;
  376.             }
  377.         }
  378.         return [
  379.             'newsletterEmailsForSync' => $newsletterEmailsForSync,
  380.             'customerGroups' => $customerGroups
  381.         ];
  382.     }
  383.     /**
  384.      * Check if customer email changed
  385.      *
  386.      * @param string $id
  387.      *
  388.      * @return bool
  389.      */
  390.     private function isEmailChanged(string $id): bool
  391.     {
  392.         return !empty(self::$previousEmails)
  393.             && !empty(self::$newEmails)
  394.             && self::$previousEmails[$id] !== self::$newEmails[$id];
  395.     }
  396.     /**
  397.      * @param $event
  398.      * @return array
  399.      */
  400.     protected function getCustomerEmails($event): array
  401.     {
  402.         $customerIds = [];
  403.         $writeResults $event->getWriteResults();
  404.         foreach ($writeResults as $result) {
  405.             $payload $result->getPayload();
  406.             if (array_key_exists('customerId'$payload)) {
  407.                 $customerIds[] = $payload['customerId'];
  408.             }
  409.         }
  410.         if (empty($customerIds)) {
  411.             return [];
  412.         }
  413.         $customers $this->customerRepository->getCustomersByIds($customerIds$event->getContext());
  414.         $emails = [];
  415.         foreach ($customers as $customer) {
  416.             $emails[] = $customer->getEmail();
  417.         }
  418.         return $emails;
  419.     }
  420. }