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

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)) {
  175.                 self::$newEmails[$payload['id']] = $payload['email'];
  176.             }
  177.         }
  178.         $sourceIds $event->getIds();
  179.         $this->syncPreviousEmails($event->getContext());
  180.         $this->syncNewRecipients($sourceIds$event->getContext());
  181.         $this->tagHandler->tagCreated();
  182.         static::$previousEmails = [];
  183.         static::$newEmails = [];
  184.     }
  185.     /**
  186.      * Customer address changed.
  187.      *
  188.      * @param EntityWrittenEvent $event
  189.      */
  190.     public function onCustomerAddressSave(EntityWrittenEvent $event): void
  191.     {
  192.         if (!$this->recipientHandler->canHandle()) {
  193.             return;
  194.         }
  195.         $emails $this->getCustomerEmails($event);
  196.         $this->recipientHandler->resyncRecipient($emails);
  197.     }
  198.     /**
  199.      * Customer tag deleted.
  200.      *
  201.      * @param EntityDeletedEvent $event
  202.      */
  203.     public function onCustomerTagDelete(EntityDeletedEvent $event): void
  204.     {
  205.         if (!$this->recipientHandler->canHandle()) {
  206.             return;
  207.         }
  208.         $emails $this->getCustomerEmails($event);
  209.         $payloads $event->getPayloads();
  210.         $deletedTags = [];
  211.         foreach ($payloads as $payload) {
  212.             if (array_key_exists('tagId'$payload)) {
  213.                 $tag $this->tagRepository->getTagById($payload['tagId'], $event->getContext());
  214.                 $crTag = new Tag('Shopware 6'$tag->getName());
  215.                 $crTag->setType('Tag');
  216.                 $deletedTags[] = $crTag;
  217.             }
  218.         }
  219.         $this->recipientHandler->resyncRecipient($emails$deletedTags);
  220.     }
  221.     /**
  222.      * Saves data for delete.
  223.      *
  224.      * @param ControllerEvent $event
  225.      */
  226.     public function saveDataForDelete(ControllerEvent $event): void
  227.     {
  228.         $request $event->getRequest();
  229.         $routeName $request->get('_route');
  230.         if (!in_array(
  231.             $routeName,
  232.             ['api.customer.delete''api.customer.update''frontend.account.profile.email.save']
  233.         )) {
  234.             return;
  235.         }
  236.         if (!$this->recipientHandler->canHandle()) {
  237.             return;
  238.         }
  239.         if (in_array($routeName, ['api.customer.delete''api.customer.update'])) {
  240.             $path $request->get('path');
  241.             // check if route contains subpaths
  242.             if (!strpos($path'/')) {
  243.                 $this->savePreviousEmail(
  244.                     $path,
  245.                     $event->getRequest()->get('sw-context') ?: Context::createDefaultContext()
  246.                 );
  247.             }
  248.         } elseif ($routeName === 'frontend.account.profile.email.save') {
  249.             $this->savePreviousEmailFromContext($request);
  250.         }
  251.     }
  252.     private function syncPreviousEmails(Context $context): void
  253.     {
  254.         foreach (static::$previousEmails as $email) {
  255.             if ($this->subscriberRepository->getByEmail($email)) {
  256.                 $this->removeOldTags($email$context);
  257.             } else {
  258.                 $this->recipientHandler->recipientDeletedEvent($email);
  259.             }
  260.         }
  261.     }
  262.     /**
  263.      * @param string $email
  264.      * @param Context $context
  265.      */
  266.     private function removeOldTags(string $emailContext $context): void
  267.     {
  268.         $customerGroups $this->customerGroupRepository->getCustomerGroups($context);
  269.         try {
  270.             $customerTags $this->tagRepository->getTags($context);
  271.         } catch (DBALException $e) {
  272.             Logger::logError('Failed to get tags because: ' $e->getMessage());
  273.             $customerTags = [];
  274.         }
  275.         $salesChannels $this->salesChannelRepository->getSalesChannels($context);
  276.         $tagsForDelete = [new Buyer('Shopware 6'), new Contact('Shopware 6')];
  277.         /** @var CustomerGroupEntity $group */
  278.         foreach ($customerGroups as $group) {
  279.             $tag = new Tag('Shopware 6'trim($group->getTranslation('name')));
  280.             $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  281.             $tagsForDelete[] = $tag;
  282.         }
  283.         /** @var TagEntity $customerTag */
  284.         foreach ($customerTags as $customerTag) {
  285.             $tag = new Tag('Shopware 6'trim($customerTag->getName()));
  286.             $tag->setType(TagService::TAG);
  287.             $tagsForDelete[] = $tag;
  288.         }
  289.         /** @var SalesChannelEntity $channel */
  290.         foreach ($salesChannels as $channel) {
  291.             $tag = new Tag('Shopware 6'trim($channel->getName()));
  292.             $tag->setType(TagService::SHOP_TAG);
  293.             $tagsForDelete[] = $tag;
  294.         }
  295.         $this->recipientHandler->resyncRecipient([$email], $tagsForDelete);
  296.     }
  297.     /**
  298.      * @param Request $request
  299.      */
  300.     private function savePreviousEmailFromContext(Request $request): void
  301.     {
  302.         /** @var SalesChannelContext $salesChannelContext */
  303.         $salesChannelContext $request->get('sw-sales-channel-context') ?:
  304.             $this->salesChannelContextService->getSalesChannelContext($request);
  305.         if ($salesChannelContext) {
  306.             $customer $salesChannelContext->getCustomer();
  307.             if ($customer) {
  308.                 static::$previousEmails[$customer->getId()] = $customer->getEmail();
  309.             }
  310.         }
  311.     }
  312.     /**
  313.      * Saves previous email.
  314.      *
  315.      * @param string|null $id
  316.      * @param Context $context
  317.      */
  318.     private function savePreviousEmail(?string $idContext $context): void
  319.     {
  320.         if (!$id) {
  321.             return;
  322.         }
  323.         $customer $this->customerRepository->getCustomerById($id$context);
  324.         if ($customer) {
  325.             static::$previousEmails[$id] = $customer->getEmail();
  326.         }
  327.     }
  328.     /**
  329.      *
  330.      * @param array $sourceIds
  331.      * @param Context $context
  332.      *
  333.      * @return void
  334.      */
  335.     private function syncNewRecipients(array $sourceIdsContext $context): void
  336.     {
  337.         $emailsAndGroupsForResync $this->getEmailsAndTagsForResync($sourceIds$context);
  338.         $newsletterEmailsForSync $emailsAndGroupsForResync['newsletterEmailsForSync'];
  339.         $customerGroups $emailsAndGroupsForResync['customerGroups'];
  340.         foreach ($newsletterEmailsForSync as $id => $email) {
  341.             $tags = !empty($customerGroups[$id]) ? [$customerGroups[$id]] : [];
  342.             $this->recipientHandler->resyncRecipient([$email], $tags);
  343.         }
  344.     }
  345.     /**
  346.      * @param array $sourceIds
  347.      * @param Context $context
  348.      *
  349.      * @return array
  350.      *
  351.      * @noinspection NullPointerExceptionInspection
  352.      */
  353.     private function getEmailsAndTagsForResync(array $sourceIdsContext $context): array
  354.     {
  355.         $newsletterEmailsForSync = [];
  356.         $customerGroups = [];
  357.         foreach ($sourceIds as $id) {
  358.             $customer $this->customerRepository->getCustomerById($id$context);
  359.             $newsletterEmailsForSync[$id] = !empty(static::$newEmails[$id]) ?
  360.                 static::$newEmails[$id] : $customer->getEmail();
  361.             if ($customer->getGroup()) {
  362.                 $tag = new Tag(TagService::SOURCE$customer->getGroup()->getName());
  363.                 $tag->setType(TagService::CUSTOMER_GROUP_TAG);
  364.                 $customerGroups[$id] = $tag;
  365.             }
  366.         }
  367.         return [
  368.             'newsletterEmailsForSync' => $newsletterEmailsForSync,
  369.             'customerGroups' => $customerGroups
  370.         ];
  371.     }
  372.     /**
  373.      * @param $event
  374.      * @return array
  375.      */
  376.     protected function getCustomerEmails($event): array
  377.     {
  378.         $customerIds = [];
  379.         $writeResults $event->getWriteResults();
  380.         foreach ($writeResults as $result) {
  381.             $payload $result->getPayload();
  382.             if (array_key_exists('customerId'$payload)) {
  383.                 $customerIds[] = $payload['customerId'];
  384.             }
  385.         }
  386.         $customers $this->customerRepository->getCustomersByIds($customerIds$event->getContext());
  387.         $emails = [];
  388.         foreach ($customers as $customer) {
  389.             $emails[] = $customer->getEmail();
  390.         }
  391.         return $emails;
  392.     }
  393. }