src/CoreBundle/Controller/CartController.php line 21

Open in your IDE?
  1. <?php
  2. namespace CoreBundle\Controller;
  3. use CoreBundle\{Helper\CoreBundleHelper,
  4.     Helper\ProductHelper,
  5.     Model\DefaultProductFood,
  6.     Services\CartProductStockChecker,
  7.     TagManager\Models\Product
  8. };
  9. use Pimcore\Db;
  10. use Pimcore\Model\DataObject;
  11. use Pimcore\Model\WebsiteSetting;
  12. use Psr\Log\LoggerInterface;
  13. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  14. use Pimcore\Model\Site;
  15. use Symfony\Component\HttpFoundation\Response;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. class CartController extends AbstractController
  19. {
  20.     /**+
  21.      * @param Request $request
  22.      * @return Response
  23.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  24.      */
  25.     public function infoAction(Request $request): Response
  26.     {
  27.         $cart $this->getCart();
  28.         $message '';
  29.         $productId $request->get('productId');
  30.         $newAmount $request->get('newAmount');
  31.         if (Site::isSiteRequest()) {
  32.             $bundleName Site::getCurrentSite()->getRootDocument()->getModule() ?: "";
  33.             if ($bundleName == 'MautnerFoodserviceBundle') {
  34.                 $bundleName 'MautnerBundle';
  35.             }
  36.             $environment Factory::getInstance()->getEnvironment();
  37.             if ($environment->getCurrentCheckoutTenant() != $bundleName) {
  38.                 $environment->setCurrentCheckoutTenant($bundleName);
  39.                 $environment->save();
  40.             }
  41.         }
  42.         if ($productId !== null && $newAmount !== null) {
  43.             // TODO: remove or change amount
  44.             $quantity = (int)$newAmount;
  45.             if ($quantity 0) {
  46.                 $checkoutManager Factory::getInstance()->getCheckoutManager($cart);
  47.                 // Set cart order state to null because if it's in paymentPending it locks into read only mode
  48.                 if ($checkoutManager->getOrder()->getOrderState())
  49.                     $checkoutManager->getOrder()->setOrderState(null);
  50.                 $cartItems $cart->getItems();
  51.                 foreach ($cartItems as $cartItem) {
  52.                     $itemKey $cartItem->getItemKey();
  53.                     //stock handling
  54.                     $amount $cartItem->getCount();
  55.                     $product $cartItem->getProduct();
  56.                     if ($itemKey == $productId) {
  57.                         $stock $product->getStock() - $quantity;
  58.                         if ($stock >= 0) {
  59.                             if ($quantity 0) {
  60.                                 $exceeded $this->isMaximumOrderableQuantityPerOrder(0$product$quantity);
  61.                                 if ($exceeded) {
  62.                                     $message $product->getOSName() . ': ' $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
  63.                                     $this->addFlash('error', ['id' => $product->getId(), 'message' => $message]);
  64.                                     break;
  65.                                 }
  66.                                 $cart->updateItemCount($itemKey$quantity);
  67.                             }
  68.                         } else {
  69.                             $exceeded $this->isMaximumOrderableQuantityPerOrder(0$product$quantity);
  70.                             if ($exceeded) {
  71.                                 $message $product->getOSName() . ': ' $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
  72.                                 $this->addFlash('error', ['id' => $itemKey'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
  73.                                 break;
  74.                             }
  75.                             $stock $product->getStock();
  76.                             $message $this->get("translator")->trans("outOfStockP1") . $quantity $this->get("translator")->trans("outOfStockP2") . $stock $this->get("translator")->trans("outOfStockP3");
  77.                             $this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("outOfStockP1") . $quantity $this->get("translator")->trans("outOfStockP2") . $stock $this->get("translator")->trans("outOfStockP3")]);
  78.                         }
  79.                     }
  80.                 }
  81.                 $cart->save();
  82.             } else {
  83.                 $cart->removeItem($productId);
  84.                 $cart->save();
  85.             }
  86.         }
  87.         /** @var CartProductStockChecker $cartProductStockChecker */
  88.         $cartProductStockChecker $this->get('core.cart_product_stock_checker');
  89.         $messages $cartProductStockChecker->checkStockOfProductinCart($cart);
  90.         if (count($messages) > 0) {
  91.             foreach ($messages as $message) {
  92.                 $this->addFlash('error'$message);
  93.             }
  94.         }
  95.         $checkoutManager Factory::getInstance()->getCheckoutManager($cart);
  96.         if ($cart->getItemCount() > 0) {
  97.             // Set cart order state to null because if it's in paymentPending it locks into read only mode
  98.             if ($checkoutManager->getOrder()->getOrderState()) {
  99.                 $checkoutManager->getOrder()->setOrderState(null);
  100.             }
  101.         }
  102.         $siteId null;
  103.         if (\Pimcore\Model\Site::isSiteRequest()) {
  104.             $site = \Pimcore\Model\Site::getCurrentSite();
  105.             $siteId $site->getId();
  106.         }
  107.         // FreeGift pricing Rule
  108.         $freeGiftCartAmount null;
  109.         $setting WebsiteSetting::getByName('freeGiftPricingRuleName'$siteId);
  110.         if ($setting instanceof WebsiteSetting) {
  111.             $freeGiftPricingRuleName $setting->getData();
  112.             $db DB::get();
  113.             $data $db->fetchOne("SELECT `condition` FROM ecommerceframework_pricing_rule WHERE `name` = ? AND `active` = 1 LIMIT 1", [$freeGiftPricingRuleName]);
  114.             if ($data) {
  115.                 $obj unserialize($data);
  116.                 if ($obj instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Bracket){
  117.                     $cartAmount $obj->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
  118.                     if (isset($cartAmount[0])) {
  119.                         $freeGiftCartAmount $cartAmount[0]->getLimit();
  120.                     }
  121.                 }
  122.             }
  123.         }
  124.         // Get free shipping limit
  125.         $freeShippingLimit null;
  126.         $amountUntilFreeDelivery $freeShippingLimit;
  127.         $listing = new \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Rule\Listing();
  128.         $listing->addConditionParam("name LIKE '%Versandkostenfrei_ab_Warenkorbwert' AND active = 1");
  129.         $allPricingRules $listing->load();
  130.         foreach ($allPricingRules as $rule) {
  131.             $conditionsByTenant $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Tenant');
  132.             if (isset($conditionsByTenant[0])) {
  133.                 $tenants $conditionsByTenant[0]->getTenant();
  134.                 if (isset($tenants[0]) && $bundleName === $tenants[0]) {
  135.                     $actions $rule->getActions();
  136.                     foreach ($actions as $action) {
  137.                         if ($action instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Action\FreeShipping) {
  138.                             $conditionsByCartAmount $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
  139.                             if (isset($conditionsByCartAmount[0])) {
  140.                                 $freeShippingLimit = (float)$conditionsByCartAmount[0]->getLimit();
  141.                             }
  142.                         }
  143.                     }
  144.                 }
  145.             }
  146.         }
  147.         $calculator $cart->getPriceCalculator();
  148.         $subTotal $calculator->getSubTotal();
  149.         $cartSubTotal $subTotal->getGrossAmount()->asNumeric();
  150.         if ($freeShippingLimit) {
  151.             $amountUntilFreeDelivery $freeShippingLimit $cartSubTotal;
  152.         }
  153.         $amountUntilFreeGift null;
  154.         if ($freeGiftCartAmount !== null && $freeGiftCartAmount 0) {
  155.             $amountUntilFreeGift $freeGiftCartAmount $cartSubTotal;
  156.         }
  157.         $params = [
  158.             'message' => $message,
  159.             'cart' => $cart,
  160.             'freeShippingLimit' => $freeShippingLimit,
  161.             'amountUntilFreeDelivery' => $amountUntilFreeDelivery,
  162.             'amountUntilFreeGift' => $amountUntilFreeGift,
  163.             'cartSubTotal' => $cartSubTotal,
  164.             'calculator' => $calculator,
  165.             'bundleName' => $bundleName,
  166.         ];
  167.         return $this->render('Cart/sidebar.html.twig'$params);
  168.     }
  169.     /**
  170.      * @param Request $request
  171.      * @return void
  172.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  173.      */
  174.     public function listAction(Request $request)
  175.     {
  176.         $action $request->get('action');
  177.         if ($action !== 'list' && method_exists($this$action 'Action')) {
  178.             $methodName $action 'Action';
  179.             return $this->$methodName($request);
  180.         }
  181.         //if this is not set - cart language is null
  182.         $this->document->setProperty("language""text"$request->get("language"));
  183.         //logic to decide which tenant is to be used, tenanst are configured in src/CoreBundle/Resources/config/pimcore/ecommerce.yml
  184.         if (Site::isSiteRequest()) {
  185.             $bundleName Site::getCurrentSite()->getRootDocument()->getModule() ?: "";
  186.             $environment Factory::getInstance()->getEnvironment();
  187.             if ($environment->getCurrentCheckoutTenant() != $bundleName) {
  188.                 $environment->setCurrentCheckoutTenant($bundleName);
  189.                 $environment->save();
  190.             }
  191.         }
  192.         $cart $this->getCart();
  193.         /** @var CartProductStockChecker $cartProductStockChecker */
  194.         $cartProductStockChecker $this->get('core.cart_product_stock_checker');
  195.         $messages $cartProductStockChecker->checkStockOfProductinCart($cart);
  196.         if (count($messages) > 0) {
  197.             foreach ($messages as $message) {
  198.                 $this->addFlash('error'$message);
  199.             }
  200.         }
  201.         $checkoutManager Factory::getInstance()->getCheckoutManager($cart);
  202.         if ($cart->getItemCount() > 0) {
  203.             // Set cart order state to null because if it's in paymentPending it locks into read only mode
  204.             if ($checkoutManager->getOrder()->getOrderState()) {
  205.                 $checkoutManager->getOrder()->setOrderState(null);
  206.             }
  207.         }
  208.         $siteId null;
  209.         if (\Pimcore\Model\Site::isSiteRequest()) {
  210.             $site = \Pimcore\Model\Site::getCurrentSite();
  211.             $siteId $site->getId();
  212.         }
  213.         // FreeGift pricing Rule
  214.         $freeGiftCartAmount null;
  215.         $setting WebsiteSetting::getByName('freeGiftPricingRuleName'$siteId);
  216.         if ($setting instanceof WebsiteSetting) {
  217.             $freeGiftPricingRuleName $setting->getData();
  218.             $db DB::get();
  219.             $data $db->fetchOne("SELECT `condition` FROM ecommerceframework_pricing_rule WHERE `name` = ? AND `active` = 1 LIMIT 1", [$freeGiftPricingRuleName]);
  220.             if ($data) {
  221.                 $obj unserialize($data);
  222.                 if ($obj instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Bracket){
  223.                     $cartAmount $obj->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
  224.                     if (isset($cartAmount[0])) {
  225.                         $freeGiftCartAmount $cartAmount[0]->getLimit();
  226.                     }
  227.                 }
  228.             }
  229.         }
  230.         // Get free shipping limit
  231.         $freeShippingLimit null;
  232.         $amountUntilFreeDelivery $freeShippingLimit;
  233.         $listing = new \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Rule\Listing();
  234.         $listing->addConditionParam("name LIKE '%Versandkostenfrei_ab_Warenkorbwert' AND active = 1");
  235.         $allPricingRules $listing->load();
  236.         foreach ($allPricingRules as $rule) {
  237.             $conditionsByTenant $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Tenant');
  238.             if (isset($conditionsByTenant[0])) {
  239.                 $tenants $conditionsByTenant[0]->getTenant();
  240.                 if (isset($tenants[0]) && $bundleName === $tenants[0]) {
  241.                     $actions $rule->getActions();
  242.                     foreach ($actions as $action) {
  243.                         if ($action instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Action\FreeShipping) {
  244.                             $conditionsByCartAmount $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
  245.                             if (isset($conditionsByCartAmount[0])) {
  246.                                 $freeShippingLimit = (float)$conditionsByCartAmount[0]->getLimit();
  247.                             }
  248.                         }
  249.                     }
  250.                 }
  251.             }
  252.         }
  253.         $calculator $cart->getPriceCalculator();
  254.         $subTotal $calculator->getSubTotal();
  255.         $cartSubTotal $subTotal->getGrossAmount()->asNumeric();
  256.         if ($freeShippingLimit) {
  257.             $amountUntilFreeDelivery $freeShippingLimit $cartSubTotal;
  258.         }
  259.         $amountUntilFreeGift null;
  260.         if ($freeGiftCartAmount !== null && $freeGiftCartAmount 0) {
  261.             $amountUntilFreeGift $freeGiftCartAmount $cartSubTotal;
  262.         }
  263.         $this->view->amountUntilFreeDelivery $amountUntilFreeDelivery;
  264.         $this->view->freeShippingLimit $freeShippingLimit;
  265.         $this->view->amountUntilFreeGift $amountUntilFreeGift;
  266.         $this->view->cart $cart;
  267.         $this->view->brandCode $this->document->getProperty('brandCode');
  268.     }
  269.     /**
  270.      * @param Request $request
  271.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  272.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  273.      */
  274.     public function addAction(Request $request)
  275.     {
  276.         $res true;
  277.         $flashMessage '';
  278.         $closeSidebarCart 0;
  279.         $sidebarCartEnabled false;
  280.         if (in_array(self::WEBSITE_FEATURE_SIDEBAR_CART$this->enabledWebsiteFeatures)) {
  281.             $sidebarCartEnabled true;
  282.             $setting WebsiteSetting::getByName('autoCloseSidebarCart');
  283.             if ($setting instanceof WebsiteSetting) {
  284.                 $closeSidebarCart = (int)$setting->getData(); // Stored as seconds
  285.             }
  286.         }
  287.         $product CoreBundleHelper::getProductByArticleNumber($request->get('article'), $this);
  288.         $quantity $request->get('quantity'1);
  289.         $currentQuantity 0;
  290.         $cart $this->getCart();
  291.         $currentItem $cart->getItem($product->getId());
  292.         if ($currentItem) {
  293.             $currentQuantity $currentItem->getCount();
  294.         }
  295.         if (!is_numeric($quantity)) {
  296.             $quantity 1;
  297.         }
  298.         $exceeded $this->isMaximumOrderableQuantityPerOrder($currentQuantity$product$quantity);
  299.         if ($exceeded) {
  300.             $res false;
  301.             $flashMessage $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
  302.             if (!$sidebarCartEnabled) {
  303.                 $this->addFlash('error'$flashMessage);
  304.                 return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
  305.                     'articlenumber' => $product->getArticleNumber(),
  306.                     'name' => $product->getUrlTitle(),
  307.                 ]));
  308.             }
  309.         } else {
  310.             // Set cart order state to null because if it's in paymentPending it locks into read only mode
  311.             $checkoutManager Factory::getInstance()->getCheckoutManager($cart);
  312.             if ($checkoutManager->getOrder()->getOrderState())
  313.                 $checkoutManager->getOrder()->setOrderState(null);
  314.             $articlenumber $request->get('article');
  315.             //error cases, not enough product in stock
  316.             if ($quantity $product->getStock()) {
  317.                 $res false;
  318.                 $flashMessage $this->get("translator")->trans("outOfStockP1") . $quantity $this->get("translator")->trans("outOfStockP2") . $product->getStock() . $this->get("translator")->trans("outOfStockP3");
  319.                 if (!$sidebarCartEnabled) {
  320.                     $this->addFlash('error'$flashMessage);
  321.                     return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
  322.                         'articlenumber' => $articlenumber,
  323.                         'name' => $product->getUrlTitle(),
  324.                     ]));
  325.                 }
  326.             } //error case, negative number ordered
  327.             elseif ($quantity 0) {
  328.                 $res false;
  329.                 $flashMessage $this->get("translator")->trans("noNegativeValuesAllowed");
  330.                 if (!$sidebarCartEnabled) {
  331.                     $this->addFlash('error'$flashMessage);
  332.                     return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
  333.                         'articlenumber' => $articlenumber,
  334.                         'name' => $product->getUrlTitle(),
  335.                     ]));
  336.                 }
  337.             } else {
  338.                 $res true;
  339.                 $cart->addItem($product$quantity);
  340.                 $cart->save();
  341.             }
  342.         }
  343.         if ($sidebarCartEnabled) {
  344.             return $this->json(['id' => $product->getId(), 'res' => $res'message' => $flashMessage'closeSidebarCart' => $closeSidebarCart]);
  345.         }
  346.         return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
  347.     }
  348.     /**
  349.      * @param Request $request
  350.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  351.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  352.      */
  353.     public function removeAction(Request $request)
  354.     {
  355.         $cid $request->get("cid");
  356.         if ($cid) {
  357.             $checkoutManager Factory::getInstance()->getCheckoutManager($this->getCart());
  358.             // Set cart order state to null because if it's in paymentPending it locks into read only mode
  359.             if ($checkoutManager->getOrder()->getOrderState())
  360.                 $checkoutManager->getOrder()->setOrderState(null);
  361.             $cart $this->getCart();
  362.             $cart->removeItem($cid);
  363.             $cart->save();
  364.         }
  365.         return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
  366.     }
  367.     /**
  368.      * @param Request $request
  369.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  370.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  371.      */
  372.     public function updateAction(Request $request)
  373.     {
  374.         $quantities $request->get("quantities");
  375.         if ($quantities) {
  376.             $cart $this->getCart();
  377.             $checkoutManager Factory::getInstance()->getCheckoutManager($cart);
  378.             // Set cart order state to null because if it's in paymentPending it locks into read only mode
  379.             if ($checkoutManager->getOrder()->getOrderState())
  380.                 $checkoutManager->getOrder()->setOrderState(null);
  381.             $cartItems $cart->getItems();
  382.             foreach ($cartItems as $cartItem) {
  383.                 $itemKey $cartItem->getItemKey();
  384.                 //stock handling
  385.                 $amount $cartItem->getCount();
  386.                 $product $cartItem->getProduct();
  387.                 $stock $product->getStock() - $quantities[$itemKey];
  388.                 if ($stock >= 0) {
  389.                     if ($quantities[$itemKey] > 0) {
  390.                         $exceeded $this->isMaximumOrderableQuantityPerOrder(0$product$quantities[$itemKey]);
  391.                         if ($exceeded) {
  392.                             $this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
  393.                             continue;
  394.                         }
  395.                         $cart->updateItemCount($itemKey$quantities[$itemKey]);
  396.                     } else {
  397.                         $cart->removeItem($itemKey);
  398.                     }
  399.                 } else {
  400.                     $exceeded $this->isMaximumOrderableQuantityPerOrder(0$product$quantities[$itemKey]);
  401.                     if ($exceeded) {
  402.                         $this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
  403.                         continue;
  404.                     }
  405.                     $stock $product->getStock() + $amount;
  406.                     $this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("outOfStockP1") . $quantities[$itemKey] . $this->get("translator")->trans("outOfStockP2") . $stock $this->get("translator")->trans("outOfStockP3")]);
  407.                 }
  408.             }
  409.             $cart->save();
  410.         }
  411.         return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
  412.     }
  413.     /**
  414.      * @param Request $request
  415.      * @param LoggerInterface $logger
  416.      * @return Response|null
  417.      */
  418.     public function ajaxCheckStockInCartAction(Request $requestLoggerInterface $logger): ?Response
  419.     {
  420.         $cart $this->getCart();
  421.         if ($request->isXmlHttpRequest()) {
  422.             /** @var CartProductStockChecker $cartProductStockChecker */
  423.             $cartProductStockChecker $this->get('core.cart_product_stock_checker');
  424.             $messages $cartProductStockChecker->checkStockOfProductinCart($cartfalse);
  425.             if (count($messages) > 0) {
  426.                 foreach ($messages as $message) {
  427.                     $this->addFlash('error'$message);
  428.                 }
  429.                 return new Response($message[0]["message"], Response::HTTP_BAD_REQUEST);
  430.             }
  431.             return new Response('Ok'Response::HTTP_OK);
  432.         }
  433.         return new Response('Something goes wrong!'500);
  434.     }
  435.     protected function isMaximumOrderableQuantityPerOrder($currentQuantity$product$quantity)
  436.     {
  437.         if (!is_numeric($quantity)) {
  438.             $quantity 1;
  439.         }
  440.         /**
  441.          * @var DefaultProductFood $product
  442.          */
  443.         $maximumOrderableQuantityPerOrder $product->getMaximumOrderableQuantityPerOrder();
  444.         if (!empty($maximumOrderableQuantityPerOrder) && is_numeric($maximumOrderableQuantityPerOrder)) {
  445.             if (($quantity $currentQuantity) > $maximumOrderableQuantityPerOrder) {
  446.                 return true;
  447.             }
  448.         }
  449.         return false;
  450.     }
  451. }