app/Customize/EventListener/EccubeProductCartAddListener.php line 89

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 Customize\EventListener;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Eccube\Event\EccubeEvents;
  15. use Eccube\Event\EventArgs;
  16. use Doctrine\ORM\EntityManagerInterface;
  17. use Eccube\Entity\Customer;
  18. use Exception;
  19. use Customize\Exception\DenyProductException;
  20. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  21. use Eccube\Entity\Product;
  22. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  23. use Symfony\Component\Security\Core\Security;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  26. use Symfony\Component\HttpFoundation\RedirectResponse;
  27. /**
  28.  * カートに商品を追加した際に発生するイベントリスナー。
  29.  */
  30. class EccubeProductCartAddListener implements EventSubscriberInterface
  31. {
  32.     const ERRORS = array(
  33.         'duplicate' => 'この商品は複数回購入することができません。',
  34.         'guest' => 'この商品はログインした状態でのみ購入することが可能です。',
  35.         'product' => '対象の商品が見つかりませんでした。'
  36.     );
  37.     /**
  38.      * @var EntityManagerInterface
  39.      */
  40.     protected $entityManager;
  41.     /**
  42.      * @var SessionInterface
  43.      */
  44.     private $session;
  45.     /**
  46.      * @var Security $security
  47.      */
  48.     private $security;
  49.     public function __construct(EntityManagerInterface $entityManagerSessionInterface $sessionSecurity $security)
  50.     {
  51.         $this->entityManager $entityManager;
  52.         $this->session $session;
  53.         $this->security $security;
  54.     }
  55.     /**
  56.      * 対応するメソッドと優先度を登録する。
  57.      * 数値が高いほど優先度高。
  58.      *
  59.      * @see https://symfony.com/doc/4.4/event_dispatcher.html
  60.      *
  61.      * @return array
  62.      */
  63.     public static function getSubscribedEvents()
  64.     {
  65.         return [
  66.             EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE => [
  67.                 ['prohibitionOfDuplicatePurchases'0]
  68.             ]
  69.         ];
  70.     }
  71.     /**
  72.      * 特定商品(プランの重複購入およびゲスト購入を禁止する。
  73.      * 基本的にはtwigで制御するため、不正POST対策のみ。
  74.      *
  75.      * @param EventArgs $event
  76.      * @return void
  77.      * @throws Exception
  78.      */
  79.     public function prohibitionOfDuplicatePurchases(EventArgs $event)
  80.     {
  81.         try {
  82.             /** @var Request $request */
  83.             $request $event->getRequest();
  84.             $arguments $event->getArguments();
  85.             if (!isset($arguments['Product'])) {
  86.                 return $this->redirectOrThrowError($requestself::ERRORS['product']);
  87.             }
  88.             /** @var \Eccube\Entity\Product $product */
  89.             $product $arguments['Product'];
  90.             if ($product->getId() == env('PLAN_PRODUCT_ID'77)) {
  91.                 // ログインしていない
  92.                 /** @var \Eccube\Entity\Customer $user */
  93.                 $user $this->security->getUser();
  94.                 if (empty($user) || !$user instanceof Customer) {
  95.                     return $this->redirectOrThrowError($requestself::ERRORS['guest'], $product);
  96.                 }
  97.                 /** @var \Doctrine\Common\Collections\ArrayCollection $orders */
  98.                 $orders $user->getOrders();
  99.                 /** @var \Eccube\Entity\Order $order */
  100.                 foreach ($orders as $order) {
  101.                     if (!empty($order->getOrderStatus()) && $order->getOrderStatus()->isDisplayOrderCount()) {
  102.                         /** @var \Eccube\Entity\OrderItem */
  103.                         foreach ($order->getOrderItems() as $orderItem) {
  104.                             if ($orderItem->isProduct()) {
  105.                                 $productId $orderItem->getProduct()->getId();
  106.                                 if ($productId == env('PLAN_PRODUCT_ID'77)) {
  107.                                     return $this->redirectOrThrowError($requestself::ERRORS['duplicate'], $product);
  108.                                 }
  109.                             }
  110.                         }
  111.                     }
  112.                 }
  113.             }
  114.         } catch (DenyProductException $e) {
  115.             throw $e;
  116.         } catch (NotFoundHttpException $e) {
  117.             throw $e;
  118.         } catch (Exception $e) {
  119.             throw $e;
  120.         }
  121.     }
  122.     /**
  123.      * 商品の購入を許可しない場合レスポンスまたは例外を発生させる。
  124.      * Ajax: 例外, 通常アクセス: リダイレクト
  125.      * →リダイレクトの場合ディスパッチ元の処理が続行してしまうため例外で対応。
  126.      *
  127.      * @param Request $request
  128.      * @param string $message
  129.      * @return RedirectResponse|void
  130.      * @throws DenyProductException|NotFoundHttpException
  131.      */
  132.     public function redirectOrThrowError(Request $requeststring $messageProduct $product null)
  133.     {
  134.         if (empty($product)) {
  135.             throw new NotFoundHttpException();
  136.         }
  137.         if ($request->isXmlHttpRequest()) {
  138.             throw new DenyProductException($message);
  139.         } else {
  140.             throw new NotFoundHttpException();
  141.             // global $kernel;
  142.             // $container = $kernel->getContainer();
  143.             // $redirectUrl = $container->get('router')->generate('product_detail', ['id' => $product->getId()], UrlGeneratorInterface::ABSOLUTE_PATH);
  144.             // $this->session->getFlashBag()->add('customize.error.deny_product', $message);
  145.             // return new RedirectResponse($redirectUrl);
  146.         }
  147.     }
  148. }