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

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.         $this->tagHandler->resyncSegments();
  232.     }
  233.     /**
  234.      * Saves data for delete.
  235.      *
  236.      * @param ControllerEvent $event
  237.      */
  238.     public function saveDataForDelete(ControllerEvent $event): void
  239.     {
  240.         $request $event->getRequest();
  241.         $routeName $request->get('_route');
  242.         if (!in_array(
  243.             $routeName,
  244.             ['api.customer.delete''api.customer.update''frontend.account.profile.email.save']
  245.         )) {
  246.             return;
  247.         }
  248.         if (!$this->recipientHandler->canHandle()) {
  249.             return;
  250.         }
  251.         if (in_array($routeName, ['api.customer.delete''api.customer.update'])) {
  252.             $path $request->get('path');
  253.             // check if route contains subpaths
  254.             if (!strpos($path'/')) {
  255.                 $this->savePreviousEmail(
  256.                     $path,
  257.                     $event->getRequest()->get('sw-context') ?: Context::createDefaultContext()
  258.                 );
  259.             }
  260.         } elseif ($routeName === 'frontend.account.profile.email.save') {
  261.             $this->savePreviousEmailFromContext($request);
  262.         }
  263.     }
  264.     private function syncPreviousEmails(Context $context): void
  265.     {
  266.         foreach (static::$previousEmails as $email) {
  267.             if ($this->subscriberRepository->getByEmail($email)) {
  268.                 $this->removeOldTags($email$context);
  269.             } else {
  270.                 $this->recipientHandler->recipientDeletedEvent($email);
  271.             }
  272.         }
  273.     }
  274.     /**
  275.      * @param string $email
  276.      * @param Context $context
  277.      */
  278.     private function removeOldTags(string $emailContext $context): void
  279.     {
  280.         $customerGroups $this->customerGroupRepository->getCustomerGroups($context);
  281.         try {
  282.             $customerTags $this->tagRepository->getTags($context);
  283.         } catch (DBALException $e) {
  284.             Logger::logError('Failed to get tags because: ' $e->getMessage());
  285.             $customerTags = [];
  286.         }
  287.         $salesChannels $this->salesChannelRepository->getSalesChannels($context);
  288.         $tagsForDelete = [new Buyer('Shopware 6'), new Contact('Shopware 6')];
  289.         /** @var CustomerGroupEntity $group */
  290.         foreach ($customerGroups as $group) {
  291.             $tag = new Tag('Shopware 6'trim($group->getTranslation('name')));
  292.             $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  293.             $tagsForDelete[] = $tag;
  294.         }
  295.         /** @var TagEntity $customerTag */
  296.         foreach ($customerTags as $customerTag) {
  297.             $tag = new Tag('Shopware 6'trim($customerTag->getName()));
  298.             $tag->setType(TagService::TAG);
  299.             $tagsForDelete[] = $tag;
  300.         }
  301.         /** @var SalesChannelEntity $channel */
  302.         foreach ($salesChannels as $channel) {
  303.             $tag = new Tag('Shopware 6'trim($channel->getName()));
  304.             $tag->setType(TagService::SHOP_TAG);
  305.             $tagsForDelete[] = $tag;
  306.         }
  307.         $this->recipientHandler->resyncRecipient([$email], $tagsForDelete);
  308.     }
  309.     /**
  310.      * @param Request $request
  311.      */
  312.     private function savePreviousEmailFromContext(Request $request): void
  313.     {
  314.         /** @var SalesChannelContext $salesChannelContext */
  315.         $salesChannelContext $request->get('sw-sales-channel-context') ?:
  316.             $this->salesChannelContextService->getSalesChannelContext($request);
  317.         if ($salesChannelContext) {
  318.             $customer $salesChannelContext->getCustomer();
  319.             if ($customer) {
  320.                 static::$previousEmails[$customer->getId()] = $customer->getEmail();
  321.             }
  322.         }
  323.     }
  324.     /**
  325.      * Saves previous email.
  326.      *
  327.      * @param string|null $id
  328.      * @param Context $context
  329.      */
  330.     private function savePreviousEmail(?string $idContext $context): void
  331.     {
  332.         if (!$id) {
  333.             return;
  334.         }
  335.         $customer $this->customerRepository->getCustomerById($id$context);
  336.         if ($customer) {
  337.             static::$previousEmails[$id] = $customer->getEmail();
  338.         }
  339.     }
  340.     /**
  341.      *
  342.      * @param array $sourceIds
  343.      * @param Context $context
  344.      *
  345.      * @return void
  346.      */
  347.     private function syncNewRecipients(array $sourceIdsContext $context): void
  348.     {
  349.         $emailsAndGroupsForResync $this->getEmailsAndTagsForResync($sourceIds$context);
  350.         $newsletterEmailsForSync $emailsAndGroupsForResync['newsletterEmailsForSync'];
  351.         $customerGroups $emailsAndGroupsForResync['customerGroups'];
  352.         foreach ($newsletterEmailsForSync as $id => $email) {
  353.             $tags = !empty($customerGroups[$id]) ? [$customerGroups[$id]] : [];
  354.             $this->recipientHandler->resyncRecipient([$email], $tags);
  355.         }
  356.     }
  357.     /**
  358.      * @param array $sourceIds
  359.      * @param Context $context
  360.      *
  361.      * @return array
  362.      *
  363.      * @noinspection NullPointerExceptionInspection
  364.      */
  365.     private function getEmailsAndTagsForResync(array $sourceIdsContext $context): array
  366.     {
  367.         $newsletterEmailsForSync = [];
  368.         $customerGroups = [];
  369.         foreach ($sourceIds as $id) {
  370.             $customer $this->customerRepository->getCustomerById($id$context);
  371.             $newsletterEmailsForSync[$id] = !empty(static::$newEmails[$id]) ?
  372.                 static::$newEmails[$id] : $customer->getEmail();
  373.             if ($customer->getGroup()) {
  374.                 $tag = new Tag(TagService::SOURCE$customer->getGroup()->getName());
  375.                 $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  376.                 $customerGroups[$id] = $tag;
  377.             }
  378.         }
  379.         return [
  380.             'newsletterEmailsForSync' => $newsletterEmailsForSync,
  381.             'customerGroups' => $customerGroups
  382.         ];
  383.     }
  384.     /**
  385.      * Check if customer email changed
  386.      *
  387.      * @param string $id
  388.      *
  389.      * @return bool
  390.      */
  391.     private function isEmailChanged(string $id): bool
  392.     {
  393.         return !empty(self::$previousEmails)
  394.             && !empty(self::$newEmails)
  395.             && self::$previousEmails[$id] !== self::$newEmails[$id];
  396.     }
  397.     /**
  398.      * @param $event
  399.      * @return array
  400.      */
  401.     protected function getCustomerEmails($event): array
  402.     {
  403.         $customerIds = [];
  404.         $writeResults $event->getWriteResults();
  405.         foreach ($writeResults as $result) {
  406.             $payload $result->getPayload();
  407.             if (array_key_exists('customerId'$payload)) {
  408.                 $customerIds[] = $payload['customerId'];
  409.             }
  410.         }
  411.         if (empty($customerIds)) {
  412.             return [];
  413.         }
  414.         $customers $this->customerRepository->getCustomersByIds($customerIds$event->getContext());
  415.         $emails = [];
  416.         foreach ($customers as $customer) {
  417.             $emails[] = $customer->getEmail();
  418.         }
  419.         return $emails;
  420.     }
  421. }