<?php
namespace Plugin\PiaHistory\EventSubscriber;
use Eccube\Entity\Product;
use Eccube\Repository\ProductRepository;
use Eccube\Repository\MemberRepository;
use Doctrine\ORM\EntityManagerInterface;
use Plugin\PiaHistory\Entity\PiaHistory;
use Plugin\PiaHistory\Entity\PiaHisProductClass;
use Plugin\PiaHistory\Entity\PiaHisProductStock;
use Plugin\PiaHistory\Entity\PiaHisRankPrice;
use Plugin\PiaHistory\Repository\PiaHistoryRepository;
use Plugin\PiaHistory\Repository\PiaHisProductClassRepository;
use Plugin\PiaHistory\Repository\PiaHisProductStockRepository;
use Plugin\PiaHistory\Repository\PiaHisRankPriceRepository;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class ProductClassEditEventSubscriber implements EventSubscriberInterface
{
/**
* @var PiaHistoryRepository
*/
private $piaHistoryRepository;
/**
* @var PiaHisProductClassRepository
*/
private $piaHisProductClassRepository;
/**
* @var PiaHisProductStockRepository
*/
private $piaHisProductStockRepository;
/**
* @var PiaHisRankPriceRepository
*/
private $piaHisRankPriceRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var MemberRepository
*/
private $memberRepository;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* ProductClassEditEventSubscriber constructor.
*/
public function __construct(
PiaHistoryRepository $piaHistoryRepository,
PiaHisProductClassRepository $piaHisProductClassRepository,
PiaHisProductStockRepository $piaHisProductStockRepository,
PiaHisRankPriceRepository $piaHisRankPriceRepository,
ProductRepository $productRepository,
MemberRepository $memberRepository,
TokenStorageInterface $tokenStorage,
EntityManagerInterface $entityManager
) {
$this->piaHistoryRepository = $piaHistoryRepository;
$this->piaHisProductClassRepository = $piaHisProductClassRepository;
$this->piaHisProductStockRepository = $piaHisProductStockRepository;
$this->piaHisRankPriceRepository = $piaHisRankPriceRepository;
$this->productRepository = $productRepository;
$this->memberRepository = $memberRepository;
$this->tokenStorage = $tokenStorage;
$this->entityManager = $entityManager;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => ['onKernelResponse', 0],
];
}
/**
* @param ResponseEvent $event
*/
public function onKernelResponse(ResponseEvent $event)
{
$request = $event->getRequest();
$response = $event->getResponse();
// 商品規格編集画面のPOSTリクエストのみ処理
if ($request->isMethod('POST') &&
$request->attributes->get('_route') === 'admin_product_product_class' &&
$response->getStatusCode() === 302) { // リダイレクトレスポンス
$productId = $request->get('id');
if ($productId) {
$this->saveProductClassHistory($productId);
}
}
}
/**
* 商品クラス履歴を保存
*
* @param int $productId
*/
private function saveProductClassHistory($productId)
{
try {
// EntityManagerの状態をチェック
if (!$this->entityManager->isOpen()) {
error_log('PiaHistory: EntityManager is closed, skipping product class history save');
return;
}
$product = $this->productRepository->find($productId);
if (!$product) {
return;
}
// トランザクション開始
$this->entityManager->beginTransaction();
// 管理者情報を取得
$adminId = 1;
$adminName = '管理者';
if ($this->tokenStorage->getToken() && $this->tokenStorage->getToken()->getUser()) {
$admin = $this->tokenStorage->getToken()->getUser();
$adminId = $admin->getId();
$adminName = $admin->getUsername();
// 管理者の詳細情報を取得
$member = $this->memberRepository->find($adminId);
if ($member) {
$adminName = $member->getName();
}
}
// 履歴メイン情報を作成
$history = new PiaHistory();
$history->setProductId($productId);
$history->setUpdateId($adminId);
$history->setUpdateName($adminName);
$history->setUpdateNum(1); // 更新回数(仮)
$history->setUpdateNote('商品規格情報を更新しました');
$history->setCreateDate(new \DateTime());
$history->setUpdateDate(new \DateTime());
$history->setDelFlg(0);
$this->piaHistoryRepository->save($history);
$historyId = $history->getId();
// 商品規格履歴を保存
$this->saveProductClassBasicHistory($historyId, $product);
// 商品在庫履歴を保存
$this->saveProductStockHistory($historyId, $product);
// 商品ランク価格履歴を保存
$this->saveRankPriceHistory($historyId, $product);
// 最後にまとめてflush
$this->piaHistoryRepository->flush();
// トランザクションコミット
$this->entityManager->commit();
} catch (\Exception $e) {
// トランザクションロールバック
if ($this->entityManager->getConnection()->isTransactionActive()) {
$this->entityManager->rollback();
}
// エラーログを出力
error_log('PiaHistory: 商品クラス履歴保存エラー - ' . $e->getMessage());
}
}
/**
* 商品規格基本履歴を保存
*
* @param int $historyId
* @param Product $product
*/
private function saveProductClassBasicHistory($historyId, Product $product)
{
foreach ($product->getProductClasses() as $productClass) {
$classHistory = new PiaHisProductClass();
$classHistory->setHisId($historyId);
$classHistory->setProductId($product->getId());
$classHistory->setProductTypeId(null); // EC-CUBE4では商品規格タイプが存在しない
$classHistory->setClassCategoryId1($productClass->getClassCategory1() ? $productClass->getClassCategory1()->getId() : null);
$classHistory->setClassCategoryId2($productClass->getClassCategory2() ? $productClass->getClassCategory2()->getId() : null);
$classHistory->setDeliveryDateId($productClass->getDeliveryDuration() ? $productClass->getDeliveryDuration()->getId() : null);
$classHistory->setProductCode($productClass->getCode());
$classHistory->setStock($productClass->getStock());
$classHistory->setStockUnlimited($productClass->isStockUnlimited());
$classHistory->setSaleLimit($productClass->getSaleLimit());
$classHistory->setPrice01($productClass->getPrice01());
$classHistory->setPrice02($productClass->getPrice02());
$classHistory->setDeliveryFee($productClass->getDeliveryFee());
$this->entityManager->persist($classHistory);
}
}
/**
* 商品在庫履歴を保存
*
* @param int $historyId
* @param Product $product
*/
private function saveProductStockHistory($historyId, Product $product)
{
foreach ($product->getProductClasses() as $productClass) {
$stockHistory = new PiaHisProductStock();
$stockHistory->setHisId($historyId);
$stockHistory->setProductClassId($productClass->getId());
$stockHistory->setStock($productClass->getStock());
$this->entityManager->persist($stockHistory);
}
}
/**
* 商品ランク価格履歴を保存
*
* @param int $historyId
* @param Product $product
*/
private function saveRankPriceHistory($historyId, Product $product)
{
// 商品ランク価格の履歴保存処理
// 他のプラグインとの連携が必要な場合はここで実装
foreach ($product->getProductClasses() as $productClass) {
// ランク価格の取得と保存処理
// 例: CustomerRankプラグインとの連携
}
}
}