app/Plugin/ProductOption42/Controller/AddcartController.php line 48

Open in your IDE?
  1. <?php
  2. /*
  3. * Plugin Name : ProductOption
  4. *
  5. * Copyright (C) BraTech Co., Ltd. All Rights Reserved.
  6. * http://www.bratech.co.jp/
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Plugin\ProductOption42\Controller;
  12. use Eccube\Controller\AbstractController;
  13. use Eccube\Entity\Master\ProductStatus;
  14. use Eccube\Entity\Customer;
  15. use Eccube\Entity\Product;
  16. use Eccube\Entity\ProductClass;
  17. use Eccube\Event\EccubeEvents;
  18. use Eccube\Event\EventArgs;
  19. use Eccube\Form\Type\AddCartType;
  20. use Eccube\Service\PurchaseFlow\PurchaseContext;
  21. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  22. use Plugin\ProductOption42\Entity\Option;
  23. use Plugin\ProductOption42\Service\ProductOptionCartService;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  26. use Symfony\Component\Routing\Annotation\Route;
  27. class AddcartController extends AbstractController
  28. {
  29.     protected $purchaseFlow;
  30.     protected $cartService;
  31.     public function __construct(
  32.         PurchaseFlow $cartPurchaseFlow,
  33.         ProductOptionCartService $cartService
  34.     ) {
  35.         $this->purchaseFlow = $cartPurchaseFlow;
  36.         $this->cartService = $cartService;
  37.     }
  38.     /**
  39.      * カートに追加.
  40.      *
  41.      * @Route("/products/add_cart/{id}", name="product_add_cart", methods={"POST"}, requirements={"id" = "\d+"})
  42.      */
  43.     public function addCart(Request $request, Product $Product)
  44.     {
  45.         // エラーメッセージの配列
  46.         $errorMessages = [];
  47.         if (!$this->checkVisibility($Product)) {
  48.             throw new NotFoundHttpException();
  49.         }
  50.         $builder = $this->formFactory->createNamedBuilder(
  51.             '',
  52.             AddCartType::class,
  53.             null,
  54.             [
  55.                 'product' => $Product,
  56.                 'id_add_product_id' => false,
  57.             ]
  58.         );
  59.         $event = new EventArgs(
  60.             [
  61.                 'builder' => $builder,
  62.                 'Product' => $Product,
  63.             ],
  64.             $request
  65.         );
  66.         $this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE);
  67.         /* @var $form \Symfony\Component\Form\FormInterface */
  68.         $form = $builder->getForm();
  69.         $form->handleRequest($request);
  70.         if (!$form->isValid()) {
  71.             foreach($form->all() as $child){
  72.                 $config = $child->getConfig();
  73.                 foreach($child->getErrors() as $error){
  74.                     $errorMessages[] = $config->getOption('label') .':'. $error->getMessage();
  75.                 }
  76.             }
  77.         }
  78.         $addCartData = $form->getData();
  79.         $ProductClass = $this->entityManager->getRepository(ProductClass::class)->find($addCartData['product_class_id']);
  80.         $limit = $ProductClass->getSaleLimit();
  81.         if(!$ProductClass->isStockUnlimited()){
  82.             $stock = $ProductClass->getStock();
  83.         }
  84.         if (!is_null($limit) || isset($stock)) {
  85.             $Carts = $this->cartService->getCarts();
  86.             $quantity = $addCartData['quantity'];
  87.             foreach($Carts as $Cart){
  88.                 foreach($Cart->getCartItems() as $item){
  89.                     if($item->getProductClass()->getId() == $ProductClass->getId())$quantity += $item->getQuantity();
  90.                 }
  91.             }
  92.             $productName = $ProductClass->getProduct()->getName();
  93.             if ($ProductClass->hasClassCategory1()) {
  94.                 $productName .= ' - '.$ProductClass->getClassCategory1()->getName();
  95.             }
  96.             if ($ProductClass->hasClassCategory2()) {
  97.                 $productName .= ' - '.$ProductClass->getClassCategory2()->getName();
  98.             }
  99.             if (!is_null($limit) && $limit < $quantity ) {
  100.                 $errorMessages[] = trans('front.shopping.over_sale_limit', ['%product%' => $productName]);
  101.             }
  102.             if (isset($stock) && $stock < $quantity ) {
  103.                 $errorMessages[] = trans('front.shopping.out_of_stock', ['%product%' => $productName]);
  104.             }
  105.         }
  106.         if(count($errorMessages) == 0){
  107.             log_info(
  108.                 'カート追加処理開始',
  109.                 [
  110.                     'product_id' => $Product->getId(),
  111.                     'product_class_id' => $addCartData['product_class_id'],
  112.                     'quantity' => $addCartData['quantity'],
  113.                 ]
  114.             );
  115.             // カートへ追加
  116.             $ProductOptions = $Product->getProductOptions();
  117.             $Options = [];
  118.             foreach($ProductOptions as $ProductOption){
  119.                 $Option = $ProductOption->getOption();
  120.                 $option_key = 'productoption'. $Option->getId();
  121.                 $value = $form->get($option_key)->getData();
  122.                 if($Option){
  123.                     $add = true;
  124.                     if($Option->getType() == Option::SELECT_TYPE || $Option->getType() == Option::RADIO_TYPE ){
  125.                         if($Option->getDisableCategory()){
  126.                             if($Option->getDisableCategory() == $value){
  127.                                 $add = false;
  128.                             }
  129.                         }
  130.                         $value = $value->getId();
  131.                         if(strlen($value) == 0)$add = false;
  132.                     }elseif($Option->getType() == Option::TEXT_TYPE || $Option->getType() == Option::TEXTAREA_TYPE || $Option->getType() == Option::NUMBER_TYPE){
  133.                         if(strlen($value) == 0)$add = false;
  134.                     }elseif($Option->getType() == Option::CHECKBOX_TYPE){
  135.                         if(count($value) == 0){
  136.                             $add = false;
  137.                         }else{
  138.                             $buff = $value;
  139.                             $value = [];
  140.                             foreach($buff as $categoryoption){
  141.                                 $value[] = $categoryoption->getId();
  142.                             }
  143.                         }
  144.                     }elseif($Option->getType() == Option::DATE_TYPE){
  145.                         if(is_null($value))$add = false;
  146.                     }
  147.                     if($add){
  148.                         if(is_array($value)){
  149.                             $Options[$Option->getId()] = $value;
  150.                         }elseif(is_object($value)){
  151.                             $Options[$Option->getId()] = $value->format('Y-m-d');
  152.                         }else{
  153.                             $Options[$Option->getId()] = (string)$value;
  154.                         }
  155.                     }
  156.                 }
  157.             }
  158.             $this->cartService->addProductOption($addCartData['product_class_id'], $Options, $addCartData['quantity']);
  159.             // 明細の正規化
  160.             $Carts = $this->cartService->getCarts();
  161.             foreach ($Carts as $Cart) {
  162.                 /** @var Customer $Customer */
  163.                 $Customer = $this->getUser();
  164.                 $result = $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart, $Customer));
  165.                 // 復旧不可のエラーが発生した場合は追加した明細を削除.
  166.                 if ($result->hasError()) {
  167.                     $this->cartService->removeProduct($addCartData['product_class_id']);
  168.                     foreach ($result->getErrors() as $error) {
  169.                         $errorMessages[] = $error->getMessage();
  170.                     }
  171.                 }
  172.                 foreach ($result->getWarning() as $warning) {
  173.                     $errorMessages[] = $warning->getMessage();
  174.                 }
  175.             }
  176.             $this->cartService->save();
  177.             log_info(
  178.                 'カート追加処理完了',
  179.                 [
  180.                     'product_id' => $Product->getId(),
  181.                     'product_class_id' => $addCartData['product_class_id'],
  182.                     'quantity' => $addCartData['quantity'],
  183.                 ]
  184.             );
  185.             $event = new EventArgs(
  186.                 [
  187.                     'form' => $form,
  188.                     'Product' => $Product,
  189.                 ],
  190.                 $request
  191.             );
  192.             $this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE);
  193.         }
  194.         if ($event->getResponse() !== null) {
  195.             return $event->getResponse();
  196.         }
  197.         if ($request->isXmlHttpRequest()) {
  198.             // ajaxでのリクエストの場合は結果をjson形式で返す。
  199.             // 初期化
  200.             $done = null;
  201.             $messages = [];
  202.             if (empty($errorMessages)) {
  203.                 // エラーが発生していない場合
  204.                 $done = true;
  205.                 array_push($messages, trans('front.product.add_cart_complete'));
  206.             } else {
  207.                 // エラーが発生している場合
  208.                 $done = false;
  209.                 $messages = $errorMessages;
  210.             }
  211.             return $this->json(['done' => $done, 'messages' => $messages]);
  212.         } else {
  213.             // ajax以外でのリクエストの場合はカート画面へリダイレクト
  214.             if (empty($errorMessages)) {
  215.                 return $this->redirectToRoute('cart');
  216.             }else{
  217.                 foreach ($errorMessages as $errorMessage) {
  218.                     $this->addRequestError($errorMessage);
  219.                 }
  220.                 return $this->redirect($request->headers->get('referer'));
  221.             }
  222.         }
  223.     }
  224.     private function checkVisibility(Product $Product)
  225.     {
  226.         $is_admin = $this->session->has('_security_admin');
  227.         // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
  228.         if (!$is_admin) {
  229.             // 在庫なし商品の非表示オプションが有効な場合.
  230.             // if ($this->BaseInfo->isOptionNostockHidden()) {
  231.             //     if (!$Product->getStockFind()) {
  232.             //         return false;
  233.             //     }
  234.             // }
  235.             // 公開ステータスでない商品は表示しない.
  236.             if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
  237.                 return false;
  238.             }
  239.         }
  240.         return true;
  241.     }
  242. }