custom/plugins/SendcloudShipping/src/Subscriber/OrderSubscriber.php line 161

Open in your IDE?
  1. <?php
  2. namespace Sendcloud\Shipping\Subscriber;
  3. use Doctrine\DBAL\DBALException;
  4. use Sendcloud\Shipping\Core\BusinessLogic\Interfaces\ConnectService;
  5. use Sendcloud\Shipping\Core\BusinessLogic\Sync\OrderCancelTask;
  6. use Sendcloud\Shipping\Core\BusinessLogic\Sync\OrderSyncTask;
  7. use Sendcloud\Shipping\Core\Infrastructure\Interfaces\Required\Configuration;
  8. use Sendcloud\Shipping\Core\Infrastructure\Logger\Logger;
  9. use Sendcloud\Shipping\Core\Infrastructure\TaskExecution\Exceptions\QueueStorageUnavailableException;
  10. use Sendcloud\Shipping\Core\Infrastructure\TaskExecution\Queue;
  11. use Sendcloud\Shipping\Core\Infrastructure\TaskExecution\Task;
  12. use Sendcloud\Shipping\Entity\Order\OrderRepository;
  13. use Sendcloud\Shipping\Entity\ServicePoint\ServicePointEntityRepository;
  14. use Sendcloud\Shipping\Entity\Shipment\ShipmentEntityRepository;
  15. use Sendcloud\Shipping\Service\Business\ConfigurationService;
  16. use Sendcloud\Shipping\Service\Utility\Initializer;
  17. use Sendcloud\Shipping\Struct\ServicePointInfo;
  18. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  19. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  20. use Shopware\Core\Checkout\Order\OrderEntity;
  21. use Shopware\Core\Checkout\Order\OrderEvents;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  23. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  24. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  25. use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedEvent;
  26. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  27. use Symfony\Component\HttpFoundation\RequestStack;
  28. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  29. /**
  30.  * Class OrderSubscriber
  31.  *
  32.  * @package Sendcloud\Shipping\\Subscriber
  33.  */
  34. class OrderSubscriber implements EventSubscriberInterface
  35. {
  36.     private static $orderNumberMap = [];
  37.     /**
  38.      * @var OrderRepository
  39.      */
  40.     private $orderRepository;
  41.     /**
  42.      * @var ServicePointEntityRepository
  43.      */
  44.     private $servicePointRepository;
  45.     /**
  46.      * @var Queue
  47.      */
  48.     private $queue;
  49.     /**
  50.      * @var ConnectService
  51.      */
  52.     private $connectService;
  53.     /**
  54.      * @var ConfigurationService
  55.      */
  56.     private $configService;
  57.     /**
  58.      * @var ShipmentEntityRepository
  59.      */
  60.     private $shipmentRepository;
  61.     /**
  62.      * @var RequestStack
  63.      */
  64.     private $requestStack;
  65.     /**
  66.      * OrderSubscriber constructor.
  67.      *
  68.      * @param OrderRepository $orderRepository
  69.      * @param ServicePointEntityRepository $servicePointEntityRepository
  70.      * @param Initializer $initializer
  71.      * @param ConnectService $connectService
  72.      * @param Queue $queue
  73.      * @param Configuration $configService
  74.      * @param ShipmentEntityRepository $shipmentRepository
  75.      */
  76.     public function __construct(
  77.         OrderRepository $orderRepository,
  78.         ServicePointEntityRepository $servicePointEntityRepository,
  79.         Initializer $initializer,
  80.         ConnectService $connectService,
  81.         Queue $queue,
  82.         Configuration $configService,
  83.         ShipmentEntityRepository $shipmentRepository,
  84.         RequestStack $requestStack
  85.     ) {
  86.         $initializer->registerServices();
  87.         $this->orderRepository $orderRepository;
  88.         $this->servicePointRepository $servicePointEntityRepository;
  89.         $this->connectService $connectService;
  90.         $this->queue $queue;
  91.         $this->configService $configService;
  92.         $this->shipmentRepository $shipmentRepository;
  93.         $this->requestStack $requestStack;
  94.     }
  95.     /**
  96.      * @inheritDoc
  97.      *
  98.      * @return string[]
  99.      */
  100.     public static function getSubscribedEvents(): array
  101.     {
  102.         return [
  103.             OrderEvents::ORDER_WRITTEN_EVENT => 'onOrderSave',
  104.             OrderEvents::ORDER_DELETED_EVENT => 'onOrderDelete',
  105.             CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
  106.             AccountOrderPageLoadedEvent::class => 'onOrderLoaded',
  107.             ControllerEvent::class => 'saveDataForDelete',
  108.         ];
  109.     }
  110.     /**
  111.      * Add service point info for mail template
  112.      *
  113.      * @param CheckoutOrderPlacedEvent $event
  114.      *
  115.      * @throws InconsistentCriteriaIdsException
  116.      */
  117.     public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
  118.     {
  119.         $order $event->getOrder();
  120.         if ($order) {
  121.             $shipment $this->shipmentRepository->getShipmentByOrderNumber($order->getOrderNumber());
  122.             $servicePointInfo $shipment json_decode($shipment->get('servicePointInfo'), true) : [];
  123.             $order->addExtension('sendcloud', new ServicePointInfo((array)$servicePointInfo));
  124.         }
  125.     }
  126.     /**
  127.      * Adds service point information on order object if exists
  128.      *
  129.      * @param AccountOrderPageLoadedEvent $event
  130.      * @throws InconsistentCriteriaIdsException
  131.      */
  132.     public function onOrderLoaded(AccountOrderPageLoadedEvent $event): void
  133.     {
  134.         /** @var OrderEntity $order */
  135.         foreach ($event->getPage()->getOrders() as $order) {
  136.             $shipment $this->shipmentRepository->getShipmentByOrderNumber($order->getOrderNumber());
  137.             if ($shipment) {
  138.                 $servicePointInfo json_decode($shipment->get('servicePointInfo'), true);
  139.                 if ($servicePointInfo) {
  140.                     $order->addExtension('sendcloud', new ServicePointInfo((array)$servicePointInfo));
  141.                 }
  142.             }
  143.         }
  144.     }
  145.     /**
  146.      * Enqueues OrderCancelTask for each deleted order
  147.      *
  148.      * @param EntityDeletedEvent $event
  149.      *
  150.      * @throws QueueStorageUnavailableException
  151.      */
  152.     public function onOrderDelete(EntityDeletedEvent $event): void
  153.     {
  154.         $ids $event->getIds();
  155.         foreach ($ids as $id) {
  156.             if (in_array($idself::$orderNumberMap)) {
  157.                 Logger::logInfo("Order delete event detected. Deleted order id: {$id}"'Integration');
  158.                 $this->enqueueTask($this->configService->getEntityQueueName('order'$id), new OrderCancelTask($id));
  159.             }
  160.         }
  161.     }
  162.     /**
  163.      * Stores shipment info and enqueues order sync task
  164.      *
  165.      * @param EntityWrittenEvent $event
  166.      *
  167.      * @throws DBALException
  168.      * @throws InconsistentCriteriaIdsException
  169.      * @throws QueueStorageUnavailableException
  170.      */
  171.     public function onOrderSave(EntityWrittenEvent $event): void
  172.     {
  173.         $request $this->requestStack->getCurrentRequest();
  174.         if ($request && $request->get('_route') !== 'api.createVersion') {
  175.             $ids $event->getIds();
  176.             $jsonIds json_encode($ids);
  177.             Logger::logInfo("Order created event detected. Order id: {$jsonIds}"'Integration');
  178.             $this->saveServicePointInfo(reset($ids));
  179.             foreach ($ids as $id) {
  180.                 $this->enqueueTask($this->configService->getEntityQueueName('order'$id), new OrderSyncTask([$id]));
  181.             }
  182.         }
  183.     }
  184.     /**
  185.      * Saves data for delete
  186.      *
  187.      * @param ControllerEvent $controllerEvent
  188.      *
  189.      * @throws InconsistentCriteriaIdsException
  190.      */
  191.     public function saveDataForDelete(ControllerEvent $controllerEvent): void
  192.     {
  193.         $request $controllerEvent->getRequest();
  194.         $routeName $request->get('_route');
  195.         if ($routeName === 'api.order.delete') {
  196.             $path $request->get('path');
  197.             // check if route contains subpaths
  198.             if (!strpos($path'/')) {
  199.                 $this->saveOrderNumber($path);
  200.             }
  201.         }
  202.     }
  203.     /**
  204.      * Enqueues given task
  205.      *
  206.      * @param string $queueName
  207.      * @param Task $task
  208.      *
  209.      * @throws QueueStorageUnavailableException
  210.      */
  211.     private function enqueueTask(string $queueNameTask $task): void
  212.     {
  213.         if ($this->connectService->isIntegrationConnected()) {
  214.             $this->queue->enqueue($queueName$task);
  215.         }
  216.     }
  217.     /**
  218.      * Stores service point information into shipments table if Service Point Delivery method is selected
  219.      *
  220.      * @param string $orderId
  221.      *
  222.      * @throws InconsistentCriteriaIdsException
  223.      * @throws DBALException
  224.      */
  225.     private function saveServicePointInfo(string $orderId): void
  226.     {
  227.         $order $this->orderRepository->getOrderById($orderId);
  228.         if ($order && ($deliveries $order->getDeliveries()) && ($customer $order->getOrderCustomer())) {
  229.             /** @var OrderDeliveryEntity $delivery */
  230.             $delivery $deliveries->first() ?: null;
  231.             if ($delivery && $delivery->getShippingMethodId() === $this->configService->getSendCloudServicePointDeliveryMethodId()) {
  232.                 $servicePointEntity $this->servicePointRepository->getServicePointByCustomerNumber($customer->getCustomerNumber());
  233.                 if ($servicePointEntity) {
  234.                     $this->shipmentRepository->updateServicePoint($order->getOrderNumber(), (array)json_decode($servicePointEntity->get('servicePointInfo'), true));
  235.                     $this->servicePointRepository->deleteServicePointByCustomerNumber($customer->getCustomerNumber());
  236.                 }
  237.             }
  238.         }
  239.     }
  240.     /**
  241.      * Saves order number before it is deleted
  242.      *
  243.      * @param string $orderId
  244.      *
  245.      * @throws InconsistentCriteriaIdsException
  246.      */
  247.     private function saveOrderNumber(string $orderId): void
  248.     {
  249.         $order $this->orderRepository->getOrderById($orderId);
  250.         if ($order) {
  251.             self::$orderNumberMap[] = $orderId;
  252.         }
  253.     }
  254. }