<?php
namespace Customize\Controller;
use Eccube\Controller\AbstractController;
use Eccube\Entity\Cart;
use Eccube\Entity\CartItem;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\CartItemRepository;
use Eccube\Service\CartService;
use Eccube\Service\OrderHelper;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Plugin\RelatedProduct42\Repository\RelatedProductRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class CartController extends AbstractController
{
/**
* @var CartItemRepository
*/
protected $cartItemRepository;
/**
* @var CartService
*/
protected $cartService;
/**
* @var PurchaseFlow
*/
protected $purchaseFlow;
/**
* @var BaseInfo
*/
protected $baseInfo;
/**
* @var RelatedProductRepository
*/
protected $relatedProductRepository;
public function __construct(
CartItemRepository $cartItemRepository,
CartService $cartService,
PurchaseFlow $purchaseFlow,
BaseInfoRepository $baseInfoRepository,
RelatedProductRepository $relatedProductRepository
) {
$this->cartItemRepository = $cartItemRepository;
$this->cartService = $cartService;
$this->purchaseFlow = $purchaseFlow;
$this->baseInfo = $baseInfoRepository->get();
$this->relatedProductRepository = $relatedProductRepository;
}
/**
* カート画面.
*
* @Route("/cart", name="cart", methods={"GET"})
* @Template("Cart/index.twig")
*/
public function index(Request $request)
{
// カートを取得して明細の正規化を実行
$Carts = $this->cartService->getCarts();
$this->execPurchaseFlow($Carts);
// TODO itemHolderから取得できるように
$least = [];
$quantity = [];
$isDeliveryFree = [];
$totalPrice = 0;
$totalQuantity = 0;
$product_ids = [];
foreach ($Carts as $Cart) {
$quantity[$Cart->getCartKey()] = 0;
$isDeliveryFree[$Cart->getCartKey()] = false;
if ($this->baseInfo->getDeliveryFreeQuantity()) {
if ($this->baseInfo->getDeliveryFreeQuantity() > $Cart->getQuantity()) {
$quantity[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeQuantity() - $Cart->getQuantity();
} else {
$isDeliveryFree[$Cart->getCartKey()] = true;
}
}
if ($this->baseInfo->getDeliveryFreeAmount()) {
if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $Cart->getTotalPrice()) {
$isDeliveryFree[$Cart->getCartKey()] = true;
} else {
$least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $Cart->getTotalPrice();
}
}
$totalPrice += $Cart->getTotalPrice();
$totalQuantity += $Cart->getQuantity();
foreach ($Cart->getItems() as $CartItem) {
$product_ids[] = $CartItem->getProductClass()->getProduct()->getId();
}
}
// カートが分割された時のセッション情報を削除
$request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
// 関連商品取得
$relatedProductQb = $this->relatedProductRepository->createQueryBuilder('rp');
$RelatedProducts = $relatedProductQb
->select('rp', 'cp')
->leftJoin('rp.ChildProduct', 'cp')
->where($relatedProductQb->expr()->in('rp.Product', ':product_ids'))
// カート内の商品が関連商品に含まれないようにする
->andWhere($relatedProductQb->expr()->notIn('rp.ChildProduct', ':product_ids'))
->setParameter('product_ids', $product_ids)
->addOrderBy('rp.id', 'DESC')
->getQuery()
->getResult();
$uniqueChildProductIds = [];
$filteredRelatedProducts = [];
// 配列をループしてChildProductが重複してる場合その値を取り除く
foreach ($RelatedProducts as $relatedProduct) {
$childProductId = $relatedProduct->getChildProduct()->getId();
if (!in_array($childProductId, $uniqueChildProductIds)) {
$uniqueChildProductIds[] = $childProductId;
$filteredRelatedProducts[] = $relatedProduct;
}
}
return [
'totalPrice' => $totalPrice,
'totalQuantity' => $totalQuantity,
// 空のカートを削除し取得し直す
'Carts' => $this->cartService->getCarts(true),
'least' => $least,
'quantity' => $quantity,
'is_delivery_free' => $isDeliveryFree,
'RelatedProducts' => $filteredRelatedProducts,
];
}
/**
* @param $Carts
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
*/
protected function execPurchaseFlow($Carts)
{
/** @var PurchaseFlowResult[] $flowResults */
$flowResults = array_map(function ($Cart) {
$purchaseContext = new PurchaseContext($Cart, $this->getUser());
return $this->purchaseFlow->validate($Cart, $purchaseContext);
}, $Carts);
// 復旧不可のエラーが発生した場合はカートをクリアして再描画
$hasError = false;
foreach ($flowResults as $result) {
if ($result->hasError()) {
$hasError = true;
foreach ($result->getErrors() as $error) {
$this->addRequestError($error->getMessage());
}
}
}
if ($hasError) {
$this->cartService->clear();
return $this->redirectToRoute('cart');
}
$this->cartService->save();
foreach ($flowResults as $index => $result) {
foreach ($result->getWarning() as $warning) {
if ($Carts[$index]->getItems()->count() > 0) {
$cart_key = $Carts[$index]->getCartKey();
$this->addRequestError($warning->getMessage(), "front.cart.${cart_key}");
} else {
// キーが存在しない場合はグローバルにエラーを表示する
$this->addRequestError($warning->getMessage());
}
}
}
return null;
}
/**
* カート内の名入れのboolean値をプルダウンに応じて制御するメソッド
*
* @Route(
* path="/cart/{operation}/{cartItemId}",
* name="cart_handle_naire",
* methods={"PUT"},
* requirements={
* "operation": "naire_true|naire_false",
* "cartItemId": "\d+"
* }
* )
*/
public function handleCartNaire($operation, $cartItemId)
{
log_info('カート名入れ操作開始', ['operation' => $operation, 'cart_item_id' => $cartItemId]);
$this->isTokenValid();
/** @var CartItem $CartItem */
$CartItem = $this->cartItemRepository->find($cartItemId);
if (is_null($CartItem)) {
log_info('商品が存在しないため、カート画面へredirect', ['operation' => $operation, 'cart_item_id' => $cartItemId]);
return $this->redirectToRoute('cart');
}
switch ($operation) {
case 'naire_true':
$CartItem->setNaire(true);
break;
case 'naire_false':
$CartItem->setNaire(false);
break;
}
$this->cartService->refreshCarts();
// カートを取得して明細の正規化を実行
$Carts = $this->cartService->getCarts();
$this->execPurchaseFlow($Carts);
log_info('カート名入れ処理終了', ['operation' => $operation, 'cart_item_id' => $cartItemId]);
return $this->redirectToRoute('cart');
}
}