<?php
/*
* Plugin Name : ProductOption
*
* Copyright (C) BraTech Co., Ltd. All Rights Reserved.
* http://www.bratech.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Plugin\ProductOption42\Event;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\Master\OrderItemType;
use Eccube\Entity\OrderItem;
use Eccube\Entity\Shipping;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Event\TemplateEvent;
use Eccube\Form\Type\ShippingMultipleType;
use Eccube\Repository\Master\OrderItemTypeRepository;
use Plugin\ProductOption42\Entity\OrderItemOption;
use Plugin\ProductOption42\Entity\OrderItemOptionCategory;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class ShoppingEvent implements EventSubscriberInterface
{
private $entityManager;
private $orderItemTypeRepository;
public function __construct(
EntityManagerInterface $entityManager,
OrderItemTypeRepository $orderItemTypeRepository
)
{
$this->entityManager = $entityManager;
$this->orderItemTypeRepository = $orderItemTypeRepository;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
'Shopping/index.twig' => 'onTempleteShoppingIndex',
'Shopping/confirm.twig' => 'onTempleteShoppingIndex',
'Shopping/shipping_multiple.twig' => 'onTempleteShoppingShippingMultiple',
EccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_INITIALIZE => 'onHookShoppingShippingMultipleInitialize',
EccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_COMPLETE => 'onHookShoppingShippingMultipleComplete',
];
}
public function onTempleteShoppingIndex(TemplateEvent $event)
{
$source = $event->getSource();
if(preg_match("/\<p\>\{\{\sorderItem\.priceIncTax\|price\s\}\}/",$source, $result)){
$search = $result[0];
$replace = "{{ include('@ProductOption42/default/Shopping/orderitem_option.twig') }}" . $search;
$source = str_replace($search, $replace, $source);
}
$event->setSource($source);
}
public function onTempleteShoppingShippingMultiple(TemplateEvent $event)
{
$source = $event->getSource();
if(preg_match("/\{\%\sif\sorderItem\.productClass\.id\s\=\=\skey\s\%\}/",$source, $result)){
$search = $result[0];
$replace = "{% if orderItem.productClass.id ~ '_' ~ orderItem.option_serial == key %}";
$source = str_replace($search, $replace, $source);
}
if(preg_match("/\<div\sclass\=\"ec\-AddAddress\_\_itemtPrice\"\>/",$source, $result)){
$search = $result[0];
$replace = $search . "{{ include('@ProductOption42/default/Shopping/shipping_multiple_option.twig') }}";
$source = str_replace($search, $replace, $source);
}
$event->setSource($source);
$parameters = $event->getParameters();
$OrderItems = $parameters['OrderItems'];
$OrderItemsForFormBuilder = [];
$ItemQuantitiesByOption = [];
$tmpIds = [];
$Order = $OrderItems[0]->getOrder();
foreach($Order->getProductOrderItems() as $OrderItem){
$quantity = $OrderItem->getQuantity();
$itemId = $OrderItem->getProductClass()->getId();
$serial = $OrderItem->getOptionSerial();
$key = $itemId .'_'. $serial;
if (!in_array($key, $tmpIds)) {
$OrderItemsForFormBuilder[] = $OrderItem;
$tmpIds[] = $key;
$ItemQuantitiesByOption[$key] = $quantity;
}else{
$ItemQuantitiesByOption[$key] += $quantity;
}
}
$parameters['OrderItems'] = $OrderItemsForFormBuilder;
$parameters['compItemQuantities'] = $ItemQuantitiesByOption;
$event->setParameters($parameters);
}
public function onHookShoppingShippingMultipleInitialize(EventArgs $event)
{
$builder = $event->getArgument('builder');
$Order = $event->getArgument('Order');
$OrderItemsForFormBuilder = [];
$tmpIds = [];
foreach($Order->getProductOrderItems() as $OrderItem){
$itemId = $OrderItem->getProductClass()->getId();
$serial = $OrderItem->getOptionSerial();
$key = $itemId .'_'. $serial;
if (!in_array($key, $tmpIds)) {
$OrderItemsForFormBuilder[] = $OrderItem;
$tmpIds[] = $key;
}
}
$builder->remove('shipping_multiple');
$builder
->add('shipping_multiple', CollectionType::class, [
'entry_type' => ShippingMultipleType::class,
'data' => $OrderItemsForFormBuilder,
'allow_add' => true,
'allow_delete' => true,
]);
}
public function onHookShoppingShippingMultipleComplete(EventArgs $event)
{
$form = $event->getArgument('form');
$Order = $event->getArgument('Order');
if ($form->isSubmitted() && $form->isValid()) {
$data = $form['shipping_multiple'];
// フォームの入力から、送り先ごとに商品の数量を集計する
$arrOrderItemTemp = [];
foreach ($data as $multiples) {
$OrderItem = $multiples->getData();
foreach ($multiples as $items) {
foreach ($items as $item) {
$CustomerAddress = $item['customer_address']->getData();
$customerAddressName = $CustomerAddress->getShippingMultipleDefaultName();
$itemId = $OrderItem->getProductClass()->getId() . '_' . $OrderItem->getOptionSerial();
$quantity = $item['quantity']->getData();
if (isset($arrOrderItemTemp[$customerAddressName]) && array_key_exists($itemId, $arrOrderItemTemp[$customerAddressName])) {
$arrOrderItemTemp[$customerAddressName][$itemId] = $arrOrderItemTemp[$customerAddressName][$itemId] + $quantity;
} else {
$arrOrderItemTemp[$customerAddressName][$itemId] = $quantity;
}
}
}
}
// -- ここから先がお届け先を再生成する処理 --
// お届け先情報をすべて削除
/** @var Shipping $Shipping */
foreach ($Order->getShippings() as $Shipping) {
foreach ($Shipping->getOrderItems() as $OrderItem) {
$Shipping->removeOrderItem($OrderItem);
$Order->removeOrderItem($OrderItem);
$this->entityManager->remove($OrderItem);
}
$Order->removeShipping($Shipping);
$this->entityManager->remove($Shipping);
}
// お届け先のリストを作成する
$ShippingList = [];
foreach ($data as $multiples) {
$OrderItem = $multiples->getData();
$ProductClass = $OrderItem->getProductClass();
$Delivery = $OrderItem->getShipping()->getDelivery();
$saleTypeId = $ProductClass->getSaleType()->getId();
foreach ($multiples as $items) {
foreach ($items as $item) {
$CustomerAddress = $item['customer_address']->getData();
$customerAddressName = $CustomerAddress->getShippingMultipleDefaultName();
if (isset($ShippingList[$customerAddressName][$saleTypeId])) {
continue;
}
$Shipping = new Shipping();
$Shipping
->setOrder($Order)
->setFromCustomerAddress($CustomerAddress)
->setDelivery($Delivery);
$Order->addShipping($Shipping);
$ShippingList[$customerAddressName][$saleTypeId] = $Shipping;
}
}
}
// お届け先のリストを保存
foreach ($ShippingList as $ShippingListByAddress) {
foreach ($ShippingListByAddress as $Shipping) {
$this->entityManager->persist($Shipping);
}
}
$ProductOrderType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);
// お届け先に、配送商品の情報(OrderItem)を関連付ける
foreach ($data as $multiples) {
/** @var OrderItem $OrderItem */
$OrderItem = $multiples->getData();
$ProductClass = $OrderItem->getProductClass();
$Product = $OrderItem->getProduct();
$saleTypeId = $ProductClass->getSaleType()->getId();
$itemId = $OrderItem->getProductClass()->getId() . '_' . $OrderItem->getOptionSerial();
$optionSerial = $OrderItem->getOptionSerial();
$OrderItemOptions = $OrderItem->getOrderItemOptions();
$optionPrice = $OrderItem->getOptionPrice();
$optionTax = $OrderItem->getOptionTax();
foreach ($multiples as $items) {
foreach ($items as $item) {
$CustomerAddress = $item['customer_address']->getData();
$customerAddressName = $CustomerAddress->getShippingMultipleDefaultName();
// お届け先から商品の数量を取得
$quantity = 0;
if (isset($arrOrderItemTemp[$customerAddressName]) && array_key_exists($itemId, $arrOrderItemTemp[$customerAddressName])) {
$quantity = $arrOrderItemTemp[$customerAddressName][$itemId];
unset($arrOrderItemTemp[$customerAddressName][$itemId]);
} else {
// この配送先には送る商品がないのでスキップ(通常ありえない)
continue;
}
// 関連付けるお届け先のインスタンスを取得
$Shipping = $ShippingList[$customerAddressName][$saleTypeId];
// インスタンスを生成して保存
$OrderItem = new OrderItem();
$OrderItem->setShipping($Shipping)
->setOrder($Order)
->setProductClass($ProductClass)
->setProduct($Product)
->setProductName($Product->getName())
->setProductCode($ProductClass->getCode())
->setPrice($ProductClass->getPrice02())
->setQuantity($quantity)
->setOrderItemType($ProductOrderType)
->setOptionSerial($optionSerial);
$ClassCategory1 = $ProductClass->getClassCategory1();
if (!is_null($ClassCategory1)) {
$OrderItem->setClasscategoryName1($ClassCategory1->getName());
$OrderItem->setClassName1($ClassCategory1->getClassName()->getName());
}
$ClassCategory2 = $ProductClass->getClassCategory2();
if (!is_null($ClassCategory2)) {
$OrderItem->setClasscategoryName2($ClassCategory2->getName());
$OrderItem->setClassName2($ClassCategory2->getClassName()->getName());
}
foreach($OrderItemOptions as $OrderItemOption){
$newOrderItemOption = new OrderItemOption();
$newOrderItemOption->setOptionId($OrderItemOption->getOptionId())
->setOrderItem($OrderItem)
->setLabel($OrderItemOption->getLabel())
->setSortNo($OrderItemOption->getSortNo());
foreach($OrderItemOption->getOrderItemOptionCategories() as $OrderItemOptionCategory){
$newOrderItemOptionCategory = new OrderItemOptionCategory();
$newOrderItemOptionCategory->setOptionCategoryId($OrderItemOptionCategory->getOptionCategoryId())
->setOrderItemOption($newOrderItemOption)
->setValue($OrderItemOptionCategory->getValue())
->setPrice($OrderItemOptionCategory->getPrice())
->setTax($OrderItemOptionCategory->getTax())
->setDeliveryFreeFlg($OrderItemOptionCategory->getDeliveryFreeFlg())
->setSortNo($OrderItemOptionCategory->getSortNo());
$newOrderItemOption->addOrderItemOptionCategory($newOrderItemOptionCategory);
}
$OrderItem->addOrderItemOption($newOrderItemOption);
}
$OrderItem->setPrice($OrderItem->getPrice() + $optionPrice);
$OrderItem->setTax($OrderItem->getTax() + $optionTax);
$OrderItem->setOptionSetFlg(true);
$Shipping->addOrderItem($OrderItem);
$Order->addOrderItem($OrderItem);
$this->entityManager->persist($OrderItem);
}
}
}
$this->entityManager->flush();
}
}
}