src/Eccube/Controller/CartController.php line 119

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Controller;
  13. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  14. use Eccube\Entity\BaseInfo;
  15. use Eccube\Entity\ProductClass;
  16. use Eccube\Event\EccubeEvents;
  17. use Eccube\Event\EventArgs;
  18. use Eccube\Repository\BaseInfoRepository;
  19. use Eccube\Repository\ProductClassRepository;
  20. use Eccube\Service\CartService;
  21. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  22. use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
  23. use Eccube\Controller\AbstractController;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. use Symfony\Component\HttpFoundation\RedirectResponse;
  27. use Eccube\Service\PurchaseFlow\PurchaseContext;
  28. use Eccube\Service\OrderHelper;
  29. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  30. class CartController extends AbstractController
  31. {
  32.     protected $productClassRepository;
  33.     protected $eventDispatcher;
  34.     protected $cartService;
  35.     protected $purchaseFlow;
  36.     protected $baseInfo;
  37.     /**
  38.      * CartController constructor.
  39.      *
  40.      * @param ProductClassRepository $productClassRepository
  41.      * @param EventDispatcherInterface $eventDispatcher
  42.      * @param CartService $cartService
  43.      * @param PurchaseFlow $cartPurchaseFlow
  44.      * @param BaseInfoRepository $baseInfoRepository
  45.      */
  46.     public function __construct(
  47.         ProductClassRepository $productClassRepository,
  48.         EventDispatcherInterface $eventDispatcher,
  49.         CartService $cartService,
  50.         PurchaseFlow $cartPurchaseFlow,
  51.         BaseInfoRepository $baseInfoRepository
  52.     ) {
  53.         $this->productClassRepository $productClassRepository;
  54.         $this->eventDispatcher $eventDispatcher;
  55.         $this->cartService $cartService;
  56.         $this->purchaseFlow $cartPurchaseFlow;
  57.         $this->baseInfo $baseInfoRepository->get();
  58.     }
  59.     /**
  60.      * カート画面.
  61.      *
  62.      * @Route("/cart", name="cart", methods={"GET"})
  63.      * @Template("Cart/index.twig")
  64.      */
  65.     public function index(Request $request)
  66.     {
  67.         // カートを取得して明細の正規化を実行
  68.         $Carts $this->cartService->getCarts();
  69.         $this->execPurchaseFlow($Carts);
  70.         // TODO itemHolderから取得できるように
  71.         $least = [];
  72.         $quantity = [];
  73.         $isDeliveryFree = [];
  74.         $totalPrice 0;
  75.         $totalQuantity 0;
  76.         foreach ($Carts as $Cart) {
  77.             // カスタマイズここから
  78.             if ($request->query->get('buystep')) {
  79.                 return $this->buystep($request$Cart->getCartKey());
  80.             }
  81.             // カスタマイズここまで
  82.             $quantity[$Cart->getCartKey()] = 0;
  83.             $isDeliveryFree[$Cart->getCartKey()] = false;
  84.             if ($this->baseInfo->getDeliveryFreeQuantity()) {
  85.                 if ($this->baseInfo->getDeliveryFreeQuantity() > $Cart->getQuantity()) {
  86.                     $quantity[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeQuantity() - $Cart->getQuantity();
  87.                 } else {
  88.                     $isDeliveryFree[$Cart->getCartKey()] = true;
  89.                 }
  90.             }
  91.             if ($this->baseInfo->getDeliveryFreeAmount()) {
  92.                 if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $Cart->getTotalPrice()) {
  93.                     $isDeliveryFree[$Cart->getCartKey()] = true;
  94.                 } else {
  95.                     $least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $Cart->getTotalPrice();
  96.                 }
  97.             }
  98.             $totalPrice += $Cart->getTotalPrice();
  99.             $totalQuantity += $Cart->getQuantity();
  100.         }
  101.         // カートが分割された時のセッション情報を削除
  102.         $request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
  103.         return [
  104.             'totalPrice' => $totalPrice,
  105.             'totalQuantity' => $totalQuantity,
  106.             // 空のカートを削除し取得し直す
  107.             'Carts' => $this->cartService->getCarts(true),
  108.             'least' => $least,
  109.             'quantity' => $quantity,
  110.             'is_delivery_free' => $isDeliveryFree,
  111.         ];
  112.     }
  113.     /**
  114.      * @param $Carts
  115.      *
  116.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|null
  117.      */
  118.     protected function execPurchaseFlow($Carts)
  119.     {
  120.         /** @var PurchaseFlowResult[] $flowResults */
  121.         $flowResults array_map(function ($Cart) {
  122.             $purchaseContext = new PurchaseContext($Cart$this->getUser());
  123.             return $this->purchaseFlow->validate($Cart$purchaseContext);
  124.         }, $Carts);
  125.         // 復旧不可のエラーが発生した場合はカートをクリアして再描画
  126.         $hasError false;
  127.         foreach ($flowResults as $result) {
  128.             if ($result->hasError()) {
  129.                 $hasError true;
  130.                 foreach ($result->getErrors() as $error) {
  131.                     $this->addRequestError($error->getMessage());
  132.                 }
  133.             }
  134.         }
  135.         if ($hasError) {
  136.             $this->cartService->clear();
  137.             return $this->redirectToRoute('cart');
  138.         }
  139.         $this->cartService->save();
  140.         foreach ($flowResults as $index => $result) {
  141.             foreach ($result->getWarning() as $warning) {
  142.                 if ($Carts[$index]->getItems()->count() > 0) {
  143.                     $cart_key $Carts[$index]->getCartKey();
  144.                     $this->addRequestError($warning->getMessage(), "front.cart.${cart_key}");
  145.                 } else {
  146.                     // キーが存在しない場合はグローバルにエラーを表示する
  147.                     $this->addRequestError($warning->getMessage());
  148.                 }
  149.             }
  150.         }
  151.         return null;
  152.     }
  153.     /**
  154.      * カート明細の加算/減算/削除を行う.
  155.      *
  156.      * - 加算
  157.      *      - 明細の個数を1増やす
  158.      * - 減算
  159.      *      - 明細の個数を1減らす
  160.      *      - 個数が0になる場合は、明細を削除する
  161.      * - 削除
  162.      *      - 明細を削除する
  163.      *
  164.      * @Route(
  165.      *     path="/cart/{operation}/{productClassId}",
  166.      *     name="cart_handle_item",
  167.      *     methods={"PUT"},
  168.      *     requirements={
  169.      *          "operation": "up|down|remove",
  170.      *          "productClassId": "\d+"
  171.      *     }
  172.      * )
  173.      */
  174.     public function handleCartItem($operation$productClassId)
  175.     {
  176.         log_info('カート明細操作開始', ['operation' => $operation'product_class_id' => $productClassId]);
  177.         $this->isTokenValid();
  178.         /** @var ProductClass $ProductClass */
  179.         $ProductClass $this->productClassRepository->find($productClassId);
  180.         if (is_null($ProductClass)) {
  181.             log_info('商品が存在しないため、カート画面へredirect', ['operation' => $operation'product_class_id' => $productClassId]);
  182.             return $this->redirectToRoute('cart');
  183.         }
  184.         // 明細の増減・削除
  185.         switch ($operation) {
  186.             case 'up':
  187.                 $this->cartService->addProduct($ProductClass1);
  188.                 break;
  189.             case 'down':
  190.                 $this->cartService->addProduct($ProductClass, -1);
  191.                 break;
  192.             case 'remove':
  193.                 $this->cartService->removeProduct($ProductClass);
  194.                 break;
  195.         }
  196.         // カートを取得して明細の正規化を実行
  197.         $Carts $this->cartService->getCarts();
  198.         $this->execPurchaseFlow($Carts);
  199.         log_info('カート演算処理終了', ['operation' => $operation'product_class_id' => $productClassId]);
  200.         return $this->redirectToRoute('cart');
  201.     }
  202.     /**
  203.      * @Route("/cart/buystep", name="cart_buystep")
  204.      */
  205.     public function buystep(Request $request)
  206.     {
  207.         // FRONT_CART_BUYSTEP_INITIALIZE
  208.         $event = new EventArgs(
  209.             array(),
  210.             $request
  211.         );
  212.         // $this->get('event_dispatcher')->dispatch(EccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE, $event);
  213.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE);
  214.         // カートをロックして保存
  215.         $this->cartService->lock();
  216.         $this->cartService->save();
  217.         // FRONT_CART_BUYSTEP_COMPLETE
  218.         $event = new EventArgs(
  219.             array(),
  220.             $request
  221.         );
  222.         // $this->get('event_dispatcher')->dispatch(EccubeEvents::FRONT_CART_BUYSTEP_COMPLETE, $event);
  223.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_CART_BUYSTEP_COMPLETE);
  224.         if ($event->hasResponse()) {
  225.             return $event->getResponse();
  226.         }
  227.         // ショッピングページへのリダイレクト
  228.         return $this->redirectToRoute('shopping_nonmember');
  229.     }
  230. }