custom/plugins/SendcloudShipping/src/Subscriber/CheckoutSubscriber.php line 168

Open in your IDE?
  1. <?php
  2. namespace Sendcloud\Shipping\Subscriber;
  3. use Doctrine\DBAL\DBALException;
  4. use Sendcloud\Shipping\Core\BusinessLogic\Interfaces\OrderService;
  5. use Sendcloud\Shipping\Entity\Customer\CustomerRepository;
  6. use Sendcloud\Shipping\Entity\ServicePoint\ServicePointEntityRepository;
  7. use Sendcloud\Shipping\Entity\Shipment\ShipmentEntityRepository;
  8. use Sendcloud\Shipping\Service\Business\ConfigurationService;
  9. use Sendcloud\Shipping\Service\Utility\Initializer;
  10. use Sendcloud\Shipping\Struct\DisableSubmitButton;
  11. use Sendcloud\Shipping\Struct\ServicePointConfig;
  12. use Sendcloud\Shipping\Struct\ServicePointInfo;
  13. use Shopware\Core\Checkout\Cart\Delivery\Struct\Delivery;
  14. use Shopware\Core\Checkout\Customer\CustomerEntity;
  15. use Shopware\Core\Checkout\Customer\CustomerEvents;
  16. use Shopware\Core\Checkout\Customer\Event\CustomerLogoutEvent;
  17. use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  20. use Shopware\Core\PlatformRequest;
  21. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  22. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  23. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  24. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\RequestStack;
  27. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  28. use Symfony\Component\HttpKernel\KernelEvents;
  29. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  30. /**
  31.  * Class CheckoutSubscriber
  32.  *
  33.  * @package Sendcloud\Shipping\\Subscriber
  34.  */
  35. class CheckoutSubscriber implements EventSubscriberInterface
  36. {
  37.     private static $removeServicePoint true;
  38.     /**
  39.      * @var CustomerRepository
  40.      */
  41.     private $customerRepository;
  42.     /**
  43.      * @var ConfigurationService
  44.      */
  45.     private $configService;
  46.     /**
  47.      * @var UrlGeneratorInterface
  48.      */
  49.     private $urlGenerator;
  50.     /**
  51.      * @var ShipmentEntityRepository
  52.      */
  53.     private $shipmentRepository;
  54.     /**
  55.      * @var ServicePointEntityRepository
  56.      */
  57.     private $servicePointRepository;
  58.     /**
  59.      * @var OrderService
  60.      */
  61.     private $orderService;
  62.     /**
  63.      * @var RequestStack
  64.      */
  65.     private $requestStack;
  66.     /**
  67.      * @var ParameterBagInterface
  68.      */
  69.     private $params;
  70.     /**
  71.      * CheckoutSubscriber constructor.
  72.      *
  73.      * @param Initializer $initializer
  74.      * @param ConfigurationService $configService
  75.      * @param UrlGeneratorInterface $urlGenerator
  76.      * @param ShipmentEntityRepository $shipmentRepository
  77.      * @param ServicePointEntityRepository $servicePointRepository
  78.      * @param CustomerRepository $customerRepository
  79.      * @param OrderService $orderService
  80.      * @param RequestStack $requestStack
  81.      * @param ParameterBagInterface $params
  82.      */
  83.     public function __construct(
  84.         Initializer $initializer,
  85.         ConfigurationService $configService,
  86.         UrlGeneratorInterface $urlGenerator,
  87.         ShipmentEntityRepository $shipmentRepository,
  88.         ServicePointEntityRepository $servicePointRepository,
  89.         CustomerRepository $customerRepository,
  90.         OrderService $orderService,
  91.         RequestStack $requestStack,
  92.         ParameterBagInterface $params
  93.     ) {
  94.         $initializer->registerServices();
  95.         $this->configService $configService;
  96.         $this->urlGenerator $urlGenerator;
  97.         $this->shipmentRepository $shipmentRepository;
  98.         $this->servicePointRepository $servicePointRepository;
  99.         $this->customerRepository $customerRepository;
  100.         $this->orderService $orderService;
  101.         $this->requestStack $requestStack;
  102.         $this->params $params;
  103.     }
  104.     /**
  105.      * @inheritDoc
  106.      *
  107.      * @return array
  108.      * @return array
  109.      */
  110.     public static function getSubscribedEvents(): array
  111.     {
  112.         return [
  113.             CheckoutConfirmPageLoadedEvent::class => 'onConfirmPageLoad',
  114.             CheckoutFinishPageLoadedEvent::class => 'onFinishPageLoad',
  115.             CustomerEvents::CUSTOMER_WRITTEN_EVENT => 'onCustomerUpdate',
  116.             CustomerEvents::CUSTOMER_ADDRESS_WRITTEN_EVENT => 'onCustomerAddressChange',
  117.             CustomerEvents::CUSTOMER_LOGOUT_EVENT => 'onCustomerLogout',
  118.             KernelEvents::CONTROLLER => 'setRemoveServicePointFlag'
  119.         ];
  120.     }
  121.     /**
  122.      * On customer address event change
  123.      *
  124.      * @param EntityWrittenEvent $event
  125.      *
  126.      * @throws InconsistentCriteriaIdsException
  127.      */
  128.     public function onCustomerAddressChange(EntityWrittenEvent $event): void
  129.     {
  130.         $payloads $event->getPayloads();
  131.         $payload reset($payloads);
  132.         if (empty($payload['customerId'])) {
  133.             return;
  134.         }
  135.         $customer $this->customerRepository->getCustomerById($payload['customerId']);
  136.         if ($customer && $customer->getDefaultShippingAddressId() === $payload['id']) {
  137.             $this->removeSelectedServicePoint($customer->getCustomerNumber());
  138.         }
  139.     }
  140.     /**
  141.      * Saves data for delete
  142.      *
  143.      * @param ControllerEvent $controllerEvent
  144.      */
  145.     public function setRemoveServicePointFlag(ControllerEvent $controllerEvent): void
  146.     {
  147.         $request $controllerEvent->getRequest();
  148.         $routeName $request->get('_route');
  149.         self::$removeServicePoint = ($routeName !== 'frontend.checkout.finish.order');
  150.     }
  151.     /**
  152.      * Unset selected service point if customer is logout
  153.      *
  154.      * @param CustomerLogoutEvent $customerLogoutEvent
  155.      *
  156.      * @throws InconsistentCriteriaIdsException
  157.      */
  158.     public function onCustomerLogout(CustomerLogoutEvent $customerLogoutEvent): void
  159.     {
  160.         $customer $customerLogoutEvent->getCustomer();
  161.         if ($customer) {
  162.             $this->removeSelectedServicePoint($customer->getCustomerNumber());
  163.         }
  164.     }
  165.     /**
  166.      * Unset selected service point if user change his data
  167.      *
  168.      * @param EntityWrittenEvent $event
  169.      *
  170.      * @throws InconsistentCriteriaIdsException
  171.      */
  172.     public function onCustomerUpdate(EntityWrittenEvent $event): void
  173.     {
  174.         if (self::$removeServicePoint) {
  175.             $request $this->requestStack->getCurrentRequest();
  176.             $ids $event->getIds();
  177.             $customerId reset($ids);
  178.             $customer $this->customerRepository->getCustomerById($customerId);
  179.             if ($customer && $this->isShippingAddressChanged($request$customer)) {
  180.                 $this->removeSelectedServicePoint($customer->getCustomerNumber());
  181.             }
  182.         }
  183.     }
  184.     /**
  185.      * Check if shipping address changed
  186.      *
  187.      * @param Request|null $request
  188.      * @param CustomerEntity $customer
  189.      *
  190.      * @return bool
  191.      */
  192.     private function isShippingAddressChanged(?Request $requestCustomerEntity $customer): bool
  193.     {
  194.         $selectAddress $request $request->get('selectAddress') : null;
  195.         $selectAddressType = !empty($selectAddress['type']) ? $selectAddress['type'] : null;
  196.         $route $request $request->get('_route') : null;
  197.         $type $request $request->get('type') : null;
  198.         $addresses $customer->getAddresses();
  199.         $addressesCount $addresses $addresses->count() : 0;
  200.         return ($selectAddressType === 'shipping' ||
  201.                 ($selectAddressType === 'billing' && ($customer->getAddresses() !== null && $addressesCount === 1))) ||
  202.             (($route === 'frontend.account.address.set-default-address' && $type === 'shipping'));
  203.     }
  204.     /**
  205.      * Removes selected service point for specific customer
  206.      * @param string $customerNumber
  207.      *
  208.      * @throws InconsistentCriteriaIdsException
  209.      */
  210.     private function removeSelectedServicePoint(string $customerNumber): void
  211.     {
  212.         $this->servicePointRepository->deleteServicePointByCustomerNumber($customerNumber);
  213.     }
  214.     /**
  215.      * Extend order info with service point location
  216.      *
  217.      * @param CheckoutFinishPageLoadedEvent $event
  218.      *
  219.      * @throws InconsistentCriteriaIdsException
  220.      */
  221.     public function onFinishPageLoad(CheckoutFinishPageLoadedEvent $event): void
  222.     {
  223.         $shipment $this->shipmentRepository->getShipmentByOrderNumber($event->getPage()->getOrder()->getOrderNumber());
  224.         if ($shipment) {
  225.             $servicePointInfo json_decode($shipment->get('servicePointInfo'), true);
  226.             if ($servicePointInfo) {
  227.                 $event->getPage()->getOrder()->addExtension('sendcloud', new ServicePointInfo((array)$servicePointInfo));
  228.             }
  229.         }
  230.     }
  231.     /**
  232.      * Extend shipping method with parameters which are required for selecting service point location
  233.      *
  234.      * @param CheckoutConfirmPageLoadedEvent $event
  235.      *
  236.      * @throws DBALException
  237.      * @throws InconsistentCriteriaIdsException
  238.      */
  239.     public function onConfirmPageLoad(CheckoutConfirmPageLoadedEvent $event): void
  240.     {
  241.         $shippingMethods $event->getPage()->getShippingMethods();
  242.         $servicePointDeliveryId $this->configService->getSendCloudServicePointDeliveryMethodId();
  243.         /** @var ShippingMethodEntity $shippingMethod */
  244.         foreach ($shippingMethods as $shippingMethod) {
  245.             if ($shippingMethod->getId() === $servicePointDeliveryId) {
  246.                 $extensions $shippingMethod->getExtensions();
  247.                 $extensions['sendcloud'] = new ServicePointConfig([
  248.                     'isServicePointDelivery' => true,
  249.                     'servicePointDeliveryId' => $servicePointDeliveryId,
  250.                     'servicePointEndpointUrl' => $this->generateServicePointUrl(),
  251.                     'apiKey' => $this->configService->getPublicKey(),
  252.                     'carriers' => implode(','$this->configService->getCarriers()),
  253.                     'weight' => $this->orderService->calculateTotalWeight($event->getPage()->getCart()->getLineItems()),
  254.                 ]);
  255.                 $shippingMethod->setExtensions($extensions);
  256.                 $shippingMethod->jsonSerialize();
  257.             }
  258.         }
  259.         $deliveries $event->getPage()->getCart()->getDeliveries();
  260.         /** @var Delivery $delivery */
  261.         foreach ($deliveries as $delivery) {
  262.             if ($delivery->getShippingMethod()->getId() === $servicePointDeliveryId) {
  263.                 $customer $event->getSalesChannelContext()->getCustomer();
  264.                 if ($customer) {
  265.                     $servicePoint $this->servicePointRepository->getServicePointByCustomerNumber($customer->getCustomerNumber());
  266.                     if (!$servicePoint) {
  267.                         $event->getPage()->addExtension('sendcloud', new DisableSubmitButton(true));
  268.                     }
  269.                 }
  270.             }
  271.         }
  272.     }
  273.     /**
  274.      * @return string
  275.      */
  276.     private function generateServicePointUrl(): string
  277.     {
  278.         $routeName 'api.sendcloud.servicepoint.new';
  279.         $params = [];
  280.         if (version_compare($this->params->get('kernel.shopware_version'), '6.4.0''lt')) {
  281.             $routeName 'api.sendcloud.servicepoint';
  282.             $params['version'] = PlatformRequest::API_VERSION;
  283.         }
  284.         return $this->urlGenerator->generate($routeName$paramsUrlGeneratorInterface::ABSOLUTE_URL);
  285.     }
  286. }