<?php
namespace Plugin\ProductPlus42\Event;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Common\EccubeConfig;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Event\TemplateEvent;
use Eccube\Repository\CustomerRepository;
use Plugin\ProductPlus42\Entity\ProductData;
use Plugin\ProductPlus42\Entity\ProductDataDetail;
use Plugin\ProductPlus42\Entity\ProductItem;
use Plugin\ProductPlus42\Repository\ProductDataDetailRepository;
use Plugin\ProductPlus42\Repository\ProductDataRepository;
use Plugin\ProductPlus42\Repository\ProductItemRepository;
use Plugin\ProductPlus42\Service\ProductPlusService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
class AdminProductEvent implements EventSubscriberInterface
{
private $entityManager;
private $eccubeConfig;
private $productItemRepository;
private $productDataRepository;
private $productDataDetailRepository;
private $productPlusService;
/**
* @var CustomerRepository
*/
protected $customerRepository;
public function __construct(
EntityManagerInterface $entityManager,
EccubeConfig $eccubeConfig,
ProductItemRepository $productItemRepository,
ProductDataRepository $productDataRepository,
ProductDataDetailRepository $productDataDetailRepository,
ProductPlusService $productPlusService,
CustomerRepository $customerRepository
)
{
$this->entityManager = $entityManager;
$this->eccubeConfig = $eccubeConfig;
$this->productItemRepository = $productItemRepository;
$this->productDataRepository = $productDataRepository;
$this->productDataDetailRepository = $productDataDetailRepository;
$this->productPlusService = $productPlusService;
$this->customerRepository = $customerRepository;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
'@admin/Product/product.twig' => 'onTemplateAdminProductEdit',
EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE => 'hookAdminProductEditComplete',
EccubeEvents::ADMIN_PRODUCT_COPY_COMPLETE => 'hookAdminProductCopyComplete',
EccubeEvents::ADMIN_PRODUCT_CSV_EXPORT => 'hookAdminProductCsvExport',
];
}
public function onTemplateAdminProductEdit(TemplateEvent $event)
{
$parameters = $event->getParameters();
$ProductItems = $this->productItemRepository->getList();
$EnabledItems = $this->productPlusService->getEnabledProductPlusForm();
foreach ($ProductItems as $key => $ProductItem) {
foreach ($EnabledItems as $EnabledItem) {
if ($ProductItem->getId() == $EnabledItem->getId())
unset($ProductItems[$key]);
}
}
$htCust = $this->customerRepository->getHash();
$parameters['htCustomer'] = $htCust;
$parameters['ProductItems'] = $ProductItems;
$event->setParameters($parameters);
$source = $event->getSource();
if (preg_match("/\{\%\sfor\sf\sin\sform(\sif|\|filter\(f\s\=\>)\sf\.vars\.eccube\_form\_options\.auto\_render/", $source, $result)) {
$search = $result[0];
$replace = "{{ include('@ProductPlus42/admin/Product/ext_edit.twig') }}" . $search;
$source = str_replace($search, $replace, $source);
}
// フォーム全体でエラーがある場合、ページ上部にエラーがあることを分かりやすく表示する
$errorBannerAnchor = "{{ form_widget(form.return_link) }}";
$errorBanner = $errorBannerAnchor . "\n"
. "{% if form.vars.submitted and not form.vars.valid %}\n"
. "<div class=\"alert alert-danger\" role=\"alert\">\n"
. "<i class=\"fa fa-exclamation-triangle me-1\"></i>入力内容にエラーがある項目があります。(<a href=\"#\" id=\"productplus-error-scroll-link\">ここ</a>をクリックすると該当箇所までスクロールします)\n"
. "</div>\n"
. "{% endif %}";
$source = str_replace($errorBannerAnchor, $errorBanner, $source);
// 「商品説明(一覧)」に既存データがある場合は、折りたたみを開いた状態で表示する
$descriptionListCollapseAnchor = '<div class="collapse ec-collapse" id="addComment">';
$descriptionListCollapseReplace = '<div class="collapse ec-collapse{% if form.description_list.vars.value %} show{% endif %}" id="addComment">';
$source = str_replace($descriptionListCollapseAnchor, $descriptionListCollapseReplace, $source);
$event->setSource($source);
$event->addSnippet('@ProductPlus42/admin/Product/upload_js.twig');
$event->addSnippet('@ProductPlus42/admin/Product/error_scroll.twig');
}
public function hookAdminProductEditComplete(EventArgs $event)
{
$Product = $event->getArgument('Product');
$form = $event->getArgument('form');
$request = $event->getRequest();
$ProductItems = $this->productItemRepository->getList();
foreach ($ProductItems as $ProductItem) {
if ($form->has('productplus_' . $ProductItem->getId())) {
$ProductData = $this->productDataRepository->findOneBy(['ProductItem' => $ProductItem, 'Product' => $Product]);
if (!$ProductData) {
$ProductData = new ProductData();
$ProductData->setProductItem($ProductItem);
$ProductData->setProduct($Product);
}
if ($ProductItem->getInputType() == ProductItem::IMAGE_TYPE) {
$add_images = $form->get('productplus_' . $ProductItem->getId() . '_add_images')->getData();
foreach ($add_images as $add_image) {
$Detail = new ProductDataDetail();
$Detail
->setValue($add_image)
->setProductData($ProductData)
->setSortNo(1);
$ProductData->addDetail($Detail);
$this->entityManager->persist($Detail);
$file = new File($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $add_image);
$file->move($this->eccubeConfig['eccube_save_image_dir']);
}
$delete_images = $form->get('productplus_' . $ProductItem->getId() . '_delete_images')->getData();
$fs = new Filesystem();
foreach ($delete_images as $delete_image) {
$Detail = $this->productDataDetailRepository->findOneBy(['value' => $delete_image]);
if ($Detail instanceof ProductDataDetail) {
$ProductData->removeDetail($Detail);
$this->entityManager->remove($Detail);
$fs->remove($this->eccubeConfig['eccube_save_image_dir'] . '/' . $delete_image);
} else {
$fs->remove($this->eccubeConfig['eccube_temp_image_dir'] . '/' . $delete_image);
}
$this->entityManager->persist($ProductData);
}
$this->entityManager->persist($ProductData);
$Product->addProductData($ProductData);
$this->entityManager->flush();
if ($image = $request->request->all()['admin_product']['productplus_' . $ProductItem->getId() . '_images'] ?? []) {
foreach ($image as $sortNo => $filename) {
$Detail = $this->productDataDetailRepository
->findOneBy([
'value' => pathinfo($filename, PATHINFO_BASENAME),
'ProductData' => $ProductData,
]);
if ($Detail) {
$Detail->setSortNo($sortNo);
$this->entityManager->persist($Detail);
}
}
$this->entityManager->flush();
}
} else {
$value = $form->get('productplus_' . $ProductItem->getId())->getData();
if ($value instanceof \DateTime) {
$value = $value->format('Y-m-d');
} elseif ($ProductItem->getInputType() == ProductItem::CHECKBOX_TYPE && is_array($value)) {
$value = implode(',', $value);
}
$ProductData = $this->productDataRepository->regist($ProductData, $ProductItem, $value);
$Product->addProductData($ProductData);
}
}
}
}
public function hookAdminProductCopyComplete(EventArgs $event)
{
$Product = $event->getArgument('Product');
$CopyProduct = $event->getArgument('CopyProduct');
foreach ($Product->getProductDatas() as $oldProductData) {
$newProductData = new ProductData();
$newProductData->setProduct($CopyProduct);
$newProductData->setProductItem($oldProductData->getProductItem());
if ($newProductData->getProductItem()->getInputType() == ProductItem::IMAGE_TYPE) {
foreach ($oldProductData->getDetails() as $oldDetail) {
// 画像ファイルを新規作成
$extension = pathinfo($oldDetail->getValue(), PATHINFO_EXTENSION);
$filename = date('mdHis') . uniqid('_') . '.' . $extension;
try {
$fs = new Filesystem();
$fs->copy($this->eccubeConfig['eccube_save_image_dir'] . '/' . $oldDetail->getValue(), $this->eccubeConfig['eccube_save_image_dir'] . '/' . $filename);
} catch (\Exception $e) {
// エラーが発生しても無視する
}
$newDetail = new ProductDataDetail();
$newDetail->setValue($filename)
->setSortNo($oldDetail->getSortNo())
->setProductData($newProductData);
$newProductData->addDetail($newDetail);
}
} else {
foreach ($oldProductData->getDetails() as $oldDetail) {
$newDetail = new ProductDataDetail();
$newDetail->setValue($oldDetail->getValue())
->setNumValue($oldDetail->getNumValue())
->setDateValue($oldDetail->getDateValue())
->setProductData($newProductData);
$newProductData->addDetail($newDetail);
}
}
$CopyProduct->addProductData($newProductData);
$this->entityManager->persist($newProductData);
}
$this->entityManager->persist($CopyProduct);
$this->entityManager->flush();
}
public function hookAdminProductCsvExport(EventArgs $event)
{
$ExportCsvRow = $event->getArgument('ExportCsvRow');
if ($ExportCsvRow->isDataNull()) {
$ProductClass = $event->getArgument('ProductClass');
$Product = $ProductClass->getProduct();
$Csv = $event->getArgument('Csv');
$csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
$value = null;
if ($csvEntityName == 'Plugin\ProductPlus42\Entity\ProductData') {
$product_item_id = $Csv->getReferenceFieldName();
if ($Csv->getFieldName() == 'product_item_id') {
$value = $Product->getIdData($product_item_id);
} elseif ($Csv->getFieldName() == 'product_item_value') {
$value = $Product->getValueData($product_item_id);
}
if (is_array($value))
$value = implode(',', $value);
$ExportCsvRow->setData($value);
}
}
}
}