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