vendor/ibexa/checkout/src/bundle/EventSubscriber/DiscountsHaveChangedExceptionSubscriber.php line 61

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. declare(strict_types=1);
  7. namespace Ibexa\Bundle\Checkout\EventSubscriber;
  8. use Ibexa\Contracts\Cart\CartServiceInterface;
  9. use Ibexa\Contracts\Checkout\Discounts\DiscountsValidationFailedException;
  10. use Ibexa\Contracts\Checkout\Exception\CheckoutException;
  11. use Ibexa\Contracts\Checkout\Value\CheckoutInterface;
  12. use Ibexa\DiscountsCodes\DiscountCodeSupplier;
  13. use Ibexa\DiscountsCodes\Value\DiscountCondition\IsValidDiscountCode;
  14. use JMS\TranslationBundle\Annotation\Desc;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\HttpFoundation\Session\Session;
  18. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  19. use Symfony\Component\HttpKernel\KernelEvents;
  20. use Symfony\Component\Routing\RouterInterface;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. final class DiscountsHaveChangedExceptionSubscriber implements EventSubscriberInterface
  23. {
  24. private RouterInterface $router;
  25. private CartServiceInterface $cartService;
  26. private TranslatorInterface $translator;
  27. private bool $enabled;
  28. private ?DiscountCodeSupplier $discountCodeSupplier;
  29. public function __construct(
  30. RouterInterface $router,
  31. CartServiceInterface $cartService,
  32. TranslatorInterface $translator,
  33. bool $enabled = true,
  34. ?DiscountCodeSupplier $discountCodeSupplier = null
  35. ) {
  36. $this->router = $router;
  37. $this->cartService = $cartService;
  38. $this->translator = $translator;
  39. $this->enabled = $enabled;
  40. $this->discountCodeSupplier = $discountCodeSupplier;
  41. }
  42. public static function getSubscribedEvents(): array
  43. {
  44. return [
  45. KernelEvents::EXCEPTION => [
  46. ['handleException', 10],
  47. ],
  48. ];
  49. }
  50. public function handleException(ExceptionEvent $event): void
  51. {
  52. if ($this->discountCodeSupplier === null || !$this->enabled) {
  53. return;
  54. }
  55. $throwable = $event->getThrowable();
  56. if (
  57. !$throwable instanceof CheckoutException
  58. || !$throwable->getPrevious() instanceof DiscountsValidationFailedException
  59. ) {
  60. return;
  61. }
  62. $checkout = $event->getRequest()->attributes->get('checkout');
  63. if (!$checkout instanceof CheckoutInterface) {
  64. return;
  65. }
  66. $cartIdentifier = $checkout->getCartIdentifier();
  67. $this->dropDiscountCode($cartIdentifier);
  68. $session = $event->getRequest()->getSession();
  69. assert($session instanceof Session);
  70. $session->getFlashBag()->add(
  71. 'checkout_errors',
  72. $this->translator->trans(
  73. /** @Desc("The applied discounts have changed since you started the checkout process. Verify your cart.") */
  74. 'checkout.error.discounts_have_changed',
  75. [],
  76. 'ibexa_checkout'
  77. )
  78. );
  79. $response = new RedirectResponse(
  80. $this->router->generate('ibexa.cart.view', [
  81. 'identifier' => $cartIdentifier,
  82. ])
  83. );
  84. $event->setResponse($response);
  85. }
  86. /**
  87. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
  88. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
  89. */
  90. private function dropDiscountCode(string $cartIdentifier): void
  91. {
  92. $cart = $this->cartService->getCart($cartIdentifier);
  93. $cartContext = $cart->getContext();
  94. if (
  95. $cartContext === null
  96. || !$cartContext->has(IsValidDiscountCode::CART_DISCOUNT_CODE_KEY)
  97. ) {
  98. return;
  99. }
  100. assert($this->discountCodeSupplier !== null);
  101. $this->discountCodeSupplier->drop(
  102. $cart,
  103. $cartContext->get(IsValidDiscountCode::CART_DISCOUNT_CODE_KEY)
  104. );
  105. }
  106. }