app/Customize/Controller/AuctionController.php line 529

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\Controller;
  13. use Customize\Entity\Auction;
  14. use Customize\Entity\Master\AuctionStatus;
  15. use Customize\Event\EccubeEvents;
  16. use Customize\Form\Type\SearchAuctionType;
  17. use Customize\Form\Type\SearchProductType;
  18. use Customize\Repository\AuctionRepository;
  19. use Customize\Repository\BitHistoryRepository;
  20. use Customize\Repository\CustomerFavoriteAuctionRepository;
  21. use Customize\Repository\CustomerFavoriteProductRepository;
  22. use Customize\Repository\ProductRepository;
  23. use Customize\Repository\OrderRepository;
  24. use Eccube\Controller\AbstractController;
  25. use Eccube\Event\EventArgs;
  26. use Eccube\Repository\Master\ProductListMaxRepository;
  27. use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
  28. use Knp\Component\Pager\PaginatorInterface;
  29. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  30. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  33. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  36. class AuctionController extends AbstractController
  37. {
  38.     /**
  39.      * @var AuctionRepository
  40.      */
  41.     protected $auctionRepository;
  42.     /**
  43.      * @var BitHistoryRepository
  44.      */
  45.     protected $bitHistoryRepository;
  46.     /**
  47.      * @var CustomerFavoriteAuctionRepository
  48.      */
  49.     protected $customerFavoriteAuctionRepository;
  50.     /**
  51.      * @var CustomerFavoriteProductRepository
  52.      */
  53.     protected $customerFavoriteProductRepository;
  54.     /**
  55.      * @var ProductRepository
  56.      */
  57.     protected $productRepository;
  58.     /**
  59.      * @var ProductListMaxRepository
  60.      */
  61.     protected $productListMaxRepository;
  62.     /**
  63.      * @var OrderRepository
  64.      */
  65.     protected $orderRepository;
  66.     private $title '';
  67.     /**
  68.      * AuctionController constructor.
  69.      */
  70.     public function __construct(
  71.         AuctionRepository $auctionRepository,
  72.         BitHistoryRepository $bitHistoryRepository,
  73.         CustomerFavoriteAuctionRepository $customerFavoriteAuctionRepository,
  74.         CustomerFavoriteProductRepository $customerFavoriteProductRepository,
  75.         ProductRepository $productRepository,
  76.         ProductListMaxRepository $productListMaxRepository,
  77.         OrderRepository $orderRepository,
  78.     ) {
  79.         $this->auctionRepository $auctionRepository;
  80.         $this->bitHistoryRepository $bitHistoryRepository;
  81.         $this->customerFavoriteAuctionRepository $customerFavoriteAuctionRepository;
  82.         $this->customerFavoriteProductRepository $customerFavoriteProductRepository;
  83.         $this->productRepository $productRepository;
  84.         $this->productListMaxRepository $productListMaxRepository;
  85.         $this->orderRepository $orderRepository;
  86.     }
  87.     /**
  88.      * オークション一覧画面.
  89.      *
  90.      * @Route("/auctions/list", name="auction_list", methods={"GET"})
  91.      *
  92.      * @Template("Auction/list.twig")
  93.      */
  94.     public function index(Request $requestPaginatorInterface $paginator)
  95.     {
  96.         if ($this->isGranted('ROLE_USER')) {
  97.             // handleRequestは空のqueryの場合は無視するため
  98.             if ($request->getMethod() === 'GET') {
  99.                 $request->query->set('pageno'$request->query->get('pageno'''));
  100.             }
  101.             // searchForm
  102.             /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
  103.             $builder $this->formFactory->createNamedBuilder(''SearchAuctionType::class);
  104.             if ($request->getMethod() === 'GET') {
  105.                 $builder->setMethod('GET');
  106.             }
  107.             $event = new EventArgs(
  108.                 [
  109.                     'builder' => $builder,
  110.                 ],
  111.                 $request
  112.             );
  113.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_INDEX_INITIALIZE);
  114.             /* @var $searchForm \Symfony\Component\Form\FormInterface */
  115.             $searchForm $builder->getForm();
  116.             $searchForm->handleRequest($request);
  117.             // paginator
  118.             $searchData $searchForm->getData();
  119.             $qb $this->auctionRepository->getQueryBuilderBySearchData($searchData);
  120.             $event = new EventArgs(
  121.                 [
  122.                     'searchData' => $searchData,
  123.                     'qb' => $qb,
  124.                 ],
  125.                 $request
  126.             );
  127.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_INDEX_SEARCH);
  128.             $searchData $event->getArgument('searchData');
  129.             $query $qb->getQuery()
  130.                 ->useResultCache(true$this->eccubeConfig['eccube_result_cache_lifetime_short']);
  131.             /** @var SlidingPagination $pagination */
  132.             $pagination $paginator->paginate(
  133.                 $query,
  134.                 ! empty($searchData['pageno']) ? $searchData['pageno'] : 1,
  135.                 ! empty($searchData['disp_number']) ? $searchData['disp_number'] : 20
  136.             );
  137.             $Customer $this->getUser();
  138.             return [
  139.                 'subtitle' => 'オークション一覧',
  140.                 'pagination' => $pagination,
  141.                 'search_form' => $searchForm->createView(),
  142.                 'Customer' => $Customer,
  143.             ];
  144.         } else {
  145.             // 非会員の場合、ログイン画面を表示
  146.             return $this->redirectToRoute('mypage_login');
  147.         }
  148.     }
  149.     /**
  150.      * オークション詳細画面.
  151.      *
  152.      * @Route("/auctions/detail/{id}", name="auction_detail", methods={"GET"}, requirements={"id" = "\d+"})
  153.      *
  154.      * @Template("Auction/detail.twig")
  155.      *
  156.      * @return array
  157.      */
  158.     public function detail(Request $requestAuction $AuctionPaginatorInterface $paginator)
  159.     {
  160.         if ($this->isGranted('ROLE_USER')) {
  161.             $Customer $this->getUser();
  162.             if (! $this->checkVisibility($Auction)) {
  163.                 throw new NotFoundHttpException();
  164.             }
  165.             if ($Auction->isBefore() && !$Customer->getIsAdmin()) {
  166.                 throw new NotFoundHttpException();
  167.             }
  168.             // handleRequestは空のqueryの場合は無視するため
  169.             if ($request->getMethod() === 'GET') {
  170.                 $request->query->set('pageno'$request->query->get('pageno'''));
  171.                 $request->query->set('orderby'$request->query->get('orderby'3));
  172.             }
  173.             // searchForm
  174.             /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
  175.             $builder $this->formFactory->createNamedBuilder(''SearchProductType::class);
  176.             if ($request->getMethod() === 'GET') {
  177.                 $builder->setMethod('GET');
  178.             }
  179.             $event = new EventArgs(
  180.                 [
  181.                     'builder' => $builder,
  182.                 ],
  183.                 $request
  184.             );
  185.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE);
  186.             /* @var $searchForm \Symfony\Component\Form\FormInterface */
  187.             $searchForm $builder->getForm();
  188.             $searchForm->handleRequest($request);
  189.             // paginator
  190.             $searchData $searchForm->getData();
  191.             $searchData['auction_id'] = $Auction->getId();
  192.             $qb $this->productRepository->getQueryBuilderBySearchData($searchData);
  193.             $event = new EventArgs(
  194.                 [
  195.                     'searchData' => $searchData,
  196.                     'qb' => $qb,
  197.                 ],
  198.                 $request
  199.             );
  200.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_PRODUCT_INDEX_SEARCH);
  201.             $searchData $event->getArgument('searchData');
  202.             $query $qb->getQuery()
  203.                 ->useResultCache(true$this->eccubeConfig['eccube_result_cache_lifetime_short']);
  204.             /** @var SlidingPagination $pagination */
  205.             $pagination $paginator->paginate(
  206.                 $query,
  207.                 ! empty($searchData['pageno']) ? $searchData['pageno'] : 1,
  208.                 ! empty($searchData['disp_number']) ? $searchData['disp_number'] : 20
  209.             );
  210.             // 下見期間かどうか
  211.             $is_preview $Auction->isPreview();
  212.             // 競り後かどうか
  213.             $is_closed $Auction->isClosed();
  214.             // 訂正リストの有無
  215.             $has_correction_list = ! empty($Auction->getCorrectionListProducts());
  216.             $Products $this->productRepository->getTotalProductsForAuction($Auction->getId());
  217.             $biddingCompaniesCounts = [];
  218.             $productIds array_map(function ($Product) {
  219.                 return $Product->getId();
  220.             }, $Products);
  221.             if ($is_closed) {
  222.                 $biddingCompaniesResults $this->bitHistoryRepository->countBiddingCompaniesForProducts($productIds);
  223.             } else {
  224.                 $biddingCompaniesResults $this->productRepository->countBiddingCompaniesForProducts($productIds);
  225.             }
  226.             foreach ($biddingCompaniesResults as $result) {
  227.                 $biddingCompaniesCounts[$result['productId']] = $result['count'];
  228.             }
  229.             foreach ($pagination as $Product) {
  230.                 // もし結果が存在しない場合は 0 をセット
  231.                 $biddingCompaniesCounts[$Product->getId()] = $biddingCompaniesCounts[$Product->getId()] ?? 0;
  232.             }
  233.             $isUnpaid = !empty($this->orderRepository->getNotPaidOrder($Customer)) ? true false;
  234.             return [
  235.                 'title' => $this->title,
  236.                 'subtitle' => $Auction->getName(),
  237.                 'Auction' => $Auction,
  238.                 'auctionId' => $Auction->getId(),
  239.                 'pagination' => $pagination,
  240.                 'search_form' => $searchForm->createView(),
  241.                 'Customer' => $Customer,
  242.                 'is_preview' => $is_preview,
  243.                 'is_closed' => $is_closed,
  244.                 'has_correction_list' => $has_correction_list,
  245.                 'biddingCompaniesCounts' => $biddingCompaniesCounts,
  246.                 'isUnpaid' => $isUnpaid
  247.             ];
  248.         } else {
  249.             // 非会員の場合、ログイン画面を表示
  250.             //  ログイン後の画面遷移先を設定
  251.             $this->setLoginTargetPath($this->generateUrl('auction_detail', ['id' => $Auction->getId()], UrlGeneratorInterface::ABSOLUTE_URL));
  252.             return $this->redirectToRoute('mypage_login');
  253.         }
  254.     }
  255.     /**
  256.      * 競り中画面.
  257.      *
  258.      * @Route("/starting_auctions/detail/{id}", name="starting_auction_detail", methods={"GET"}, requirements={"id" = "\d+"})
  259.      *
  260.      * @Template("Product/starting_detail.twig")
  261.      *
  262.      * @return array
  263.      */
  264.     public function startingDetail(Request $requestAuction $Auction)
  265.     {
  266.         if ($this->isGranted('ROLE_USER')) {
  267.             if (! $this->checkVisibility($Auction)) {
  268.                 throw new NotFoundHttpException();
  269.             }
  270.             $Customer $this->getUser();
  271.             $Products $this->productRepository->getProductsSortedByAuctionNo($Auction->getId());
  272.             $ProductsCount count($this->productRepository->getTotalProductsForAuction($Auction->getId()));
  273.             $firstProductId = !empty($Products) ? $Products[0]['id'] : 0;
  274.             
  275.             $nextProductImages = [];
  276.             $auctionNos array_map(function ($Product) {
  277.                 return $Product->getAuctionNo();
  278.             }, $Products);
  279.             if (!empty($auctionNos)) {
  280.                 $minAuctionNo min($auctionNos);
  281.                 $nextProducts $this->productRepository->findNextProducts($Auction->getId(), $minAuctionNo);
  282.                 foreach ($Products as $Product) {
  283.                     $filteredProducts array_filter($nextProducts, function($nextProduct) use ($Product) {
  284.                         return $nextProduct->getAuctionNo() > $Product->getAuctionNo();
  285.                     });
  286.                 
  287.                     // 2件だけ取得
  288.                     $nextProductImages[$Product->getId()] = array_slice($filteredProducts02);
  289.                 }
  290.             };
  291.             $productIds array_map(function ($Product) {
  292.                 return $Product->getId();
  293.             }, $Products);
  294.             $biddingCompaniesCounts = [];
  295.             $biddingCompaniesResults $this->productRepository->countBiddingCompaniesForProducts($productIds);
  296.             foreach ($biddingCompaniesResults as $result) {
  297.                 $biddingCompaniesCounts[$result['productId']] = $result['count'];
  298.             }
  299.             $isFavorites = [];
  300.             $favorites $this->customerFavoriteProductRepository->getFavoritesForCustomer($Customer$productIds);
  301.             foreach ($Products as $Product) {
  302.                 $isFavorites[$Product->getId()] = in_array($Product->getId(), $favorites);
  303.             }
  304.             $startPrices = [];
  305.             $startPricesResults $this->productRepository->getStartPrices($productIds);
  306.             foreach ($startPricesResults as $result) {
  307.                 $startPrices[$result['productId']] =  number_format($result['startPrice']);
  308.             }
  309.             
  310.             $limitPrices = [];
  311.             $settingPersents = [];
  312.             $canBids = [];
  313.             $isOwns = [];
  314.             foreach ($Products as $Product) {
  315.                 $limitPrices[$Product->getId()] = $Product->getLimitPrice();
  316.                 $settingPersents[$Product->getId()] = $Product->getSettingPersent();
  317.                 $canBids[$Product->getId()] = $Product->getTenderPrice($Customer) != && $Product->getNowPrice() == $Product->getTenderPrice($Customer) ? false true;
  318.                 $isOwns[$Product->getId()] = $Product->getCustomer() == $Customer true false;
  319.             }
  320.             $randomBytes random_bytes(32);
  321.             $token hash('sha256'$randomBytes);
  322.             $hashedToken hash('sha256'$token);
  323.             $Customer->setToken($hashedToken);
  324.             $this->entityManager->persist($Customer);
  325.             $this->entityManager->flush();
  326.             $socketHostUrl getenv('SOCKET_HOST_URL');
  327.             $isUnpaid = !empty($this->orderRepository->getNotPaidOrder($Customer)) ? true false;
  328.             // 競り後かどうか
  329.             $is_closed $Auction->isClosed();
  330.             return [
  331.                 'title' => $this->title,
  332.                 'Auction' => $Auction,
  333.                 'Products' => $Products,
  334.                 'limitPrices' => json_encode($limitPrices),
  335.                 'settingPersents' => json_encode($settingPersents),
  336.                 'nextProductImages' => $nextProductImages,
  337.                 'token' => $token,
  338.                 'Customer' => $Customer,
  339.                 'isFavorites' => $isFavorites,
  340.                 'biddingCompaniesCounts' => $biddingCompaniesCounts,
  341.                 'canBids' => json_encode($canBids),
  342.                 'isOwns' => json_encode($isOwns),
  343.                 'startPrices' => json_encode($startPrices),
  344.                 'socketHostUrl' => $socketHostUrl,
  345.                 'ProductsCount' => $ProductsCount,
  346.                 'isUnpaid' => $isUnpaid,
  347.                 'is_closed' => $is_closed,
  348.                 'firstProductId' => $firstProductId
  349.             ];
  350.         } else {
  351.             // 非会員の場合、ログイン画面を表示
  352.             return $this->redirectToRoute('mypage_login');
  353.         }
  354.     }
  355.     /**
  356.      * お気に入り追加.
  357.      *
  358.      * @Route("/auctions/add_favorite/{id}", name="auction_add_favorite", requirements={"id" = "\d+"}, methods={"GET", "POST"})
  359.      */
  360.     public function addFavorite(Request $requestAuction $Auction)
  361.     {
  362.         $this->checkVisibility($Auction);
  363.         $event = new EventArgs(
  364.             [
  365.                 'Auction' => $Auction,
  366.             ],
  367.             $request
  368.         );
  369.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_FAVORITE_ADD_INITIALIZE);
  370.         if ($this->isGranted('ROLE_USER')) {
  371.             $Customer $this->getUser();
  372.             $this->customerFavoriteAuctionRepository->addFavorite($Customer$Auction);
  373.             $this->session->getFlashBag()->set('auction_detail.just_added_favorite'$Auction->getId());
  374.             $event = new EventArgs(
  375.                 [
  376.                     'Auction' => $Auction,
  377.                 ],
  378.                 $request
  379.             );
  380.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_FAVORITE_ADD_COMPLETE);
  381.             return $this->redirect($_SERVER['HTTP_REFERER']);
  382.         } else {
  383.             // 非会員の場合、ログイン画面を表示
  384.             //  ログイン後の画面遷移先を設定
  385.             $this->setLoginTargetPath($_SERVER['HTTP_REFERER']);
  386.             $this->session->getFlashBag()->set('eccube.add.favorite'true);
  387.             $event = new EventArgs(
  388.                 [
  389.                     'Auction' => $Auction,
  390.                 ],
  391.                 $request
  392.             );
  393.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_FAVORITE_ADD_COMPLETE);
  394.             return $this->redirectToRoute('mypage_login');
  395.         }
  396.     }
  397.     /**
  398.      * お気に入り削除.
  399.      *
  400.      * @Route("/auctions/remove_favorite/{id}", name="auction_remove_favorite", requirements={"id" = "\d+"}, methods={"GET", "POST"})
  401.      */
  402.     public function removeFavorite(Request $requestAuction $Auction)
  403.     {
  404.         if ($this->isGranted('ROLE_USER')) {
  405.             $Customer $this->getUser();
  406.             $CustomerFavoriteAuction $this->customerFavoriteAuctionRepository->findOneBy(['Customer' => $Customer'Auction' => $Auction]);
  407.             if ($CustomerFavoriteAuction) {
  408.                 $this->customerFavoriteAuctionRepository->delete($CustomerFavoriteAuction);
  409.             } else {
  410.                 throw new BadRequestHttpException();
  411.             }
  412.             $event = new EventArgs(
  413.                 [
  414.                     'Customer' => $Customer,
  415.                     'CustomerFavoriteAuction' => $CustomerFavoriteAuction,
  416.                 ],
  417.                 $request
  418.             );
  419.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_AUCTION_FAVORITE_REMOVE_COMPLETE);
  420.             return $this->redirect($_SERVER['HTTP_REFERER']);
  421.         } else {
  422.             // 非会員の場合、ログイン画面を表示
  423.             return $this->redirectToRoute('mypage_login');
  424.         }
  425.     }
  426.     /**
  427.      * オークションのstart_date/end_dateを登録
  428.      *
  429.      * @Route("/auctions/register_date/{id}", name="register_date", requirements={"id" = "\d+"}, methods={"GET", "POST"})
  430.      */
  431.     public function registerDate(Request $requestAuction $Auction) {
  432.         if ($request->request->get('type') == 'start') {
  433.             $Auction->setStartDate(new \DateTime());
  434.         } else {
  435.             $Auction->setEndDate(new \DateTime());
  436.         }
  437.         $this->entityManager->flush();
  438.         return $this->json(['done' => true]);
  439.     }
  440.     /**
  441.      * 開催中のオークションを取得
  442.      *
  443.      * @Route("/auctions/start_auction_list", name="start_auction_list", methods={"GET", "POST"})
  444.      */
  445.     public function startAuctionList(Request $request) {
  446.         $startAuction $this->auctionRepository->getStartAuction();
  447.         return $this->json(json_encode($startAuction));
  448.     }
  449.     protected function getPageTitle($searchData)
  450.     {
  451.         if (isset($searchData['name']) && ! empty($searchData['name'])) {
  452.             return trans('front.auction.search_result');
  453.         } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
  454.             return $searchData['category_id']->getName();
  455.         } else {
  456.             return trans('front.auction.all_auctions');
  457.         }
  458.     }
  459.     /**
  460.      * 閲覧可能なオークションかどうかを判定
  461.      *
  462.      *
  463.      * @return bool 閲覧可能な場合はtrue
  464.      */
  465.     protected function checkVisibility(Auction $Auction)
  466.     {
  467.         $is_admin $this->session->has('_security_admin');
  468.         // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
  469.         if (! $is_admin) {
  470.             // 公開ステータスでない商品は表示しない.
  471.             if ($Auction->getStatus()->getId() !== AuctionStatus::DISPLAY_SHOW) {
  472.                 return false;
  473.             }
  474.         }
  475.         return true;
  476.     }
  477. }