app/Plugin/SDream/EventSubscriber/CartSubscriber.php line 106

Open in your IDE?
  1. <?php
  2. /*
  3.     役割:UI制御・警告表示
  4. */
  5. namespace Plugin\SDream\EventSubscriber;
  6. use Eccube\Event\EccubeEvents;
  7. use Eccube\Event\EventArgs;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. use Psr\Log\LoggerInterface;
  10. use Eccube\Service\CartService;
  11. use Symfony\Component\HttpFoundation\RedirectResponse;
  12. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  13. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  14. use Symfony\Component\Routing\RouterInterface;
  15. use Plugin\SDream\Service\CustomerGuard;
  16. use Plugin\SDream\Service\CartRuleChecker;
  17. use Plugin\SDream\Service\ProductPurchaseRuleChecker;
  18. use Plugin\SDream\Service\PurchaseHistoryLimiter;
  19. use Plugin\SDream\Service\PaymentRestrictionService;
  20. use Symfony\Component\Security\Core\Security;
  21. use Eccube\Entity\Customer;
  22. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  23. use Eccube\Service\OrderHelper;
  24. class CartSubscriber implements EventSubscriberInterface
  25. {
  26.     private Security $security;
  27.     private CartService $cartService;
  28.     private OrderHelper $orderHelper;
  29.     private CustomerGuard $customerGuard;
  30.     private CartRuleChecker $cartRuleChecker;
  31.     private ProductPurchaseRuleChecker $productPurchaseRuleChecker;
  32.     private PurchaseHistoryLimiter $purchaseHistoryLimiter;
  33.     private PaymentRestrictionService $paymentRestrictionService;
  34.     private FlashBagInterface $flashBag;
  35.     private RouterInterface $router;//ルート名から URL を生成するためのサービス
  36.     private LoggerInterface $logger;
  37.     public function __construct(
  38.         Security $security,
  39.         CartService $cartService,
  40.         OrderHelper $orderHelper,
  41.         CustomerGuard $customerGuard,
  42.         CartRuleChecker $cartRuleChecker,
  43.         ProductPurchaseRuleChecker $productPurchaseRuleChecker,
  44.         PurchaseHistoryLimiter $purchaseHistoryLimiter,
  45.         PaymentRestrictionService $paymentRestrictionService,
  46.         FlashBagInterface $flashBag,
  47.         LoggerInterface $logger,
  48.         RouterInterface $router
  49.     ) {
  50.         $this->security $security;
  51.         $this->flashBag $flashBag;
  52.         $this->orderHelper $orderHelper;
  53.         $this->customerGuard $customerGuard;
  54.         $this->cartRuleChecker $cartRuleChecker;
  55.         $this->productPurchaseRuleChecker $productPurchaseRuleChecker;
  56.         $this->purchaseHistoryLimiter $purchaseHistoryLimiter;
  57.         $this->paymentRestrictionService $paymentRestrictionService;
  58.         $this->cartService $cartService;
  59.         $this->logger $logger;
  60.         $this->router $router;
  61.     }
  62.     private function getCurrentCustomer(): ?Customer
  63.     {
  64.         $user $this->security->getUser();
  65.         return $user instanceof Customer $user null;
  66.     }
  67.     public static function getSubscribedEvents()
  68.     {
  69.         return [
  70.             //EccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE => 'onBuyStep', エラー時にカートが止まらない
  71.             EccubeEvents::FRONT_CART_BUYSTEP_COMPLETE => 'onBuyStep',
  72.         ];
  73.     }
  74.     /**
  75.      * 
  76.      * カート
  77.      *  → チェックをする ・・・ ここでこれを実施
  78.      *  → レジに進む
  79.      *
  80.      * チェックする内容
  81.      *  ・不定貫なら カード決済、Paid は与信のみ
  82.      *      再与信対象(ペイドの再与信はどうやるか??不明のまま)
  83.      * ・定貫・不定貫が混ざっている場合はエラー
  84.      *  ・複数配送先が混ざっている場合はエラー
  85.      * ・例えば、冷凍は代引きNGとかでもできる
  86.      * 
  87.      * 
  88.      * 
  89.      */ 
  90.     public function onBuyStep(EventArgs $event)
  91.     {
  92.         //$this->logger->info('onBuyStep called');
  93.         // ★ Cart は service から取得
  94.         $Cart $this->cartService->getCart();
  95.         if (!$Cart) {
  96.             return;
  97.         }
  98.         //チェックする
  99.         $errors = [];
  100.         //ログインユーザー
  101.         $Customer =
  102.             $this->getCurrentCustomer() ?: $this->orderHelper->getNonMember();
  103.         //1.会員状態・会員区分チェック
  104.         try {
  105.             $this->customerGuard->assertPurchasable($Customer);
  106.         } catch (AccessDeniedException $e) {
  107.             $errors[] = $e->getMessage();
  108.         }
  109.         //2.カート構成ルール(Cart全体)
  110.         //3.商品購入可否ルール(商品×会員)
  111.         //4.購入履歴制限(時間制限)
  112.         $errors array_merge(
  113.             $errors,
  114.             $this->cartRuleChecker->validate($Cart),
  115.             $this->productPurchaseRuleChecker->validate($Cart$Customer),
  116.             $this->purchaseHistoryLimiter->validate($Cart$Customer)
  117.         );
  118.         // 5.決済ドメインルール(共通決済)
  119.         $allowedPayments =
  120.             $this->paymentRestrictionService
  121.                 ->resolveAllowedPayments($Cart$Customer);
  122.         if (empty($allowedPayments)) {
  123.             $errors[] =
  124.                 '同じ支払方法で購入できない商品が含まれています。' .
  125.                 '恐れ入りますが、商品を分けてご購入ください。';
  126.         }
  127.         if (!empty($errors)) {
  128.             foreach ($errors as $message) {
  129.                 $this->flashBag->add(
  130.                     'eccube.front.cart.error',
  131.                     $message
  132.                 );
  133.             }
  134.             // STOP!「レジに進む」へ「進ませない」
  135.             //$event->stopPropagation();            
  136.             $event->setResponse(
  137.                 new RedirectResponse($this->router->generate('cart'))
  138.             );
  139.             return;
  140.         }
  141.     }
  142.     //強制中止確認用・・・画面メッセージ
  143.     public function onBuyStepDEBUG(EventArgs $event)
  144.     {
  145.         $this->logger->info('onBuyStep called (force reject test)');
  146.         // ★ Cart 画面で表示される Flash キー
  147.         $this->flashBag->add(
  148.             'eccube.front.cart.error',
  149.             '【テスト】現在このカートではレジに進めません。'
  150.         );
  151.         /*
  152.             index.twigの以下の表示される
  153.             {% for error in app.session.flashbag.get('eccube.front.cart.error') %}
  154.                 <div class="ec-cartRole__error">
  155.                     <div class="ec-alert-warning">
  156.                         <div class="ec-alert-warning__icon">
  157.                             <img src="{{ asset('assets/icon/exclamation-white.svg') }}">
  158.                         </div>
  159.                         <div class="ec-alert-warning__text">
  160.                             {{ error|trans|nl2br }}
  161.                         </div>
  162.                     </div>
  163.                 </div>
  164.             {% endfor %}
  165.         */
  166.         $event->setResponse(
  167.             new RedirectResponse($this->router->generate('cart'))
  168.         );
  169.         
  170.     }
  171.     private function hasVariableWeightItem($Cart): bool
  172.     {
  173.         foreach ($Cart->getCartItems() as $cartItem) {
  174.             $productClass $cartItem->getProductClass();
  175.             if (!$productClass) {
  176.                 continue;
  177.             }
  178.             $product $productClass->getProduct();
  179.             if ($product && $product->isVariableWeight()) {
  180.                 return true;
  181.             }
  182.         }
  183.         return false;
  184.     }
  185. }