<?php
/**
* @version EC-CUBE4系
* @copyright 株式会社 翔 kakeru.co.jp
*
* 2022年03月21日カスタマイズ
*
* app/Customize/Controller/CartController.php
*
*
* カート
*
*
*
* ≡≡≡┏(^o^)┛
*****************************************************/
namespace Customize\Controller;
use Customize\Controller\LM\DataLayerTrait;
use Customize\Event\LmEvents;
use Customize\Service\EstimateCharacterizer;
use Customize\Service\GoodsService;
use Customize\Service\LmHelper;
use Customize\Service\MobileDetector as LmMobileDetector;
use Customize\Service\SampleService;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Customer;
use Eccube\Entity\Layout;
use Eccube\Entity\ProductClass;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\ProductClassRepository;
use Customize\Service\CartService;
use Customize\Service\OrderHelper;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Twig\Environment as Twig;
use Lm\Engine\EC\Entity\GoodsWithRelated;
use Lm\Engine\Zaiko\Entity\SkuExtended;
use Lm\Entity\Goods;
use Lm\Entity\GoodsColor;
use Lm\Entity\GoodsPrice;
use Lm\Entity\Jancode;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Customize\Service\CommonService;
use Customize\Service\CatalogService;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Customize\Validator as Assert;
use Customize\Service\EstimateService;
use Customize\Converter\OrderConverter;
use Customize\Service\RecentGoodsService;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class CartController extends \Eccube\Controller\CartController
{
use DataLayerTrait {
DataLayerTrait::__construct as __dataLayerTraitConstruct;
}
const URL_NAME_AJAX = [
CartService::ROUTE_ADD_NORMAL,
CartService::ROUTE_VALID_ESTIMATE,
CartService::ROUTE_ADD_SAMPLE,
CartService::ROUTE_ADD_LINE,
];
const URL_NANE_SUBMIT = [
CartService::ROUTE_ADD_CATALOG,
CartService::ROUTE_ADD_ESTIMATE,
CartService::ROUTE_ADD_HYBRID,
CartService::ROUTE_ADD_REPEAT,
];
const CartErrorMessage = "front.cart_item_error%02d";
/**
* 「カートに入れる」フラグ - 商品をカートに追加しない
*/
const ADD_PRODUCTS_NONE = 0;
/**
* 「カートに入れる」フラグ - 商品を1つずつカートに追加する
*/
const ADD_PRODUCTS_EACH = 1;
/**
* 「カートに入れる」フラグ - 商品をまとめてカートに追加する
*/
const ADD_PRODUCTS_BULK = 2;
/**
* 「カートに入れる」フラグ - リピート注文
*/
const ADD_PRODUCTS_REPEAT = 3;
/**
* @var BaseInfo
*/
protected $baseInfo;
protected $LmHelper;
protected $CommonService;
protected $CatalogService;
protected $Validator;
protected $Products;
protected $Errors = [];
protected $ItemNum = 0;
protected $CartType;
protected $EstimateService;
protected $OrderConverter;
protected $session;
protected Twig $Twig;
/**
* @var EstimateCharacterizer
*/
private $EstimateCharacterizer;
/**
* @var GoodsService
*/
private $GoodsService;
/**
* @var LmMobileDetector
*/
private $mobileDetector;
/**
* @var SampleService
*/
private $SampleService;
/**
* CartController constructor.
*
* @param ProductClassRepository $productClassRepository
* @param CartService $cartService
* @param PurchaseFlow $cartPurchaseFlow
* @param BaseInfoRepository $baseInfoRepository
*/
public function __construct(
ProductClassRepository $productClassRepository,
CartService $cartService,
PurchaseFlow $cartPurchaseFlow,
BaseInfoRepository $baseInfoRepository,
CommonService $CommonService,
CatalogService $CatalogService,
ValidatorInterface $Validator,
EstimateService $EstimateService,
EstimateCharacterizer $EstimateCharacterizer,
OrderConverter $OrderConverter,
GoodsService $GoodsService,
LmMobileDetector $mobileDetector,
RecentGoodsService $RecentGoodsService,
SampleService $SampleService,
SessionInterface $session,
ContainerInterface $container,
Twig $Twig
)
{
//
parent::__construct($productClassRepository, $cartService, $cartPurchaseFlow, $baseInfoRepository);
//
$this->baseInfo = $baseInfoRepository->get();
$this->CommonService = $CommonService;
$this->CatalogService = $CatalogService;
$this->Validator = $Validator;
$this->EstimateService = $EstimateService;
$this->EstimateCharacterizer = $EstimateCharacterizer;
$this->OrderConverter = $OrderConverter;
$this->GoodsService = $GoodsService;
$this->mobileDetector = $mobileDetector;
$this->RecentGoodsService = $RecentGoodsService;
$this->SampleService = $SampleService;
$this->session = $session;
$this->Container = $container;
$this->Twig = $Twig;
//
self::__dataLayerTraitConstruct($CommonService);
}
/**
* カート画面.
*
* @Route("/cart/", name="cart", methods={"GET"})
* @Template("Cart/index.twig")
*/
public function index(Request $request)
{
if (!$this->session->get('referer')) {
if (($referer = $request->headers->get('referer')) && strpos($referer, "/cart") === false && strpos($referer, "/estimate") === false && strpos($referer, "/shopping") === false) {
$this->session->set('referer', $referer);
}
}
if (
$this->cartService->getCartType() == CartService::CartTypeCatalog
&& $request->get('from_url') != 'add_catalog'
&& $request->get('_route') !== CartService::ROUTE_ADD_CATALOG
&& empty($this->CommonService->GetLmOrderOption(CommonService::Lm_Option_Catalog))
) {
$this->RemoveCart('catalog',null,'return');
}
$isYoyaku = false;
//
$this->checkCartItemsAvailable();
//print_r( $_SESSION['data'] ?? []); unset( $_SESSION['data']);
// カートを取得して明細の正規化を実行
$Carts = $this->cartService->getCarts();
$this->execPurchaseFlow($Carts);
list($this->CartTypeId, $Products) = $this->cartService->MakeValidationData();
if ($this->CartTypeId != CartService::CartTypeSample) {
$this->AddCartValidation($Products,$this->cartService->GetCartType() ,false);
}
// TODO itemHolderから取得できるように
$least = [];
$isDeliveryFree = [];
$totalPrice = 0;
$ProductTotal =0;
$totalQuantity = $this->CommonService->calculateTotalQuantityForCarts($Carts);
$CatalogCartKey = null;
$EstimateOptions = [];
$EstimatetTotal = 0;
foreach ($Carts as $Cart) {
$isDeliveryFree[$Cart->getCartKey()] = false;
$OptionTotal = $this->cartService->GetEstimateOptionData($Cart->getCartItems(),'cart');
list($ETotal,$EstimateOptions[$Cart->getCartKey()]) = $this->EstimateCharacterizer->SetEstimateOption($Cart->getCartItems(),$OptionTotal);
$EstimatetTotal += $ETotal;
$ProductTotal += $Cart->getTotalPrice() + $EstimatetTotal;
if ($this->baseInfo->getDeliveryFreeAmount()) {
if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $ProductTotal) {
$isDeliveryFree[$Cart->getCartKey()] = true;
} else {
$least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $ProductTotal;
}
}
$CatalogCartKey = $Cart->getCartKey();
/**
* TODO: モジュール化
* 予約フラグ
*/
foreach ($Cart->getCartItems() as $item) {
//
$janId = $item->getProductClass()->getId();
//
if ($hoge = $this->GoodsService->getGoodsReservation(null, null, $janId)) {
//
$isYoyaku = true;
break;
}
}
}
$LargeDiscountRitu = $this->EstimateCharacterizer->SetLargeDiscount($ProductTotal);
$LargeDiscount = $this->EstimateCharacterizer->GetLargeDiscount();
// カートが分割された時のセッション情報を削除
$request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
list($CatalogDAta, $CatalogCategoryLabel) = $this->GetCatalogData();
switch ($this->cartService->getCartType()) {
case CartService::CartTypeCatalog:
$catalogOrderList = $this->CommonService->GetLmOrderOption(CommonService::Lm_Option_Catalog);
$totalQuantity = is_array($catalogOrderList) ? count($catalogOrderList) : 0;
$Title = 'front.cart_catalog.title';
$Twig = 'Cart/Catalog.twig';
break;
default:
$Title = 'front.cart.title';
$Twig = 'Cart/index.twig';
break;
}
$Title = trans($Title);
//LM仕様の商品表示順
$this->cartService->getLmCartItems();
// Get recent item
$cookies = $this->RecentGoodsService->getRecentView();
$recentviews = array();
if (!empty($cookies)) {
$recentviews = $this->RecentGoodsService->LM_getRecentViews2($cookies);
}
//
foreach ($this->cartService->getCarts() as $cart) {
foreach ($cart->getCartItems() as $cartItem) {
//
$id = $cartItem->getProductClass()->getProduct()->getId();
$quantity = $cartItem->getQuantity();
//
$this->dataLayer['ydn']['yahoo_retargeting_items'][] = $this->CommonService->get_yahoo_retargeting_item($id, $quantity);
$this->dataLayer['criteo']['item'][] = [
'id' => $id,
'price' => $cartItem->getPriceIncTax(),
'quantity' => $quantity,
];
}
}
// 在庫切れの商品が含まれていないかの確認用フラグ
$isItemsStockAvailable = $this->cartService->isItemsStockAvailable();
if ($request->get('from_url') == CartService::ROUTE_ADD_REPEAT) {
$listSusoageChange = [];
} else {
$listSusoageChange = $this->cartService->listSusoageChange();
}
//
return
$this->render($Twig, [
'totalPrice' => $ProductTotal - $LargeDiscount,
'totalQuantity' => $totalQuantity,
// 空のカートを削除し取得し直す
'Carts' => $this->cartService->getCarts(true),
'least' => $least,
'is_delivery_free' => $isDeliveryFree,
'title' => $Title,
'h1_comment' => "{$this->baseInfo->getShopName()}の{$Title}",
'CatalogData' => $CatalogDAta,
'CatalogCategoryLabel' => $CatalogCategoryLabel,
'CatalogCartKey' => $CatalogCartKey,
'SubWindoWData' => $this->CommonService->GetYaml('CatalogSubWindow.yaml'),
'EstimateOptions' => $EstimateOptions,
'EstimateTotla' => $EstimatetTotal,
'ProductTotal' => $ProductTotal,
'LargeDiscount' => $LargeDiscount,
'LargeDiscountRitu'=>$LargeDiscountRitu,
'BreadCrumbs' =>[],
'RepartData' =>$this->CommonService->GetLmOrderOption('repeat'),
'isYoyaku' => $isYoyaku,
'isMobile' => $this->mobileDetector->isMobile(),
'recentviews' => $recentviews,
'dataLayer' => $this->dataLayer,
'isShowGlobalFooter' => false,
'isItemsStockAvailable' => $isItemsStockAvailable,
'isSusoageChange' => count($listSusoageChange) > 0,
'listSusoageChange' => $listSusoageChange
]);
}
/**
* @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;
}
/**
* カタログのDataを返す
*
*
*/
protected function GetCatalogData()
{
if (CartService::CartTypeCatalog != $this->cartService->getCartType()) {
return [null, null, null];
}
$Catatogs = $this->CatalogService->GetCataLog();
$CatalogCategoryLabel = $this->CommonService->GetYaml('catalog_category.yaml');
return [$Catatogs, $CatalogCategoryLabel];
}
/**
* Check if current cart is type 3, 4 when repeat order
*
* @Route("/cart/check_mix_cart/", name="check_mix_cart", methods={"POST"} )
*/
public function CheckMixCart(Request $request)
{
$CurrentCartType = $this->cartService->GetCartType();
$showErrorModal = $CurrentCartType === CartService::CartTypeSample || $CurrentCartType === CartService::CartTypeCatalog;
if ($showErrorModal) {
$this->Errors[] = $this->CommonService->GetExclusionControl(
CartService::CartTypeNormal,
trans('front.ExclusionControl.repeat_mixed_cart_type_' . $CurrentCartType . '_warning')
);
return $this->json([
'status' => 'Error', 'Errors' => $this->Errors, 'show_error_modal' => $showErrorModal
]);
} else {
return $this->json([
'status' => 'ok', 'Errors' => '', 'show_error_modal' => $showErrorModal
]);
}
}
/**
* カートに商品を追加・変更する
*
* @Route("/cart/add_Normal", name=CartService::ROUTE_ADD_NORMAL, methods={"GET","POST"} )
* @Route("/cart/valid_estimate", name=CartService::ROUTE_VALID_ESTIMATE, methods={"GET","POST"} )
* @Route("/cart/add_estimate", name=CartService::ROUTE_ADD_ESTIMATE, methods={"GET","POST"} )
* @Route("/cart/add_sample", name=CartService::ROUTE_ADD_SAMPLE, methods={"GET","POST"} )
* @Route("/cart/add_catalog", name=CartService::ROUTE_ADD_CATALOG, methods={"GET","POST"} )
* @Route("/cart/add_line", name=CartService::ROUTE_ADD_LINE, methods={"GET","POST"} )
* @Route("/cart/add_hybrid", name=CartService::ROUTE_ADD_HYBRID, methods={"GET","POST"} )
* @Route("/cart/add_repeat", name=CartService::ROUTE_ADD_REPEAT, methods={"GET","POST"} )
*/
public function AddCart(Request $request)
{
$carts = $this->cartService->getCarts();
$UrlName = $request->get('_route');
//
$goodsId = $request->get('goodsId');
$CartType = $this->cartService->GetCartType();
$ExclusionControl = null;
$showErrorModal = false;
if ($Products = $this->cartService->CartItemConv($request->get('product_matrix'))) {
// セット品番対応
$Products = $this->cartService->convertProductsForSetPurchase($Products);
// 排他チェック
if (($checkMixCart = $this->cartService->checkMixCart($UrlName, array_keys($Products))) !== true) {
$showErrorModal = true;
$messageId = "front.ExclusionControl.mixed_cart_type_{$checkMixCart[0]}_add_{$checkMixCart[1]}_warning";
$messageId.= isset($checkMixCart[2]) ? "_{$checkMixCart[2]}" : '';
$messageId.= isset($checkMixCart[3]) ? "_{$checkMixCart[3]}" : '';
$this->Errors[] = $this->CommonService->GetExclusionControl(
CartService::CartTypeNormal,
trans($messageId)
);
}
}
/* 一旦トークンを外す 2022/11/26
if ('add_catalog' != $UrlName) {
if ($this->CommonService->GetToken(CommonService::Matrix_Token) != $request->get('OlToken')) {
if(in_array($UrlName,self::URL_NANE_SUBMIT)) {
throw new NotFoundHttpException();
}else{
// $Token = $this->CommonService->ResetToken(CommonService::Matrix_Token);
return $this->json(['status' => 'Error', 'Error' =>''],400);
}
}
}
*/
#排他制御解除 カタログ
if(CartService::CartTypeCatalog == $this->cartService->GetCartType()){
if(!$this->CommonService->GetLmOrderOption('catalog')){
$this->RemoveCart('catalog',null,'return');
}
}
#OrderOption 初期化
if(!$this->cartService->GetCartType()){
$this->CommonService->InitializeLmOrderOption();
}
$Errors = [];
$AddProductsFlg = self::ADD_PRODUCTS_EACH; //2 = オリジナル カートに追加を一気におこなう
//
$MaxEstimateId= $this->cartService->getMaxEstimateId();
switch ($UrlName) {
case CartService::ROUTE_ADD_REPEAT:
if(!$LmOrderId = $request->get('order_id')){
$ExclusionControl = CartService::RepeatError01;
break;
}
if(!$Datas = $this->OrderConverter->GetCartFromLmOrderId($LmOrderId)){
$ExclusionControl = CartService::RepeatError01;
break;
}
// 非表示商品のチェック
if (!LmHelper::isSecret()) {
foreach ($Datas['orderList'] as $index => $order) {
if (($goods = new Goods($order['goodsId'])) && $goods->getGoodsStatus() === Goods::GOODS_STATUS_UNAVAIABLE) {
//
unset($Datas['orderList'][$index]);
//
$this->addRequestError('現在、ご購入頂けない商品が含まれていましたのでカートから削除しました。', "front.cart");
}
}
$Datas['orderList'] = array_values($Datas['orderList']);
}
/**
* TODO: Revert me.
* @var Customer $user
* @var int|null $LmOrderId
*/
function _log_20230414_03(Customer $user, $LmOrderId) {
$lmCustomerId = '';
if (!empty($user)) {
$lmCustomerId = $user->getLmCustomerId();
}
log_info("[LM]/cart/add_repeat/ - \{ \$lmCustoerId: {$lmCustomerId}, \$lmOrderId: {$LmOrderId} \}");
}
_log_20230414_03($this->CommonService->getUser(), $LmOrderId);
$ItemRepeatCartType = $this->RepeatCartType($Datas['orderList']);
$CurrentCartType = $this->cartService->GetCartType();
$filterRepeatOrderTypeEstimate = array_filter($Datas['orderList'], function ($item) {
return !empty($item['Options']);
});
if ($CurrentCartType == CartService::CartTypeSample || $CurrentCartType == CartService::CartTypeCatalog) {
$ExclusionControl = CartService::RepeatError03;
break;
}
$CartType = ($ItemRepeatCartType == CartService::CartTypeEstimate ||
$CurrentCartType == CartService::CartTypeEstimate) ?
CartService::CartTypeEstimate :
CartService::CartTypeNormal;
$AddProductsFlg = self::ADD_PRODUCTS_REPEAT;
#カートタイプの登録
$this->cartService->SetCartType($CartType);
$this->CommonService->AddLmOrderOption('repeat',['ohid'=>$Datas['ohId']]);
break;
case CartService::ROUTE_ADD_LINE:
$AddProductsFlg = self::ADD_PRODUCTS_BULK;
if ($Data = $request->get('CartItem')) {
list($Products, $Errors) = $this->cartService->AddCartLine($Data);
if (count($Errors) > 0) {
foreach ($Errors as $Id => $ErrorId) {
$this->SetCartError($ErrorId, $Id);
}
}
if ($CartType == CartService::CartTypeSample) {
$this->SetSampleItemMax($Products, false);
}
$this->AddCartValidation($Products,$this->cartService->GetCartType() ,false);
} else {
$this->SetCartError(12);
}
break;
case CartService::ROUTE_ADD_CATALOG:
$layoutId = $this->mobileDetector->isMobile() ? 30 : 29;
$em = $this->Container->get('doctrine.orm.entity_manager');
$Layout = $em->getRepository(Layout::class)->find($layoutId);
$this->Twig->addGlobal('Layout', $Layout);
if ($this->cartService->getCartType()) {
if (CartService::CartTypeCatalog != $this->cartService->getCartType()) {
$ExclusionControl = CartService::CartTypeCatalog;
break;
}
}
// 一旦 全てのカート商品を削除する
$this->cartService->clear();
#カートタイプの設定
$this->cartService->SetCartType(CartService::CartTypeCatalog);
$this->Products[$this->CommonService->GetConfig('CatalogProdctClassId')] = 1;
break;
case CartService::ROUTE_ADD_SAMPLE:
if ($this->cartService->getCartType()) {
if (CartService::CartTypeSample != $this->cartService->getCartType()) {
$cartType = $this->cartService->getCartType();
$showErrorModal = true;
$this->Errors[] = $this->CommonService->GetExclusionControl(
CartService::CartTypeNormal,
trans('front.ExclusionControl.mixed_cart_type_' . $cartType . '_add_' . CartService::CartTypeSample . '_warning')
);
break;
}
}
#カートタイプの設定
$this->cartService->SetCartType(CartService::CartTypeSample);
$this->AddCartValidation($Products,CartService::CartTypeSample);
$this->SetSampleItemMax($Products);
break;
case CartService::ROUTE_VALID_ESTIMATE:
if ($this->cartService->getCartType()) {
if (CartService::CartTypeSample <= $this->cartService->getCartType()) {
$cartType = $this->cartService->getCartType();
$showErrorModal = true;
$this->Errors[] = $this->CommonService->GetExclusionControl(
CartService::CartTypeNormal,
trans('front.ExclusionControl.mixed_cart_type_' . $cartType . '_add_' . CartService::CartTypeEstimate . '_warning')
);
break;
}
}
$AddProductsFlg = self::ADD_PRODUCTS_NONE; #登録を行わない
$this->AddCartValidation($Products,$this->cartService->getCartType());
break;
case CartService::ROUTE_ADD_ESTIMATE:
if ($this->cartService->getCartType()) {
if (CartService::CartTypeSample <= $this->cartService->getCartType()) {
$ExclusionControl = CartService::CartTypeEstimate;
break;
}
}
$this->cartService->SetCartType(CartService::CartTypeEstimate);
$this->cartService->SetEstimates($request->get('estimate'));
$this->AddCartValidation($Products,$this->cartService->getCartType());
break;
case CartService::ROUTE_ADD_HYBRID:
if ($this->cartService->getCartType()) {
if (CartService::CartTypeSample <= $this->cartService->getCartType()) {
$ExclusionControl = CartService::CartTypeEstimate;
break;
}
}
$AddProductsFlg = self::ADD_PRODUCTS_NONE;
$Hybrid = $request->get('Hybrid');
if ($CasrtItemIds = $Hybrid['cart_item_ids'] ?? null) {
$this->cartService->SetCartType(CartService::CartTypeEstimate);
$this->cartService->SetEstimates($request->get('estimate'));
$this->cartService->setPreOrderId(null);
$this->cartService->SetHybrid($CasrtItemIds);
}
break;
case CartService::ROUTE_ADD_NORMAL:
default:
if ($this->cartService->getCartType()) {
if (CartService::CartTypeSample <= $this->cartService->getCartType()) {
$cartType = $this->cartService->getCartType();
$showErrorModal = true;
$this->Errors[] = $this->CommonService->GetExclusionControl(
CartService::CartTypeNormal,
trans('front.ExclusionControl.mixed_cart_type_' . $cartType . '_add_' . CartService::CartTypeNormal . '_warning')
);
break;
}
}
#カートタイプの設定
if ($this->cartService->getCartType() == CartService::CartTypeEstimate) {
$this->cartService->SetCartType(CartService::CartTypeComposite);
} else {
$this->cartService->SetCartType(CartService::CartTypeNormal);
}
//
$cartItemIds = [];
$cartItems = $this->cartService->getAllCartsItems();
if ($cartItems) {
foreach ($cartItems as $cartItem) {
$cartItemIds[] = $cartItem->getProductClass()->getId();
}
}
if (!empty($goodsId)) {
$goods = new GoodsWithRelated($goodsId);
if ($goods->isGoodsSetPurchase()) {
$productKeys = array_keys($Products);
$allKeysExist = true;
foreach ($productKeys as $key) {
if (!in_array($key, $cartItemIds)) {
$allKeysExist = false;
break;
}
}
if (!$allKeysExist) {
$MaxEstimateId++;
}
$this->cartService->SetEstimateId($MaxEstimateId);
}
}
$this->AddCartValidation($Products, CartService::CartTypeNormal);
break;
}
/** 排他モード */
if ($ExclusionControl) {
$this->session->set(CartService::Session_ExclusionControlFlg, $ExclusionControl);
if(in_array($UrlName,self::URL_NANE_SUBMIT)) {
return $this->redirectToRoute('cart');
}else{
return $this->json(['status' => 'Error', 'Error' =>'排他制御エラーカートにリダイレクトしてください。'],400);
}
}
//$this->Errors[] = ['errid' => 1, 'message' => $AddProductsFlg ];
#エラーがある
if (count($this->Errors) > 0) {
$Token = $this->CommonService->ResetToken(CommonService::Matrix_Token);
return $this->json([
'status' => 'Error', 'OlToken' => $Token, 'Errors' => $this->Errors, 'show_error_modal' => $showErrorModal
]);
}
try {
log_info("----AddProductsFlg: ". $AddProductsFlg . " Cart: ", [
"CartType" => $this->cartService->GetCartType(),
"request" => $request->request->all()
]);
} catch (\Exception $exception) {
log_error("cart_error:AddProductsFlg " . $exception->getMessage());
}
# EC-CUBE のデフォルトでは iSKU ごとの登録ですが 一挙に登録します
switch ($AddProductsFlg) {
case self::ADD_PRODUCTS_REPEAT:
foreach ($Datas['orderList'] as $Data) {
#見積もりシミュレーションの初期化
$this->cartService->InitiarizeEstimate();
$this->SetProduct($Data['Products']);
if (count($Data['Options']) > 0) {
$Options = $Data['Options'][0] ?? $Data['Options'];
$Options['repeat'] = $Datas['ohId'];
$Options['product_class_id'] = array_key_first($this->Products);
$this->cartService->SetEstimates($Options);
}
$MaxEstimateId++;
$this->cartService->SetEstimateId($MaxEstimateId);
$this->cartService->AddCartProduct($this->Products);
$this->cartService->UpRepeatEstimateOption();
$this->handleDispathEventAddProductToCart($Data['Products'], $Data['goodsId']);
}
break;
case self::ADD_PRODUCTS_BULK:
$this->cartService->AddProducts();
$this->cartService->save();
$this->cartService->UpEstimateOption();
break;
case self::ADD_PRODUCTS_EACH;
#一つづつカートへ追加
$this->cartService->AddCartProduct($this->Products);
/*foreach ($this->Products as $ClassId => $Quantity) {
if (!$Quantity) {
continue;
}
$ProductClass = $this->cartService->GetProductClass($ClassId) ?? $ClassId;
$this->cartService->addProduct($ProductClass, $Quantity);
}
$this->cartService->save();*/
break;
}
$this->session->set(LmEvents::SESSION_FRONT_PRODUCT_CART, true);
// use screen detail block matrix
if (!empty($goodsId)) {
$this->handleDispathEventAddProductToCart($Products, $goodsId);
}
//
if ($returnUrl = $request->get('returnUrl')) {
$this->session->set('referer', $returnUrl);
}
if ($UrlName === CartService::ROUTE_ADD_CATALOG) {
return $this->index($request);
} else if(in_array($UrlName,self::URL_NANE_SUBMIT)) {
return $this->redirectToRoute('cart', ['from_url' => $UrlName]);
}
$Token = $this->CommonService->ResetToken(CommonService::Matrix_Token);
return $this->json(['status' => 'OK', 'data' => $Products, 'OlToken' => $Token]);
}
/**
* カートを削除する
*
* @Route("/cart/remove/{mode}/{Token}/{id}", name="remove_cart_item", methods={"GET"}, requirements={"mode" = "[a-z]+","Token" = "\w+","id" = "\d+" })
*/
public function RemoveCart($mode = null, $Token = null, $id = null)
{
if (is_null($mode)) {
throw new NotFoundHttpException();
}
if (!$mode == 'all') {
if ($this->CommonService->GetToken(CommonService::RemoveCartItme) != $Token) {
throw new NotFoundHttpException();
}
$this->CommonService->RemoveToken(CommonService::RemoveCartItme);
}
$Url = 'homepage';
switch ($mode) {
case 'item':
$cart = $this->cartService->getCart();
if (!empty($cart)) {
foreach($cart->getItems() as $item ) {
if ($item->getId() == $id) {
$productId = $item->getProductClass()->getProduct()->getId();
$janId= $item->getProductClass()->getId();
$event = new EventArgs([
'deleted_item_id' => $productId,
'deleted_item_sku_id' => $janId
]);
$this->eventDispatcher->dispatch($event,LmEvents::SESSION_FRONT_PRODUCT_CART_DELETE_PRODUCT );
$this->session->set(LmEvents::SESSION_FRONT_PRODUCT_CART, true);
}
}
}
$this->cartService
->RemoveItem($id) # $Param = CartItem ItemId
->UpEstimateOption()
;
$Url = 'cart';
break;
case 'all':
$Url = 'cart';
case 'catalog':
//全てのカート商品を削除する
$this->cartService->clear();
//LmOrderOption の削除
$this->CommonService->InitializeLmOrderOption();
if ($id=='return'){
return [];
}
break;
}
return $this->redirectToRoute($Url);
}
/**
* カートをロック状態に設定し、購入確認画面へ遷移する.
*
* @Route("/cart/buystep/{cart_key}", name="cart_buystep", requirements={"cart_key" = "[a-zA-Z0-9]+[_][\x20-\x7E]+"}, methods={"POST","GET"})
*/
public function buystep(Request $request, $cart_key)
{
$Carts = $this->cartService->getCart();
if (!is_object($Carts)) {
return $this->redirectToRoute('cart');
}
// FRONT_CART_BUYSTEP_INITIALIZE
$event = new EventArgs(
[],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE );
#202203/31 カタログを追加する
if (CartService::CartTypeCatalog == $Carts->getCartType()) {
// CSRFトークンの検査
if (empty($token = $request->get('OlToken')) || ($token !== $this->CommonService->GetToken('catalog'))) {
//
throw new AccessDeniedHttpException('[LM]CSRF token is invalid.');
}
//
$this->CommonService->RequestLmOrderOption();
$options = $this->CommonService->GetLmOrderOption();
if (empty($options)) {
return $this->redirectToRoute('cart', ['from_url' => 'add_catalog']);
}
}
$this->cartService->SetCartType($Carts->getCartType());
$this->cartService->setPrimary($cart_key);
$this->cartService->save();
// FRONT_CART_BUYSTEP_COMPLETE
$event = new EventArgs(
[],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_CART_BUYSTEP_COMPLETE);
if ($event->hasResponse()) {
return $event->getResponse();
}
return $this->redirectToRoute($request->get('next_step', 'shopping'));
}
/**
* ポップアップ詳細見出し
* /catalog/detail/{id}
* ポップアップ詳細見出し catalog_detail_headline
*
* @Route("/catalog/detail/{id}/", name="catalog_ditail", methods={"GET"},requirements={"id" = "\d+"}))
* @Template("Cart/CatalogDetail.twig")
*/
public function CatalogDitail(Request $request, $id = null)
{
$Data = $this->CatalogService->GetCatalog(['id' => $id]);
if($Data && isset($Data['catalog_detail_uploaded_image_list'])){
$Data['image_lists'] = json_decode($Data['catalog_detail_uploaded_image_list'], true);
}else{
$Data['image_lists'] = null;
}
return [
'Data' => $Data,
'SubWindoWData' => $this->CommonService->GetYaml('CatalogSubWindow.yaml'),
];
}
/**
* エラーを返す
* 1 X個以上
* 2 既にカートにある
* 3 在庫なし
* 4 数字以外
* 5 商品が削除されている
* 6 サンプルは1個までです
* 7 サンプルカートにある
* 8 個数を入れてくださお
* 0 11 サンプルMAX
* 0 12 数量が入っていない
* 0 13 DATAが確認できないDATAあります
* 0 14 変更するDATAがありません。
*/
public function AddCartValidation($Products, $CartType ,$Flg = true)
{
if (!is_array($Products)) {
return $this->SetCartError(14);
}
if (count($Products) < 1) {
return $this->SetCartError(14);
}
$Limit = $CartType == CartService::CartTypeSample ? $this->CommonService->GetConfig('SampleLimit') : null;
#オブジェクトからエラーIDを取得する
$SetError = function ($ClassId, $Error) {
if ($Error->count() < 1) {
return null;
}
return $Error[0]->getMessage();
};
// 入力チェック
foreach ($Products as $ClassId => $Quantity) {
$this->ItemNum++;
$this->Products[$ClassId] = $Quantity;
if (!$ProductClass = $this->cartService->GetProductClass($ClassId)) {
$this->SetCartError(5);
} else {
$ClassCategory1 = $ProductClass->getClassCategory1();
if ($ClassCategory1 && !$ClassCategory1->isVisible()) {
$this->SetCartError(5);
} else {
$ClassCategory2 = $ProductClass->getClassCategory2();
if ($ClassCategory2 && !$ClassCategory2->isVisible()) {
$this->SetCartError(5);;
}
}
}//Classの検証
if ($ErrId = $SetError($ClassId, $this->Validator->validate(
$Quantity,
[
new Assert\Quantity(['ClassId' => $ClassId,
'Limit' => $Limit,
'StockLimit' => $this->CommonService->GetConfig('Stocklimit'),
'Flg' => $Flg,
'CartType' => $CartType,
])
]
))
) {
$this->SetCartError($ErrId, $ClassId, $ProductClass, $Flg);
}//ヴァり
}
return;
}
/**
* @param int error id
* @param int product_class_id
*
* @return string ErrorMessage
*/
protected function SetCartError($ErrId, $ClassId = 0, $Class = null, $Flg = false, $MessageParams = [])
{
$ClassName = '';
if ($Flg) {
$Name1 = '';
$Name2 = '';
if ($Class) {
if ($Classcategory1 = $Class->getClassCategory1()){
$Name1 = $Classcategory1->getName();
}
if ($Classcategory2 = $Class->getClassCategory2()){
$Name2 = $Classcategory2->getName();
}
$ClassName = $Name1 . ':' . $Name2 . ' ';
}
}
$Msg = sprintf(self::CartErrorMessage, $ErrId);
$Msg = trans($Msg, $MessageParams);
$Msg = $this->CommonService->BaseInfo($Msg);
$Msg = $ClassName . $Msg;
switch ($ErrId) {
case 5 :
$Msg .= ' ClassId=' . $ClassId;
break;
}
$this->Errors[] = ['errid' => $ErrId, 'message' => $Msg, 'class_id' => $ClassId, 'add_lines' => $this->cartService->getAddlines($ClassId)];
}
protected function SetProduct($Products){
$this->Products = null;
foreach ($Products as $Product){
$this->Products[$Product['product_class_id']] = $Product['quantity'];
}
}
protected function RepeatCartType($Datas){
$CartType = CartService::CartTypeNormal;
foreach ($Datas as $i=> $Data){
if(count($Data['Options'])>0){
$CartType = CartService::CartTypeEstimate;
}
}
return $CartType;
}
protected function SetSampleItemMax($Products , $Flg = true)
{
$CartItemNum = 0;
if($Flg){
foreach ($this->cartService->getCarts() as $Cart) {
$CartItemNum += count($Cart->getCartItems());
}
}
$sampleLimit = $this->SampleService->getSampleLimit();
if (!$sampleLimit) {
return true;
}
if ($sampleLimit['sl_quantity_limit'] < ($CartItemNum + count($Products))) {
return $this->SetCartError(15, 0, null, false, ['%sl_quantity_limit%' => $sampleLimit['sl_quantity_limit']]);
}
if (!$Customer = $this->CommonService->getUser()) {
return true;
}
if ($this->SampleService->getOrderCountAfterPurchase($Customer->getLmCustomerId()) >= $sampleLimit['sl_no_purchase_limit']) {
return $this->SetCartError(16, 0, null, false, ['%sl_no_purchase_limit%' => $sampleLimit['sl_no_purchase_limit']]);
}
if ($sampleLimit['sl_number_limit'] == 0) {
return $this->SetCartError(17);
}
if ($this->SampleService->getOrderCountOfToday($Customer->getLmCustomerId()) >= $sampleLimit['sl_number_limit']) {
return $this->SetCartError(18, 0, null, false, ['%sl_number_limit%' => $sampleLimit['sl_number_limit']]);
}
}
protected function hasExitedGoodsSusoageOnCurrentCart()
{
$existSusoage = false;
foreach ($this->cartService->getCarts() as $Cart) {
foreach ($Cart->getCartItems() as $CartItem) {
$ProductCode = $CartItem->getProductClass()->getCode();
$GoodsSusoage = $this->GoodsService->getGoodsSusoageByHinban($ProductCode);
if ($GoodsSusoage == 1) {
$existSusoage = true;
break;
}
}
if ($existSusoage) {
break;
}
}
return $existSusoage;
}
protected function hasExitedGoodsSusoageOnRepeatItems(array $orderList)
{
$existSusoage = false;
foreach ($orderList as $item) {
$GoodsSusoage = $this->GoodsService->getGoodsSusoageById($item['goodsId']);
if ($GoodsSusoage == 1) {
$existSusoage = true;
break;
}
}
return $existSusoage;
}
/***
* Function use to dispath event Add product to Cart
*
* @param array $products
* @param int|null $goodsId
* @return void
*/
private function handleDispathEventAddProductToCart(Array $products, ?int $goodsId)
{
$addedItemSkuId = implode(',', array_keys($products));
$event = new EventArgs([
'added_item_id' => $goodsId,
'added_item_sku_id' => $addedItemSkuId
]);
$this->eventDispatcher->dispatch($event,LmEvents::SESSION_FRONT_PRODUCT_CART_ADD_PRODUCT );
}
/**
* #Route("/cart/remove_cart_items", methods={"DELETE"} )
*/
public function removeCartItems(Request $request)
{
$cartItems = $request->get('cartItems', []);
if (!empty($cartItems)) {
$this->cartService->removeCartItems($cartItems);
return $this->json(['status' => 'OK']);
}
return $this->json(['status' => 'Error']);
}
/**
* @return void
* @throws \Exception
*/
public function checkCartItemsAvailable()
{
//
$cartItemIdsToBeRemoved = [];
//
foreach ($this->cartService->getCarts() as $Cart) {
//
foreach ($Cart->getCartItems() as $CartItem) {
/**
* @var SkuExtended $sku
*/
$jancode = new Jancode($CartItem->getProductClass()->getId());
$sku = SkuExtended::getInstance($jancode->getJanGoods(), $jancode->getJanId());
//
if ($sku->isNoDisplay() || $sku->getGclDisplayStatus() === GoodsColor::DISPLAY_STATUS_UNAVAILABLE || $sku->getGpDisplay() === GoodsPrice::DISPLAY_HIDDEN) {
//
$cartItemIdsToBeRemoved[] = $CartItem->getId();
}
}
}
//
if (!empty($cartItemIdsToBeRemoved)) {
$this->cartService->removeCartItems($cartItemIdsToBeRemoved);
$this->addRequestError('現在、ご購入頂けない商品が含まれていましたのでカートから削除されました。', "front.cart");
}
}
}