app/Customize/Controller/CartController.php line 76

Open in your IDE?
  1. <?php
  2. namespace Customize\Controller;
  3. use Eccube\Controller\AbstractController;
  4. use Eccube\Entity\BaseInfo;
  5. use Eccube\Entity\ProductClass;
  6. use Eccube\Event\EccubeEvents;
  7. use Eccube\Event\EventArgs;
  8. use Eccube\Repository\BaseInfoRepository;
  9. use Eccube\Repository\ProductClassRepository;
  10. use Eccube\Service\CartService;
  11. use Eccube\Service\OrderHelper;
  12. use Eccube\Service\PurchaseFlow\PurchaseContext;
  13. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  14. use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
  15. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. use Customize\Common\Constants;
  19. use Eccube\Common\EccubeConfig;
  20. class CartController extends AbstractController
  21. {
  22.     /**
  23.      * @var ProductClassRepository
  24.      */
  25.     protected $productClassRepository;
  26.     /**
  27.      * @var CartService
  28.      */
  29.     protected $cartService;
  30.     /**
  31.      * @var PurchaseFlow
  32.      */
  33.     protected $purchaseFlow;
  34.     /**
  35.      * @var BaseInfo
  36.      */
  37.     protected $baseInfo;
  38.     private $setting;
  39.     /**
  40.      * CartController constructor.
  41.      *
  42.      * @param ProductClassRepository $productClassRepository
  43.      * @param CartService $cartService
  44.      * @param PurchaseFlow $cartPurchaseFlow
  45.      * @param BaseInfoRepository $baseInfoRepository
  46.      */
  47.     public function __construct(
  48.         ProductClassRepository $productClassRepository,
  49.         CartService $cartService,
  50.         PurchaseFlow $cartPurchaseFlow,
  51.         BaseInfoRepository $baseInfoRepository,
  52.         EccubeConfig $eccubeConfig,
  53.     ) {
  54.         $this->productClassRepository $productClassRepository;
  55.         $this->cartService $cartService;
  56.         $this->purchaseFlow $cartPurchaseFlow;
  57.         $this->baseInfo $baseInfoRepository->get();
  58.         $this->eccubeConfig $eccubeConfig;
  59.     }
  60.     /**
  61.      * カート画面.
  62.      *
  63.      * @Route("/cart", name="cart", methods={"GET"})
  64.      * @Template("Cart/index.twig")
  65.      */
  66.     public function index(Request $request)
  67.     {
  68.         $result $this->cartService->validateLocale($request$this->cartService->getCart());
  69.         
  70.         if($result['isPass'] == false){
  71.             return $this->redirectToRoute('cart_locale', [
  72.                 '_locale' => $result['locale']
  73.             ]);
  74.         }
  75.         
  76.         // カートを取得して明細の正規化を実行
  77.         $Carts $this->cartService->getCarts();
  78.         $this->execPurchaseFlow($Carts);
  79.         // TODO itemHolderから取得できるように
  80.         $least = [];
  81.         $quantity = [];
  82.         $isDeliveryFree = [];
  83.         $totalPrice 0;
  84.         $totalQuantity 0;
  85.         foreach ($Carts as $Cart) {
  86.             $quantity[$Cart->getCartKey()] = 0;
  87.             $isDeliveryFree[$Cart->getCartKey()] = false;
  88.             if ($this->baseInfo->getDeliveryFreeQuantity()) {
  89.                 if ($this->baseInfo->getDeliveryFreeQuantity() > $Cart->getQuantity()) {
  90.                     $quantity[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeQuantity() - $Cart->getQuantity();
  91.                 } else {
  92.                     $isDeliveryFree[$Cart->getCartKey()] = true;
  93.                 }
  94.             }
  95.             if ($this->baseInfo->getDeliveryFreeAmount()) {
  96.                 if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $Cart->getTotalPrice()) {
  97.                     $isDeliveryFree[$Cart->getCartKey()] = true;
  98.                 } else {
  99.                     $least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $Cart->getTotalPrice();
  100.                 }
  101.             }
  102.             $totalPrice += $Cart->getTotalPrice();
  103.             $totalQuantity += $Cart->getQuantity();
  104.         }
  105.         // カートが分割された時のセッション情報を削除
  106.         $request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
  107.         return [
  108.             'totalPrice' => $totalPrice,
  109.             'totalQuantity' => $totalQuantity,
  110.             // 空のカートを削除し取得し直す
  111.             'Carts' => $this->cartService->getCarts(true),
  112.             'Cart' => $this->cartService->getCart(),
  113.             'least' => $least,
  114.             'quantity' => $quantity,
  115.             'is_delivery_free' => $isDeliveryFree,
  116.         ];
  117.     }
  118.     /**
  119.      * カート画面.
  120.      *
  121.      * @Route("/{_locale}/cart", name="cart_locale", methods={"GET"})
  122.      * @Template("Cart/index.twig")
  123.      */
  124.     public function indexLocale(Request $request)
  125.     {
  126.         if($this->eccubeConfig['salon_domain'] == $_SERVER['SERVER_NAME']){
  127.             $this->redirectToRoute('homepage');
  128.         }
  129.         
  130.         $result $this->cartService->validateLocale($request$this->cartService->getCart());
  131.         if($result['isPass'] == false){
  132.             return $this->redirectToRoute('cart_locale', [
  133.                 '_locale' => $result['locale']
  134.             ]);
  135.         }
  136.         if($request->getLocale() == Constants::LOCALE_JAPAN){
  137.             return $this->redirectToRoute('cart');
  138.         }
  139.         return $this->index($request);
  140.     }
  141.     /**
  142.      * カート明細の加算/減算/削除を行う.
  143.      *
  144.      * - 加算
  145.      *      - 明細の個数を1増やす
  146.      * - 減算
  147.      *      - 明細の個数を1減らす
  148.      *      - 個数が0になる場合は、明細を削除する
  149.      * - 削除
  150.      *      - 明細を削除する
  151.      *
  152.      * @Route(
  153.      *     path="/cart/{operation}/{productClassId}",
  154.      *     name="cart_handle_item",
  155.      *     methods={"PUT"},
  156.      *     requirements={
  157.      *          "operation": "up|down|remove",
  158.      *          "productClassId": "\d+"
  159.      *     }
  160.      * )
  161.      */
  162.     public function handleCartItem($operation$productClassId)
  163.     {
  164.         log_info('カート明細操作開始', ['operation' => $operation'product_class_id' => $productClassId]);
  165.         $this->isTokenValid();
  166.         /** @var ProductClass $ProductClass */
  167.         $ProductClass $this->productClassRepository->find($productClassId);
  168.         if (is_null($ProductClass)) {
  169.             log_info('商品が存在しないため、カート画面へredirect', ['operation' => $operation'product_class_id' => $productClassId]);
  170.             if (isset($_SERVER['REQUEST_URI'])) {
  171.                 if (!strpos($_SERVER['REQUEST_URI'], Constants::LOCALE_JAPAN)) {
  172.                     return $this->redirectToRoute('cart_locale');
  173.                 };
  174.             }
  175.             return $this->redirectToRoute('cart');
  176.         }
  177.         // 明細の増減・削除
  178.         switch ($operation) {
  179.             case 'up':
  180.                 $this->cartService->addProduct($ProductClass1);
  181.                 break;
  182.             case 'down':
  183.                 $this->cartService->addProduct($ProductClass, -1);
  184.                 break;
  185.             case 'remove':
  186.                 $this->cartService->removeProduct($ProductClass);
  187.                 break;
  188.         }
  189.         // カートを取得して明細の正規化を実行
  190.         $Carts $this->cartService->getCarts();
  191.         $this->execPurchaseFlow($Carts);
  192.         switch ($operation) {
  193.             case 'up':
  194.                 break;
  195.             case 'down':
  196.                 $event = new EventArgs(
  197.                     [
  198.                         'productClass' => $ProductClass
  199.                     ],
  200.                 );
  201.                 $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_CART_DOWN_COMPLETE);
  202.                 break;
  203.             case 'remove':
  204.                 break;
  205.         }
  206.         log_info('カート演算処理終了', ['operation' => $operation'product_class_id' => $productClassId]);
  207.         if (isset($_SERVER['REQUEST_URI'])) {
  208.             if (!strpos($_SERVER['REQUEST_URI'], Constants::LOCALE_JAPAN)) {
  209.                 return $this->redirectToRoute('cart_locale');
  210.             };
  211.         }
  212.         return $this->redirectToRoute('cart');
  213.     }
  214.     /**
  215.      * カート明細の加算/減算/削除を行う.
  216.      *
  217.      * - 加算
  218.      *      - 明細の個数を1増やす
  219.      * - 減算
  220.      *      - 明細の個数を1減らす
  221.      *      - 個数が0になる場合は、明細を削除する
  222.      * - 削除
  223.      *      - 明細を削除する
  224.      *
  225.      * @Route(
  226.      *     path="/{_locale}/cart/{operation}/{productClassId}",
  227.      *     name="cart_handle_item_locale",
  228.      *     methods={"PUT"},
  229.      *     requirements={
  230.      *          "operation": "up|down|remove",
  231.      *          "productClassId": "\d+"
  232.      *     }
  233.      * )
  234.      */
  235.     public function handleCartItemLocale($operation$productClassId)
  236.     {
  237.         return $this->handleCartItem($operation$productClassId);
  238.     }
  239.     /**
  240.      * @param $Carts
  241.      *
  242.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|null
  243.      */
  244.     protected function execPurchaseFlow($Carts)
  245.     {
  246.         /** @var PurchaseFlowResult[] $flowResults */
  247.         $flowResults array_map(function ($Cart) {
  248.             $purchaseContext = new PurchaseContext($Cart$this->getUser());
  249.             return $this->purchaseFlow->validate($Cart$purchaseContext);
  250.         }, $Carts);
  251.         // 復旧不可のエラーが発生した場合はカートをクリアして再描画
  252.         $hasError false;
  253.         foreach ($flowResults as $result) {
  254.             if ($result->hasError()) {
  255.                 $hasError true;
  256.                 foreach ($result->getErrors() as $error) {
  257.                     $this->addRequestError($error->getMessage());
  258.                 }
  259.             }
  260.         }
  261.         if ($hasError) {
  262.             $this->cartService->clear();
  263.             if (isset($_SERVER['REQUEST_URI'])) {
  264.                 if (!strpos($_SERVER['REQUEST_URI'], Constants::LOCALE_JAPAN)) {
  265.                     return $this->redirectToRoute('cart_locale');
  266.                 };
  267.             }
  268.             return $this->redirectToRoute('cart');
  269.         }
  270.         $this->cartService->save();
  271.         foreach ($flowResults as $index => $result) {
  272.             foreach ($result->getWarning() as $warning) {
  273.                 if ($Carts[$index]->getItems()->count() > 0) {
  274.                     $cart_key $Carts[$index]->getCartKey();
  275.                     $this->addRequestError($warning->getMessage(), "front.cart.${cart_key}");
  276.                 } else {
  277.                     // キーが存在しない場合はグローバルにエラーを表示する
  278.                     $this->addRequestError($warning->getMessage());
  279.                 }
  280.             }
  281.         }
  282.         return null;
  283.     }
  284.     /**
  285.      * カートをロック状態に設定し、購入確認画面へ遷移する.
  286.      *
  287.      * @Route("/cart/buystep/{cart_key}", name="cart_buystep", requirements={"cart_key" = "[a-zA-Z0-9]+[_][\x20-\x7E]+"}, methods={"GET"})
  288.      */
  289.     public function buystep(Request $request$cart_key)
  290.     {
  291.         $Carts $this->cartService->getCart();
  292.         if (!is_object($Carts)) {
  293.             if (!$request->get('_locale') == Constants::LOCALE_JAPAN) {
  294.                 return $this->redirectToRoute('cart_locale');
  295.             }
  296.             return $this->redirectToRoute('cart');
  297.         }
  298.         // FRONT_CART_BUYSTEP_INITIALIZE
  299.         $event = new EventArgs(
  300.             [],
  301.             $request
  302.         );
  303.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE);
  304.         $this->cartService->setPrimary($cart_key);
  305.         $this->cartService->save();
  306.         // FRONT_CART_BUYSTEP_COMPLETE
  307.         $event = new EventArgs(
  308.             [],
  309.             $request
  310.         );
  311.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_CART_BUYSTEP_COMPLETE);
  312.         if ($event->hasResponse()) {
  313.             return $event->getResponse();
  314.         }
  315.         return $request->get('_locale') != Constants::LOCALE_JAPAN && $request->get('_locale') != null
  316.             $this->redirectToRoute('shopping_locale')
  317.             : $this->redirectToRoute('shopping');
  318.     }
  319.     /**
  320.      * カートをロック状態に設定し、購入確認画面へ遷移する.
  321.      *
  322.      * @Route("/{_locale}/cart/buystep/{cart_key}", name="cart_buystep_locale", requirements={"cart_key" = "[a-zA-Z0-9]+[_][\x20-\x7E]+"}, methods={"GET"})
  323.      */
  324.     public function buystepLocale(Request $request$cart_key)
  325.     {
  326.         return $this->buystep($request$cart_key);
  327.     }
  328. }