vendor/coreshop/core-shop/src/CoreShop/Bundle/FrontendBundle/Controller/CartController.php line 366

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * CoreShop
  5.  *
  6.  * This source file is available under two different licenses:
  7.  *  - GNU General Public License version 3 (GPLv3)
  8.  *  - CoreShop Commercial License (CCL)
  9.  * Full copyright and license information is available in
  10.  * LICENSE.md which is distributed with this source code.
  11.  *
  12.  * @copyright  Copyright (c) CoreShop GmbH (https://www.coreshop.org)
  13.  * @license    https://www.coreshop.org/license     GPLv3 and CCL
  14.  *
  15.  */
  16. namespace CoreShop\Bundle\FrontendBundle\Controller;
  17. use CoreShop\Bundle\OrderBundle\DTO\AddToCartInterface;
  18. use CoreShop\Bundle\OrderBundle\Factory\AddToCartFactoryInterface;
  19. use CoreShop\Bundle\OrderBundle\Form\Type\AddToCartType;
  20. use CoreShop\Bundle\OrderBundle\Form\Type\CartType;
  21. use CoreShop\Bundle\OrderBundle\Form\Type\ShippingCalculatorType;
  22. use CoreShop\Bundle\WorkflowBundle\Manager\StateMachineManagerInterface;
  23. use CoreShop\Component\Address\Model\AddressInterface;
  24. use CoreShop\Component\Core\Order\Modifier\CartItemQuantityModifier;
  25. use CoreShop\Component\Order\Cart\CartModifierInterface;
  26. use CoreShop\Component\Order\Cart\Rule\CartPriceRuleProcessorInterface;
  27. use CoreShop\Component\Order\Cart\Rule\CartPriceRuleUnProcessorInterface;
  28. use CoreShop\Component\Order\Context\CartContextInterface;
  29. use CoreShop\Component\Order\Manager\CartManagerInterface;
  30. use CoreShop\Component\Order\Model\CartPriceRuleVoucherCodeInterface;
  31. use CoreShop\Component\Order\Model\OrderInterface;
  32. use CoreShop\Component\Order\Model\OrderItemInterface;
  33. use CoreShop\Component\Order\Model\PurchasableInterface;
  34. use CoreShop\Component\Order\OrderSaleTransitions;
  35. use CoreShop\Component\Order\Repository\CartPriceRuleVoucherRepositoryInterface;
  36. use CoreShop\Component\Shipping\Calculator\TaxedShippingCalculatorInterface;
  37. use CoreShop\Component\Shipping\Resolver\CarriersResolverInterface;
  38. use CoreShop\Component\StorageList\StorageListItemQuantityModifierInterface;
  39. use CoreShop\Component\Tracking\Tracker\TrackerInterface;
  40. use Symfony\Component\EventDispatcher\GenericEvent;
  41. use Symfony\Component\Form\FormError;
  42. use Symfony\Component\HttpFoundation\JsonResponse;
  43. use Symfony\Component\HttpFoundation\Request;
  44. use Symfony\Component\HttpFoundation\Response;
  45. use Symfony\Component\HttpFoundation\Session\Session;
  46. use Symfony\Component\Validator\ConstraintViolationListInterface;
  47. class CartController extends FrontendController
  48. {
  49.     public function widgetAction(Request $request): Response
  50.     {
  51.         return $this->render($this->templateConfigurator->findTemplate('Cart/_widget.html'), [
  52.             'cart' => $this->getCart(),
  53.         ]);
  54.     }
  55.     public function createQuoteAction(Request $requestStateMachineManagerInterface $machineManager)
  56.     {
  57.         $this->denyAccessUnlessGranted('CORESHOP_QUOTE_CREATE');
  58.         $order $this->getCart();
  59.         $workflow $machineManager->get($orderOrderSaleTransitions::IDENTIFIER);
  60.         $workflow->apply($orderOrderSaleTransitions::TRANSITION_QUOTE);
  61.         return $this->redirectToRoute('coreshop_quote_detail', ['quote' => $order->getId()]);
  62.     }
  63.     public function summaryAction(Request $request): Response
  64.     {
  65.         $this->denyAccessUnlessGranted('CORESHOP_CART');
  66.         $this->denyAccessUnlessGranted('CORESHOP_CART_SUMMARY');
  67.         $cart $this->getCart();
  68.         $form $this->get('form.factory')->createNamed('coreshop'CartType::class, $cart);
  69.         $form->handleRequest($request);
  70.         if (in_array($request->getMethod(), ['POST''PUT''PATCH']) && $form->isSubmitted()) {
  71.             if ($form->isValid()) {
  72.                 $cart $form->getData();
  73.                 $code $form->get('cartRuleCoupon')->getData();
  74.                 if (method_exists($form'getClickedButton')) {
  75.                     $submit $form->getClickedButton();
  76.                     $validateVoucherCode $submit && 'submit_voucher' === $submit->getName();
  77.                 } else {
  78.                     $validateVoucherCode = (bool) $code;
  79.                 }
  80.                 if ($validateVoucherCode) {
  81.                     $voucherCode $this->getCartPriceRuleVoucherRepository()->findByCode($code ?? '');
  82.                     if (!$voucherCode instanceof CartPriceRuleVoucherCodeInterface) {
  83.                         $this->addFlash(
  84.                             'error',
  85.                             $this->get('translator')->trans('coreshop.ui.error.voucher.not_found'),
  86.                         );
  87.                         return $this->redirectToRoute('coreshop_cart_summary');
  88.                     }
  89.                     $priceRule $voucherCode->getCartPriceRule();
  90.                     if ($this->getCartPriceRuleProcessor()->process($cart$priceRule$voucherCode)) {
  91.                         $this->getCartManager()->persistCart($cart);
  92.                         $this->addFlash(
  93.                             'success',
  94.                             $this->get('translator')->trans('coreshop.ui.success.voucher.stored'),
  95.                         );
  96.                     } else {
  97.                         $this->addFlash('error'$this->get('translator')->trans('coreshop.ui.error.voucher.invalid'));
  98.                     }
  99.                 } else {
  100.                     $this->addFlash('success'$this->get('translator')->trans('coreshop.ui.cart_updated'));
  101.                 }
  102.                 $this->get('event_dispatcher')->dispatch(new GenericEvent($cart), 'coreshop.cart.update');
  103.                 $this->getCartManager()->persistCart($cart);
  104.                 return $this->redirectToRoute('coreshop_cart_summary');
  105.             }
  106.             $session $request->getSession();
  107.             if ($session instanceof Session) {
  108.                 foreach ($form->getErrors() as $error) {
  109.                     $session->getFlashBag()->add('error'$error->getMessage());
  110.                 }
  111.                 return $this->redirectToRoute('coreshop_cart_summary');
  112.             }
  113.         }
  114.         return $this->render($this->templateConfigurator->findTemplate('Cart/summary.html'), [
  115.             'cart' => $cart,
  116.             'form' => $form->createView(),
  117.         ]);
  118.     }
  119.     public function shipmentCalculationAction(Request $request): Response
  120.     {
  121.         $this->denyAccessUnlessGranted('CORESHOP_CART');
  122.         $this->denyAccessUnlessGranted('CORESHOP_CART_CALCULATE_SHIPMENT');
  123.         $cart $this->getCart();
  124.         $form $this->get('form.factory')->createNamed('coreshop'ShippingCalculatorType::class, null, [
  125.             'action' => $this->generateUrl('coreshop_cart_check_shipment'),
  126.         ]);
  127.         $availableCarriers = [];
  128.         $form->handleRequest($request);
  129.         //check if there is a shipping calculation request
  130.         if (in_array($request->getMethod(), ['POST''PUT''PATCH']) && $form->isSubmitted() && $form->isValid()) {
  131.             $shippingCalculatorFormData $form->getData();
  132.             $carrierPriceCalculator $this->get(TaxedShippingCalculatorInterface::class);
  133.             $carriersResolver $this->get(CarriersResolverInterface::class);
  134.             /** @var AddressInterface $virtualAddress */
  135.             $virtualAddress $this->get('coreshop.factory.address')->createNew();
  136.             $virtualAddress->setCountry($shippingCalculatorFormData['country']);
  137.             $virtualAddress->setPostcode($shippingCalculatorFormData['zip']);
  138.             $carriers $carriersResolver->resolveCarriers($cart$virtualAddress);
  139.             foreach ($carriers as $carrier) {
  140.                 $price $carrierPriceCalculator->getPrice($carrier$cart$virtualAddress);
  141.                 $priceWithoutTax $carrierPriceCalculator->getPrice($carrier$cart$virtualAddressfalse);
  142.                 $availableCarriers[] = [
  143.                     'name' => $carrier->getTitle(),
  144.                     'isFreeShipping' => $price === 0,
  145.                     'price' => $price,
  146.                     'priceWithoutTax' => $priceWithoutTax,
  147.                     'data' => $carrier,
  148.                 ];
  149.             }
  150.             uasort($availableCarriers, function ($a$b) {
  151.                 return $a['price'] > $b['price'];
  152.             });
  153.         }
  154.         return $this->render($this->templateConfigurator->findTemplate('Cart/ShipmentCalculator/_widget.html'), [
  155.             'cart' => $cart,
  156.             'form' => $form->createView(),
  157.             'availableCarriers' => $availableCarriers,
  158.         ]);
  159.     }
  160.     public function addItemAction(Request $request): Response
  161.     {
  162.         $this->denyAccessUnlessGranted('CORESHOP_CART');
  163.         $this->denyAccessUnlessGranted('CORESHOP_CART_ADD_ITEM');
  164.         $redirect $this->getParameterFromRequest($request'_redirect'$this->generateUrl('coreshop_index'));
  165.         $product $this->get('coreshop.repository.stack.purchasable')->find($this->getParameterFromRequest($request'product'));
  166.         if (!$product instanceof PurchasableInterface) {
  167.             if ($request->isXmlHttpRequest()) {
  168.                 return new JsonResponse([
  169.                     'success' => false,
  170.                 ]);
  171.             }
  172.             return $this->redirect($redirect);
  173.         }
  174.         $cartItem $this->get('coreshop.factory.order_item')->createWithPurchasable($product);
  175.         $this->getQuantityModifer()->modify($cartItem1);
  176.         $addToCart $this->createAddToCart($this->getCart(), $cartItem);
  177.         $form $this->get('form.factory')->createNamed('coreshop-' $product->getId(), AddToCartType::class, $addToCart);
  178.         if ($request->isMethod('POST')) {
  179.             $redirect $this->getParameterFromRequest($request'_redirect'$this->generateUrl('coreshop_cart_summary'));
  180.             $form->handleRequest($request);
  181.             if ($form->isSubmitted() && $form->isValid()) {
  182.                 /**
  183.                  * @var AddToCartInterface $addToCart
  184.                  */
  185.                 $addToCart $form->getData();
  186.                 $this->getCartModifier()->addToList($addToCart->getCart(), $addToCart->getCartItem());
  187.                 $this->getCartManager()->persistCart($this->getCart());
  188.                 $this->get(TrackerInterface::class)->trackCartAdd(
  189.                     $addToCart->getCart(),
  190.                     $addToCart->getCartItem()->getProduct(),
  191.                     $addToCart->getCartItem()->getQuantity(),
  192.                 );
  193.                 $this->addFlash('success'$this->get('translator')->trans('coreshop.ui.item_added'));
  194.                 if ($request->isXmlHttpRequest()) {
  195.                     return new JsonResponse([
  196.                         'success' => true,
  197.                     ]);
  198.                 }
  199.                 return $this->redirect($redirect);
  200.             }
  201.             foreach ($form->getErrors(truetrue) as $error) {
  202.                 $this->addFlash('error'$error->getMessage());
  203.             }
  204.             if ($request->isXmlHttpRequest()) {
  205.                 return new JsonResponse([
  206.                     'success' => false,
  207.                     'errors' => array_map(function (FormError $error) {
  208.                         return $error->getMessage();
  209.                     }, iterator_to_array($form->getErrors(true))),
  210.                 ]);
  211.             }
  212.             return $this->redirect($redirect);
  213.         }
  214.         if ($request->isXmlHttpRequest()) {
  215.             return new JsonResponse([
  216.                 'success' => false,
  217.             ]);
  218.         }
  219.         return $this->render(
  220.             $this->getParameterFromRequest($request'template'$this->templateConfigurator->findTemplate('Product/_addToCart.html')),
  221.             [
  222.                 'form' => $form->createView(),
  223.                 'product' => $product,
  224.             ],
  225.         );
  226.     }
  227.     public function removeItemAction(Request $request): Response
  228.     {
  229.         $this->denyAccessUnlessGranted('CORESHOP_CART');
  230.         $this->denyAccessUnlessGranted('CORESHOP_CART_REMOVE_ITEM');
  231.         $cartItem $this->get('coreshop.repository.order_item')->find($this->getParameterFromRequest($request'cartItem'));
  232.         if (!$cartItem instanceof OrderItemInterface) {
  233.             return $this->redirectToRoute('coreshop_index');
  234.         }
  235.         if ($cartItem->getOrder()->getId() !== $this->getCart()->getId()) {
  236.             return $this->redirectToRoute('coreshop_index');
  237.         }
  238.         $this->addFlash('success'$this->get('translator')->trans('coreshop.ui.item_removed'));
  239.         $this->getCartModifier()->removeFromList($this->getCart(), $cartItem);
  240.         $this->getCartManager()->persistCart($this->getCart());
  241.         $request->attributes->set('product'$cartItem->getProduct());
  242.         $this->get(TrackerInterface::class)->trackCartRemove($this->getCart(), $cartItem->getProduct(), $cartItem->getQuantity());
  243.         return $this->redirectToRoute('coreshop_cart_summary');
  244.     }
  245.     public function removePriceRuleAction(Request $request): Response
  246.     {
  247.         $this->denyAccessUnlessGranted('CORESHOP_CART');
  248.         $this->denyAccessUnlessGranted('CORESHOP_CART_REMOVE_PRICE_RULE');
  249.         $code $this->getParameterFromRequest($request'code');
  250.         $cart $this->getCart();
  251.         $voucherCode $this->getCartPriceRuleVoucherRepository()->findByCode($code);
  252.         if (!$voucherCode instanceof CartPriceRuleVoucherCodeInterface) {
  253.             return $this->redirectToRoute('coreshop_cart_summary');
  254.         }
  255.         $priceRule $voucherCode->getCartPriceRule();
  256.         $this->getCartPriceRuleUnProcessor()->unProcess($cart$priceRule$voucherCode);
  257.         $this->getCartManager()->persistCart($cart);
  258.         return $this->redirectToRoute('coreshop_cart_summary');
  259.     }
  260.     protected function createAddToCart(OrderInterface $cartOrderItemInterface $cartItem): AddToCartInterface
  261.     {
  262.         return $this->get(AddToCartFactoryInterface::class)->createWithCartAndCartItem($cart$cartItem);
  263.     }
  264.     protected function getCartPriceRuleProcessor(): CartPriceRuleProcessorInterface
  265.     {
  266.         return $this->get(CartPriceRuleProcessorInterface::class);
  267.     }
  268.     protected function getCartPriceRuleUnProcessor(): CartPriceRuleUnProcessorInterface
  269.     {
  270.         return $this->get(CartPriceRuleUnProcessorInterface::class);
  271.     }
  272.     protected function getCartModifier(): CartModifierInterface
  273.     {
  274.         return $this->get(CartModifierInterface::class);
  275.     }
  276.     protected function getQuantityModifer(): StorageListItemQuantityModifierInterface
  277.     {
  278.         return $this->get(CartItemQuantityModifier::class);
  279.     }
  280.     protected function getCartPriceRuleVoucherRepository(): CartPriceRuleVoucherRepositoryInterface
  281.     {
  282.         return $this->get('coreshop.repository.cart_price_rule_voucher_code');
  283.     }
  284.     protected function getCart(): OrderInterface
  285.     {
  286.         return $this->getCartContext()->getCart();
  287.     }
  288.     protected function getCartContext(): CartContextInterface
  289.     {
  290.         return $this->get(CartContextInterface::class);
  291.     }
  292.     protected function getCartManager(): CartManagerInterface
  293.     {
  294.         return $this->get(CartManagerInterface::class);
  295.     }
  296.     private function getCartItemErrors(OrderItemInterface $cartItem): ConstraintViolationListInterface
  297.     {
  298.         return $this
  299.             ->get('validator')
  300.             ->validate($cartItemnull$this->container->getParameter('coreshop.form.type.cart_item.validation_groups'))
  301.         ;
  302.     }
  303. }