<?php
namespace CoreBundle\Controller;
use CoreBundle\{Helper\CoreBundleHelper,
Helper\ProductHelper,
Model\DefaultProductFood,
Services\CartProductStockChecker,
TagManager\Models\Product
};
use Pimcore\Db;
use Pimcore\Model\DataObject;
use Pimcore\Model\WebsiteSetting;
use Psr\Log\LoggerInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Model\Site;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class CartController extends AbstractController
{
/**+
* @param Request $request
* @return Response
* @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
*/
public function infoAction(Request $request): Response
{
$cart = $this->getCart();
$message = '';
$productId = $request->get('productId');
$newAmount = $request->get('newAmount');
if (Site::isSiteRequest()) {
$bundleName = Site::getCurrentSite()->getRootDocument()->getModule() ?: "";
if ($bundleName == 'MautnerFoodserviceBundle') {
$bundleName = 'MautnerBundle';
}
$environment = Factory::getInstance()->getEnvironment();
if ($environment->getCurrentCheckoutTenant() != $bundleName) {
$environment->setCurrentCheckoutTenant($bundleName);
$environment->save();
}
}
if ($productId !== null && $newAmount !== null) {
// TODO: remove or change amount
$quantity = (int)$newAmount;
if ($quantity > 0) {
$checkoutManager = Factory::getInstance()->getCheckoutManager($cart);
// Set cart order state to null because if it's in paymentPending it locks into read only mode
if ($checkoutManager->getOrder()->getOrderState())
$checkoutManager->getOrder()->setOrderState(null);
$cartItems = $cart->getItems();
foreach ($cartItems as $cartItem) {
$itemKey = $cartItem->getItemKey();
//stock handling
$amount = $cartItem->getCount();
$product = $cartItem->getProduct();
if ($itemKey == $productId) {
$stock = $product->getStock() - $quantity;
if ($stock >= 0) {
if ($quantity > 0) {
$exceeded = $this->isMaximumOrderableQuantityPerOrder(0, $product, $quantity);
if ($exceeded) {
$message = $product->getOSName() . ': ' . $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
$this->addFlash('error', ['id' => $product->getId(), 'message' => $message]);
break;
}
$cart->updateItemCount($itemKey, $quantity);
}
} else {
$exceeded = $this->isMaximumOrderableQuantityPerOrder(0, $product, $quantity);
if ($exceeded) {
$message = $product->getOSName() . ': ' . $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
$this->addFlash('error', ['id' => $itemKey, 'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
break;
}
$stock = $product->getStock();
$message = $this->get("translator")->trans("outOfStockP1") . $quantity . $this->get("translator")->trans("outOfStockP2") . $stock . $this->get("translator")->trans("outOfStockP3");
$this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("outOfStockP1") . $quantity . $this->get("translator")->trans("outOfStockP2") . $stock . $this->get("translator")->trans("outOfStockP3")]);
}
}
}
$cart->save();
} else {
$cart->removeItem($productId);
$cart->save();
}
}
/** @var CartProductStockChecker $cartProductStockChecker */
$cartProductStockChecker = $this->get('core.cart_product_stock_checker');
$messages = $cartProductStockChecker->checkStockOfProductinCart($cart);
if (count($messages) > 0) {
foreach ($messages as $message) {
$this->addFlash('error', $message);
}
}
$checkoutManager = Factory::getInstance()->getCheckoutManager($cart);
if ($cart->getItemCount() > 0) {
// Set cart order state to null because if it's in paymentPending it locks into read only mode
if ($checkoutManager->getOrder()->getOrderState()) {
$checkoutManager->getOrder()->setOrderState(null);
}
}
$siteId = null;
if (\Pimcore\Model\Site::isSiteRequest()) {
$site = \Pimcore\Model\Site::getCurrentSite();
$siteId = $site->getId();
}
// FreeGift pricing Rule
$freeGiftCartAmount = null;
$setting = WebsiteSetting::getByName('freeGiftPricingRuleName', $siteId);
if ($setting instanceof WebsiteSetting) {
$freeGiftPricingRuleName = $setting->getData();
$db = DB::get();
$data = $db->fetchOne("SELECT `condition` FROM ecommerceframework_pricing_rule WHERE `name` = ? AND `active` = 1 LIMIT 1", [$freeGiftPricingRuleName]);
if ($data) {
$obj = unserialize($data);
if ($obj instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Bracket){
$cartAmount = $obj->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
if (isset($cartAmount[0])) {
$freeGiftCartAmount = $cartAmount[0]->getLimit();
}
}
}
}
// Get free shipping limit
$freeShippingLimit = null;
$amountUntilFreeDelivery = $freeShippingLimit;
$listing = new \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Rule\Listing();
$listing->addConditionParam("name LIKE '%Versandkostenfrei_ab_Warenkorbwert' AND active = 1");
$allPricingRules = $listing->load();
foreach ($allPricingRules as $rule) {
$conditionsByTenant = $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Tenant');
if (isset($conditionsByTenant[0])) {
$tenants = $conditionsByTenant[0]->getTenant();
if (isset($tenants[0]) && $bundleName === $tenants[0]) {
$actions = $rule->getActions();
foreach ($actions as $action) {
if ($action instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Action\FreeShipping) {
$conditionsByCartAmount = $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
if (isset($conditionsByCartAmount[0])) {
$freeShippingLimit = (float)$conditionsByCartAmount[0]->getLimit();
}
}
}
}
}
}
$calculator = $cart->getPriceCalculator();
$subTotal = $calculator->getSubTotal();
$cartSubTotal = $subTotal->getGrossAmount()->asNumeric();
if ($freeShippingLimit) {
$amountUntilFreeDelivery = $freeShippingLimit - $cartSubTotal;
}
$amountUntilFreeGift = null;
if ($freeGiftCartAmount !== null && $freeGiftCartAmount > 0) {
$amountUntilFreeGift = $freeGiftCartAmount - $cartSubTotal;
}
$params = [
'message' => $message,
'cart' => $cart,
'freeShippingLimit' => $freeShippingLimit,
'amountUntilFreeDelivery' => $amountUntilFreeDelivery,
'amountUntilFreeGift' => $amountUntilFreeGift,
'cartSubTotal' => $cartSubTotal,
'calculator' => $calculator,
'bundleName' => $bundleName,
];
return $this->render('Cart/sidebar.html.twig', $params);
}
/**
* @param Request $request
* @return void
* @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
*/
public function listAction(Request $request)
{
$action = $request->get('action');
if ($action !== 'list' && method_exists($this, $action . 'Action')) {
$methodName = $action . 'Action';
return $this->$methodName($request);
}
//if this is not set - cart language is null
$this->document->setProperty("language", "text", $request->get("language"));
//logic to decide which tenant is to be used, tenanst are configured in src/CoreBundle/Resources/config/pimcore/ecommerce.yml
if (Site::isSiteRequest()) {
$bundleName = Site::getCurrentSite()->getRootDocument()->getModule() ?: "";
$environment = Factory::getInstance()->getEnvironment();
if ($environment->getCurrentCheckoutTenant() != $bundleName) {
$environment->setCurrentCheckoutTenant($bundleName);
$environment->save();
}
}
$cart = $this->getCart();
/** @var CartProductStockChecker $cartProductStockChecker */
$cartProductStockChecker = $this->get('core.cart_product_stock_checker');
$messages = $cartProductStockChecker->checkStockOfProductinCart($cart);
if (count($messages) > 0) {
foreach ($messages as $message) {
$this->addFlash('error', $message);
}
}
$checkoutManager = Factory::getInstance()->getCheckoutManager($cart);
if ($cart->getItemCount() > 0) {
// Set cart order state to null because if it's in paymentPending it locks into read only mode
if ($checkoutManager->getOrder()->getOrderState()) {
$checkoutManager->getOrder()->setOrderState(null);
}
}
$siteId = null;
if (\Pimcore\Model\Site::isSiteRequest()) {
$site = \Pimcore\Model\Site::getCurrentSite();
$siteId = $site->getId();
}
// FreeGift pricing Rule
$freeGiftCartAmount = null;
$setting = WebsiteSetting::getByName('freeGiftPricingRuleName', $siteId);
if ($setting instanceof WebsiteSetting) {
$freeGiftPricingRuleName = $setting->getData();
$db = DB::get();
$data = $db->fetchOne("SELECT `condition` FROM ecommerceframework_pricing_rule WHERE `name` = ? AND `active` = 1 LIMIT 1", [$freeGiftPricingRuleName]);
if ($data) {
$obj = unserialize($data);
if ($obj instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Bracket){
$cartAmount = $obj->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
if (isset($cartAmount[0])) {
$freeGiftCartAmount = $cartAmount[0]->getLimit();
}
}
}
}
// Get free shipping limit
$freeShippingLimit = null;
$amountUntilFreeDelivery = $freeShippingLimit;
$listing = new \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Rule\Listing();
$listing->addConditionParam("name LIKE '%Versandkostenfrei_ab_Warenkorbwert' AND active = 1");
$allPricingRules = $listing->load();
foreach ($allPricingRules as $rule) {
$conditionsByTenant = $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\Tenant');
if (isset($conditionsByTenant[0])) {
$tenants = $conditionsByTenant[0]->getTenant();
if (isset($tenants[0]) && $bundleName === $tenants[0]) {
$actions = $rule->getActions();
foreach ($actions as $action) {
if ($action instanceof \Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Action\FreeShipping) {
$conditionsByCartAmount = $rule->getConditionsByType('\Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\Condition\CartAmount');
if (isset($conditionsByCartAmount[0])) {
$freeShippingLimit = (float)$conditionsByCartAmount[0]->getLimit();
}
}
}
}
}
}
$calculator = $cart->getPriceCalculator();
$subTotal = $calculator->getSubTotal();
$cartSubTotal = $subTotal->getGrossAmount()->asNumeric();
if ($freeShippingLimit) {
$amountUntilFreeDelivery = $freeShippingLimit - $cartSubTotal;
}
$amountUntilFreeGift = null;
if ($freeGiftCartAmount !== null && $freeGiftCartAmount > 0) {
$amountUntilFreeGift = $freeGiftCartAmount - $cartSubTotal;
}
$this->view->amountUntilFreeDelivery = $amountUntilFreeDelivery;
$this->view->freeShippingLimit = $freeShippingLimit;
$this->view->amountUntilFreeGift = $amountUntilFreeGift;
$this->view->cart = $cart;
$this->view->brandCode = $this->document->getProperty('brandCode');
}
/**
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
*/
public function addAction(Request $request)
{
$res = true;
$flashMessage = '';
$closeSidebarCart = 0;
$sidebarCartEnabled = false;
if (in_array(self::WEBSITE_FEATURE_SIDEBAR_CART, $this->enabledWebsiteFeatures)) {
$sidebarCartEnabled = true;
$setting = WebsiteSetting::getByName('autoCloseSidebarCart');
if ($setting instanceof WebsiteSetting) {
$closeSidebarCart = (int)$setting->getData(); // Stored as seconds
}
}
$product = CoreBundleHelper::getProductByArticleNumber($request->get('article'), $this);
$quantity = $request->get('quantity', 1);
$currentQuantity = 0;
$cart = $this->getCart();
$currentItem = $cart->getItem($product->getId());
if ($currentItem) {
$currentQuantity = $currentItem->getCount();
}
if (!is_numeric($quantity)) {
$quantity = 1;
}
$exceeded = $this->isMaximumOrderableQuantityPerOrder($currentQuantity, $product, $quantity);
if ($exceeded) {
$res = false;
$flashMessage = $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()]);
if (!$sidebarCartEnabled) {
$this->addFlash('error', $flashMessage);
return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
'articlenumber' => $product->getArticleNumber(),
'name' => $product->getUrlTitle(),
]));
}
} else {
// Set cart order state to null because if it's in paymentPending it locks into read only mode
$checkoutManager = Factory::getInstance()->getCheckoutManager($cart);
if ($checkoutManager->getOrder()->getOrderState())
$checkoutManager->getOrder()->setOrderState(null);
$articlenumber = $request->get('article');
//error cases, not enough product in stock
if ($quantity > $product->getStock()) {
$res = false;
$flashMessage = $this->get("translator")->trans("outOfStockP1") . $quantity . $this->get("translator")->trans("outOfStockP2") . $product->getStock() . $this->get("translator")->trans("outOfStockP3");
if (!$sidebarCartEnabled) {
$this->addFlash('error', $flashMessage);
return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
'articlenumber' => $articlenumber,
'name' => $product->getUrlTitle(),
]));
}
} //error case, negative number ordered
elseif ($quantity < 0) {
$res = false;
$flashMessage = $this->get("translator")->trans("noNegativeValuesAllowed");
if (!$sidebarCartEnabled) {
$this->addFlash('error', $flashMessage);
return $this->redirect($this->generateUrl('shopHandlerProductDetail', [
'articlenumber' => $articlenumber,
'name' => $product->getUrlTitle(),
]));
}
} else {
$res = true;
$cart->addItem($product, $quantity);
$cart->save();
}
}
if ($sidebarCartEnabled) {
return $this->json(['id' => $product->getId(), 'res' => $res, 'message' => $flashMessage, 'closeSidebarCart' => $closeSidebarCart]);
}
return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
}
/**
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
*/
public function removeAction(Request $request)
{
$cid = $request->get("cid");
if ($cid) {
$checkoutManager = Factory::getInstance()->getCheckoutManager($this->getCart());
// Set cart order state to null because if it's in paymentPending it locks into read only mode
if ($checkoutManager->getOrder()->getOrderState())
$checkoutManager->getOrder()->setOrderState(null);
$cart = $this->getCart();
$cart->removeItem($cid);
$cart->save();
}
return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
}
/**
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
*/
public function updateAction(Request $request)
{
$quantities = $request->get("quantities");
if ($quantities) {
$cart = $this->getCart();
$checkoutManager = Factory::getInstance()->getCheckoutManager($cart);
// Set cart order state to null because if it's in paymentPending it locks into read only mode
if ($checkoutManager->getOrder()->getOrderState())
$checkoutManager->getOrder()->setOrderState(null);
$cartItems = $cart->getItems();
foreach ($cartItems as $cartItem) {
$itemKey = $cartItem->getItemKey();
//stock handling
$amount = $cartItem->getCount();
$product = $cartItem->getProduct();
$stock = $product->getStock() - $quantities[$itemKey];
if ($stock >= 0) {
if ($quantities[$itemKey] > 0) {
$exceeded = $this->isMaximumOrderableQuantityPerOrder(0, $product, $quantities[$itemKey]);
if ($exceeded) {
$this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
continue;
}
$cart->updateItemCount($itemKey, $quantities[$itemKey]);
} else {
$cart->removeItem($itemKey);
}
} else {
$exceeded = $this->isMaximumOrderableQuantityPerOrder(0, $product, $quantities[$itemKey]);
if ($exceeded) {
$this->addFlash('error', ['id' => $product->getId(), 'message' => $this->get("translator")->trans("maximumOrderableQuantityPerOrderExceeded", [$product->getMaximumOrderableQuantityPerOrder()])]);
continue;
}
$stock = $product->getStock() + $amount;
$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")]);
}
}
$cart->save();
}
return $this->redirect($this->generateUrl('shopHandlerCart', ['action' => 'list']));
}
/**
* @param Request $request
* @param LoggerInterface $logger
* @return Response|null
*/
public function ajaxCheckStockInCartAction(Request $request, LoggerInterface $logger): ?Response
{
$cart = $this->getCart();
if ($request->isXmlHttpRequest()) {
/** @var CartProductStockChecker $cartProductStockChecker */
$cartProductStockChecker = $this->get('core.cart_product_stock_checker');
$messages = $cartProductStockChecker->checkStockOfProductinCart($cart, false);
if (count($messages) > 0) {
foreach ($messages as $message) {
$this->addFlash('error', $message);
}
return new Response($message[0]["message"], Response::HTTP_BAD_REQUEST);
}
return new Response('Ok', Response::HTTP_OK);
}
return new Response('Something goes wrong!', 500);
}
protected function isMaximumOrderableQuantityPerOrder($currentQuantity, $product, $quantity)
{
if (!is_numeric($quantity)) {
$quantity = 1;
}
/**
* @var DefaultProductFood $product
*/
$maximumOrderableQuantityPerOrder = $product->getMaximumOrderableQuantityPerOrder();
if (!empty($maximumOrderableQuantityPerOrder) && is_numeric($maximumOrderableQuantityPerOrder)) {
if (($quantity + $currentQuantity) > $maximumOrderableQuantityPerOrder) {
return true;
}
}
return false;
}
}