src/EventSubscriber/Shop/BeforeOrderCreateSubscriber.php line 58

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\EventSubscriber\Shop;
  4. use ApiPlatform\Core\EventListener\EventPriorities;
  5. use App\Entity\Ledger\Account;
  6. use App\Entity\Shop\Order;
  7. use App\Exceptions\Shop\BuyerAlreadyHasAnyItemsException;
  8. use App\Services\Shop\OrderItemValidator;
  9. use App\Services\Transaction\CreateService;
  10. use App\Services\Transaction\Types\TypeCreatorInterface;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpKernel\Event\ViewEvent;
  14. use Symfony\Component\HttpKernel\KernelEvents;
  15. use Symfony\Component\Workflow\WorkflowInterface;
  16. class BeforeOrderCreateSubscriber implements EventSubscriberInterface
  17. {
  18.     protected const COMMENT 'Checkout order #%s';
  19.     public function __construct(
  20.         private readonly TypeCreatorInterface $payTypeCreator,
  21.         private readonly OrderItemValidator $orderItemValidator,
  22.         private readonly WorkflowInterface $orderStateMachine,
  23.         private readonly CreateService $transactionService,
  24.         private readonly Account $bankAccount,
  25.     ) {
  26.     }
  27.     public static function getSubscribedEvents(): array
  28.     {
  29.         return [
  30.             KernelEvents::VIEW => [
  31.                 ['validate'EventPriorities::PRE_WRITE 1],
  32.                 ['checkout'EventPriorities::PRE_WRITE],
  33.             ],
  34.         ];
  35.     }
  36.     /**
  37.      * @throws BuyerAlreadyHasAnyItemsException
  38.      */
  39.     public function validate(ViewEvent $event): void
  40.     {
  41.         if (!$this->support($event)) {
  42.             return;
  43.         }
  44.         $this->orderItemValidator->validate($this->getOrder($event));
  45.     }
  46.     /**
  47.      * @throws \Throwable
  48.      */
  49.     public function checkout(ViewEvent $event): void
  50.     {
  51.         if (!$this->support($event)) {
  52.             return;
  53.         }
  54.         $order $this->getOrder($event);
  55.         $payType $this->payTypeCreator->createType(
  56.             $order->getBuyer()->getMainAccount(),
  57.             $this->bankAccount,
  58.             $order->getTotal(),
  59.             sprintf(self::COMMENT$order->getId()),
  60.         );
  61.         try {
  62.             $this->transactionService->perform($payType);
  63.             $this->orderStateMachine->apply($order'pay');
  64.         } catch (\Throwable $e) {
  65.             $this->orderStateMachine->apply($order'reject');
  66.             throw $e;
  67.         }
  68.     }
  69.     private function support(ViewEvent $event): bool
  70.     {
  71.         $method $event->getRequest()->getMethod();
  72.         $order $event->getControllerResult();
  73.         return $order instanceof Order && Request::METHOD_POST === $method;
  74.     }
  75.     private function getOrder(ViewEvent $event): Order
  76.     {
  77.         return $event->getControllerResult();
  78.     }
  79. }