custom/plugins/CheckoutPlugin/src/Storefront/Subscriber/CustomerLoginSubscriber.php line 241

Open in your IDE?
  1. <?php
  2. namespace Virgin\CheckoutPlugin\Storefront\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  5. use Shopware\Core\Checkout\Customer\CustomerEntity;
  6. use Shopware\Core\Checkout\Customer\Event\CustomerBeforeLoginEvent;
  7. use Shopware\Core\Checkout\Customer\Event\CustomerLoginEvent;
  8. use Shopware\Core\Checkout\Customer\Event\CustomerLogoutEvent;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\Uuid\Uuid;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Component\HttpFoundation\Session\Session;
  16. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  17. use Symfony\Contracts\EventDispatcher\Event;
  18. use Shopware\Core\Checkout\Cart\CartRuleLoader;
  19. use Virgin\ProductModelExtension\Custom\ProductType\ProductTypeEntity;
  20. use Virgin\SystemIntegration\Services\RestApiClient;
  21. class CustomerLoginSubscriber implements EventSubscriberInterface
  22. {
  23. /**
  24. * ...
  25. *
  26. * @var EntityRepository
  27. */
  28. protected $customerRepository;
  29. /**
  30. * ...
  31. *
  32. * @var CartRuleLoader
  33. */
  34. protected $cartLoader;
  35. /**
  36. * ...
  37. *
  38. * @var CartService
  39. */
  40. private $cartService;
  41. /**
  42. * ...
  43. *
  44. * @var Connection
  45. */
  46. private $db;
  47. /**
  48. * ...
  49. *
  50. * @var string
  51. */
  52. static private $token;
  53. private $restApiClient;
  54. /** @var Session */
  55. private $session;
  56. /**
  57. * ...
  58. *
  59. * @param EntityRepository $customerRepository
  60. * @param CartRuleLoader $cartLoader
  61. * @param CartService $cartService
  62. * @param Connection $db
  63. * @param RestApiClient $restApiClient
  64. */
  65. public function __construct(
  66. EntityRepository $customerRepository,
  67. CartRuleLoader $cartLoader,
  68. CartService $cartService,
  69. Connection $db,
  70. RestApiClient $restApiClient,
  71. SessionInterface $session
  72. ) {
  73. // set params
  74. $this->customerRepository = $customerRepository;
  75. $this->cartLoader = $cartLoader;
  76. $this->cartService = $cartService;
  77. $this->db = $db;
  78. $this->restApiClient = $restApiClient;
  79. $this->session = $session;
  80. }
  81. /**
  82. * {@inheritDoc}
  83. */
  84. public static function getSubscribedEvents(): array
  85. {
  86. return [
  87. // CustomerBeforeLoginEvent::class => 'onBeforeCustomerLogin',
  88. // CustomerLoginEvent::class => 'onCustomerLogin',
  89. CustomerLogoutEvent::class => 'onCustomerLogout'
  90. ];
  91. }
  92. /**
  93. * ...
  94. *
  95. * @param CustomerBeforeLoginEvent $event
  96. */
  97. public function onBeforeCustomerLogin(CustomerBeforeLoginEvent $event)
  98. {
  99. // get the customer by email.
  100. // if the validation fails, we wont call the next event which would actually load the cart
  101. $customer = $this->getCustomerByEmail(
  102. $event->getEmail(),
  103. $event->getSalesChannelContext()
  104. );
  105. // even valid?
  106. if (!$customer instanceof CustomerEntity) {
  107. // error will be cought by shopware
  108. return;
  109. }
  110. // get the old cart token by customer id
  111. $token = $this->getCustomerCartToken(
  112. $customer,
  113. $event->getSalesChannelContext()
  114. );
  115. // none found?
  116. if (empty($token)) {
  117. // done
  118. return;
  119. }
  120. // save it
  121. self::$token = $token;
  122. }
  123. /**
  124. * ...
  125. *
  126. * @param CustomerLoginEvent $event
  127. */
  128. public function onCustomerLogin(CustomerLoginEvent $event)
  129. {
  130. if ($this->session->get('warningSnippet')) {
  131. $this->session->remove('warningSnippet');
  132. }
  133. // get parameters
  134. $customer = $event->getCustomer();
  135. $salesChannelContext = $event->getSalesChannelContext();
  136. $token = $event->getContextToken();
  137. // when we have a cart as a guest (with products) and we log in after
  138. // then the cart item doesnt get an update for the customer id.
  139. // so we make sure that our current cart has the customer id even before
  140. // we try to load an old cart - which may not exist.
  141. $this->db->update(
  142. 'cart',
  143. ['customer_id' => Uuid::fromHexToBytes($customer->getId())],
  144. ['token' => $token]
  145. );
  146. // no token found in pre-login?
  147. if (empty(self::$token)) {
  148. // ignore
  149. return;
  150. }
  151. // get the current cart
  152. $cart = $this->cartService->getCart(
  153. $token,
  154. $salesChannelContext
  155. );
  156. // load the old cart by the saved token
  157. $oldCart = $this->cartLoader->loadByToken(
  158. $salesChannelContext,
  159. self::$token
  160. );
  161. // if current cart has a subscription or a revolution_digitale
  162. $newLineItem = null;
  163. foreach ($cart->getLineItems() as $lineItem) {
  164. $lineItemProductType = $lineItem->getPayloadValue('product_type');
  165. if ($lineItemProductType == ProductTypeEntity::SUBSCRIPTION ||
  166. $lineItemProductType == ProductTypeEntity::REVOLUTION_DIGITALE) {
  167. $newLineItem = $lineItem;
  168. }
  169. }
  170. // loop every line item from the old cart
  171. foreach ($oldCart->getCart()->getLineItems() as $lineItem) {
  172. // and add it to the current cart
  173. $lineItemProductType = $lineItem->getPayloadValue('product_type');
  174. if ($lineItem->isStackable()) {
  175. if (($lineItemProductType == ProductTypeEntity::SUBSCRIPTION ||
  176. $lineItemProductType == ProductTypeEntity::REVOLUTION_DIGITALE) &&
  177. $newLineItem != null
  178. ) {
  179. $lineItem = $newLineItem;
  180. }
  181. $cart = $this->cartService->add(
  182. $cart,
  183. $lineItem,
  184. $event->getSalesChannelContext()
  185. );
  186. }
  187. }
  188. // remove customer id from old cart
  189. $this->db->update(
  190. 'cart',
  191. ['customer_id' => null],
  192. ['customer_id' => Uuid::fromHexToBytes($customer->getId())]
  193. );
  194. // force the customer id in the current cart
  195. $this->db->update(
  196. 'cart',
  197. ['customer_id' => Uuid::fromHexToBytes($customer->getId())],
  198. ['token' => $token]
  199. );
  200. if (!empty($_SESSION['utm_params'])) {
  201. $this->restApiClient->insertUtmParams($_SESSION['utm_params'], $customer->getEmail(), $customer->getFirstName(), $customer->getLastName(), 'LOGIN');
  202. unset($_SESSION['utm_params']);
  203. }
  204. }
  205. /**
  206. * ...
  207. *
  208. * @param Event $event
  209. */
  210. public function onCustomerLogout(CustomerLogoutEvent $event)
  211. {
  212. }
  213. /**
  214. * ...
  215. *
  216. * @param string $email
  217. * @param SalesChannelContext $salesChannelContext
  218. *
  219. * @return CustomerEntity|null
  220. */
  221. private function getCustomerByEmail(string $email, SalesChannelContext $salesChannelContext)
  222. {
  223. // create criteria
  224. $criteria = new Criteria();
  225. $criteria->addFilter(new EqualsFilter('customer.email', $email));
  226. $criteria->addFilter(new EqualsFilter('customer.guest', 0));
  227. // search it
  228. $result = $this->customerRepository->search($criteria, $salesChannelContext->getContext());
  229. // return the first customer
  230. return $result->first();
  231. }
  232. /**
  233. * ...
  234. *
  235. * @param CustomerEntity $customer
  236. * @param SalesChannelContext $salesChannelContext
  237. *
  238. * @return string|null
  239. */
  240. private function getCustomerCartToken(CustomerEntity $customer, SalesChannelContext $salesChannelContext)
  241. {
  242. return (string) $this->db->createQueryBuilder()
  243. ->select('token')
  244. ->from('cart')
  245. ->where('customer_id = :id')
  246. ->setParameter('id', Uuid::fromHexToBytes($customer->getId()))
  247. ->execute()
  248. ->fetchColumn();
  249. }
  250. }