<?php
namespace Plugin\Shiro8Download42;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Eccube\Common\EccubeConfig;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Event\EccubeEvents;
use Eccube\Event\TemplateEvent;
use Eccube\Event\EventArgs;
use Plugin\Shiro8Download42\Repository\Shiro8ProductFileRepository;
use Plugin\Shiro8Download42\Repository\Shiro8OrderDetailFileRepository;
use Plugin\Shiro8Download42\Repository\ConfigRepository;
use Plugin\Shiro8Download42\Entity\Shiro8ProductFile;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints as Assert;
use Eccube\Service\CartService;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Twig\Environment;
use Symfony\Contracts\Translation\TranslatorInterface;
class Event implements EventSubscriberInterface
{
/**
* プラグインが追加するフォーム名.
*/
const PRODUCT_DOWNLOAD_FILE = 'plg_shiro8_product_file_file';
const PRODUCT_DOWNLOAD = 'plg_shiro8_product_file';
const PRODUCT_DOWNLOAD_DEL_FLG = 'plg_shiro8_product_file_del_flg';
/**
* @var Environment
*/
private $twig;
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var CartService
*/
protected $cartService;
/**
* @var EccubeConfig
*/
private $eccubeConfig;
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var Shiro8ProductFileRepository
*/
private $shiro8ProductFileRepository;
/**
* @var ConfigRepository
*/
private $configRepository;
/**
* @var Shiro8OrderDetailFileRepository
*/
private $shiro8OrderDetailFileRepository;
/**
*
* @param ContainerInterface $container
* @param CartService $cartService
* @param EccubeConfig $eccubeConfig
* @param EntityManagerInterface $entityManager
* @param Shiro8ProductFileRepository $shiro8ProductFileRepository
*/
public function __construct(Environment $twig, TranslatorInterface $translator,
ContainerInterface $container,
CartService $cartService,
EccubeConfig $eccubeConfig,
EntityManagerInterface $entityManager,
Shiro8ProductFileRepository $shiro8ProductFileRepository,
ConfigRepository $configRepository,
Shiro8OrderDetailFileRepository $shiro8OrderDetailFileRepository)
{
$this->twig = $twig;
$this->translator = $translator;
$this->container = $container;
$this->cartService = $cartService;
$this->eccubeConfig = $eccubeConfig;
$this->entityManager = $entityManager;
$this->shiro8ProductFileRepository = $shiro8ProductFileRepository;
$this->configRepository = $configRepository;
$this->shiro8OrderDetailFileRepository = $shiro8OrderDetailFileRepository;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
EccubeEvents::ADMIN_PRODUCT_EDIT_INITIALIZE => 'onAdminProductFormInitialize',
EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE => 'onAdminProductEditComplete',
'@admin/Product/product.twig' => 'onRenderAdminProduct',
'Product/detail.twig' => 'onRenderProductDetail',
'Product/list.twig' => 'onRenderProductList',
EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE => 'onFrontProductCartAddComplete',
'Mypage/index.twig' => 'onRenderMyPageIndex',
'@user_data/history_list.twig' => 'onRenderMyPageIndex', //追加
'Mypage/history.twig' => 'onRenderMyPageHistory',
EccubeEvents::MAIL_ORDER => 'onOrderReplaceForMail',
];
}
/**
* 管理画面:商品登録画面に, 商品コンテンツのフォームを追加する.
*
* @param EventArgs $event
*/
public function onAdminProductFormInitialize(EventArgs $event)
{
/* @var Category $TargetCategory */
$Product = $event->getArgument('Product');
$id = $Product->getId();
$ProductClasses = $Product->getProductClasses();
$ProductClass = $ProductClasses[0];
//規格無しの場合
if (!$Product->hasProductClass()) {
$ProductFile = null;
if ($ProductClass->getId()) {
// 商品編集時は初期値を取得
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
}
// 商品新規登録またはコンテンツが未登録の場合
if (!$ProductFile) {
$ProductFile = new Shiro8ProductFile();
}
// フォームの追加
/** @var FormInterface $builder */
// 初期値を設定
$builder = $event->getArgument('builder');
if ($ProductFile->getFile() != '') {
$builder->get(self::PRODUCT_DOWNLOAD)->setData($ProductFile->getFile());
} else {
$builder->get(self::PRODUCT_DOWNLOAD)->setData(null);
}
}
}
/**
* 管理画面:商品登録画面で、登録処理を行う.
*
* @param EventArgs $event
*/
public function onAdminProductEditComplete(EventArgs $event)
{
//イベント元からの値を取得
$Product = $event->getArgument('Product');
$form = $event->getArgument('form');
//規格無しの場合
if (!$Product->hasProductClass()) {
// 現在のエンティティを取得
$id = $Product->getId();
$ProductClasses = $Product->getProductClasses();
$ProductClass = $ProductClasses[0];
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
if (!$ProductFile) {
$ProductFile = new Shiro8ProductFile();
}
// ファイルアップロード
$image = $form[self::PRODUCT_DOWNLOAD_FILE]->getData();
$filename = null;
if (isset($image)) {
//ファイルフォーマット検証
$mimeType = $image->getMimeType();
if (false !== strpos($mimeType, 'pdf') || $mimeType == 'application/zip' || $mimeType == 'application/x-gzip'
|| false !== strpos($mimeType, 'image') || $mimeType == 'text/plain' || $mimeType == 'application/gzip') {
//何もしない
} else {
throw new UnsupportedMediaTypeHttpException('ファイル形式が不正です');
}
$extension = $image->guessExtension();
$filename = date('mdHis') . uniqid('_') . '.' . $extension;
$image->move($this->eccubeConfig['plugin_data_realdir'] . "/Shiro8Download42/Resource", $filename);
}
$fileNameOld = $form[self::PRODUCT_DOWNLOAD]->getData();
$fileDelFlg = $form[self::PRODUCT_DOWNLOAD_DEL_FLG]->getData();
if ($fileDelFlg == 1 || ($fileNameOld == "" && $filename == "")) {
// エンティティを更新
$ProductFile
->setId($ProductClass->getId())
->setFile(null);
// DB更新
$this->entityManager->persist($ProductFile);
$this->entityManager->flush($ProductFile);
} else if ($filename != "") {
//ファイルがアップロードされている
// エンティティを更新
$ProductFile
->setId($ProductClass->getId())
->setFile($filename);
// DB更新
$this->entityManager->persist($ProductFile);
$this->entityManager->flush($ProductFile);
} else {
// エンティティを更新
$ProductFile
->setId($ProductClass->getId())
->setFile($fileNameOld);
// DB更新
$this->entityManager->persist($ProductFile);
$this->entityManager->flush($ProductFile);
}
}
}
/**
* 管理画面:商品登録画面にファイル編集フォームを表示する.
*
* @param TemplateEvent $event
*/
public function onRenderAdminProduct(TemplateEvent $event)
{
$event->addSnippet('@Shiro8Download42/admin/Product/product.twig');
}
/**
* 商品詳細画面に商品コンテンツを表示する.
*
* @param TemplateEvent $event
*/
public function onRenderProductDetail(TemplateEvent $event)
{
$parameters = $event->getParameters();
// 商品がない場合、レンダリングしない
if (!$parameters['Product']) {
return;
}
// twigパラメータにカテゴリコンテンツを追加
$loginFlg = true;
$Product = $parameters['Product'];
if (!$Product->hasProductClass()) {
$ProductClasses = $Product->getProductClasses();
$ProductClass = $ProductClasses[0];
$ProductFile = null;
if ($ProductClass->getId()) {
// 商品編集時は初期値を取得
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
}
// 商品新規登録またはコンテンツが未登録の場合
if ($ProductFile && $ProductFile->getFile() != '') {
//ログイン済みか判定
$loginFlg = $this->isGranted('ROLE_USER');
}
}
$parameters['hasProductFileAndSignIn'] = $loginFlg;
//ダウンロード販売規格商品判定用に配列を作る
$class_categories = array();
foreach ($Product->getProductClasses() as $ProductClass) {
$ClassCategory1 = $ProductClass->getClassCategory1();
$ClassCategory2 = $ProductClass->getClassCategory2();
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
$dlFlg = false;
if ($ProductFile && $ProductFile->getFile() != '') {
$dlFlg = true;
}
$class_category_id1 = $ClassCategory1 ? (string) $ClassCategory1->getId() : '__unselected2';
$class_category_id2 = $ClassCategory2 ? (string) $ClassCategory2->getId() : '';
$class_categories[$class_category_id1]['#'.$class_category_id2] = array(
'dl_find' => $dlFlg
);
}
$parameters['product_class_categories'] = $class_categories;
$event->setParameters($parameters);
$event->addSnippet('@Shiro8Download42/default/Product/product.twig');
}
/**
* 商品一覧画面に商品コンテンツを表示する.
*
* @param TemplateEvent $event
*/
public function onRenderProductList(TemplateEvent $event)
{
$parameters = $event->getParameters();
// 商品がない場合、レンダリングしない
if (!$parameters['pagination'] || count($parameters['pagination']) == 0) {
return;
}
$loginFlgs = array();
foreach ($parameters['pagination'] as $k => $Product) {
// twigパラメータにカテゴリコンテンツを追加
$loginFlg = true;
if (!$Product->hasProductClass()) {
$ProductClasses = $Product->getProductClasses();
$ProductClass = $ProductClasses[0];
$ProductFile = null;
if ($ProductClass->getId()) {
// 商品編集時は初期値を取得
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
}
// 商品新規登録またはコンテンツが未登録の場合
if ($ProductFile && $ProductFile->getFile() != '') {
//ログイン済みか判定
$loginFlg = $this->isGranted('ROLE_USER');
}
}
$loginFlgs[$k] = $loginFlg;
}
$parameters['hasProductFileAndSignIn'] = $loginFlgs;
//ダウンロード販売規格商品判定用に配列を作る
$class_categories = array();
foreach ($parameters['pagination'] as $Product) {
foreach ($Product->getProductClasses() as $ProductClass) {
$ClassCategory1 = $ProductClass->getClassCategory1();
$ClassCategory2 = $ProductClass->getClassCategory2();
$ProductFile = $this->shiro8ProductFileRepository->find($ProductClass->getId());
$dlFlg = false;
if ($ProductFile && $ProductFile->getFile() != '') {
$dlFlg = true;
}
$class_category_id1 = $ClassCategory1 ? (string) $ClassCategory1->getId() : '__unselected2';
$class_category_id2 = $ClassCategory2 ? (string) $ClassCategory2->getId() : '';
$class_categories[$Product->getId()][$class_category_id1]['#'.$class_category_id2] = array(
'dl_find' => $dlFlg
);
}
}
$parameters['product_class_categories'] = $class_categories;
$event->setParameters($parameters);
$event->addSnippet('@Shiro8Download42/default/Product/list.twig');
}
/**
* 管理画面:商品登録画面で、登録処理を行う.
*
* @param EventArgs $event
*/
public function onFrontProductCartAddComplete(EventArgs $event)
{
//イベント元からの値を取得
$Product = $event->getArgument('Product');
$form = $event->getArgument('form');
$addCartData = $form->getData();
$ProductFile = $this->shiro8ProductFileRepository->find($addCartData['product_class_id']);
// 商品新規登録またはコンテンツが未登録の場合
$isDownload = false;
if ($ProductFile && $ProductFile->getFile() != '') {
$isDownload = true;
}
// カスタマイズ開始 ゲストでもカートに入れられるように
// if ($isDownload && !$this->isGranted('ROLE_USER')) {
//カートの中身を削除
// $this->cartService->removeProduct($addCartData['product_class_id']);
//エラーを返す
// throw new NotFoundHttpException();
// }
// カスタマイズ終了
}
/**
* マイページの購入履歴にダウンロードリンクを表示する.
*
* @param TemplateEvent $event
*/
public function onRenderMyPageIndex(TemplateEvent $event)
{
$parameters = $event->getParameters();
// 商品がない場合、レンダリングしない
//if (!$parameters['pagination']) {
if (!$parameters['photos']) {
return;
}
// twigコードにコンテンツを挿入
$sourceOrigin = $event->getSource();
//$search = '× {{ OrderItem.quantity }}</p> ';
$search = '<a class="dl_btn"></a>';
$snipet = $this->twig->getLoader()->getSourceContext('@Shiro8Download42/default/Mypage/index.twig')->getCode();
$source = str_replace($search, $snipet, $sourceOrigin);
$event->setSource($source);
$addCartSetting = $this->configRepository->find(1);
// twigパラメータにコンテンツを追加
$orderDetailFiles = array();
$orderDetailFlgs = array();
//$Orders = $parameters['pagination'];
$Orders = $parameters['photos'];
foreach ($Orders as $Order) {
//入金済みか判定
if ($Order->getPaymentDate() == '') {
continue;
}
$OrderDetails = $Order->getOrderItems();
foreach ($OrderDetails as $v) {
if ($v->isProduct()) {
$OrderDetailFile = $this->shiro8OrderDetailFileRepository->findOneBy(['order_item_id' => $v->getId()]);
if ($OrderDetailFile && $OrderDetailFile->getRand() != '') {
//ダウンロード可否の判定
if ($addCartSetting->getUseFlg() == 1) {
//回数
if ($addCartSetting->getDlCount() > $OrderDetailFile->getDlCount()) {
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
} else {
$orderDetailFlgs[$v->getId()] = false;
}
} else if ($addCartSetting->getUseFlg() == 2) {
//無制限
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
} else {
//入金日からの日数
if ($Order->getPaymentDate()->modify(" + " . $addCartSetting->getDateCount() . " day")->getTimestamp() > time()) {
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
} else {
$orderDetailFlgs[$v->getId()] = false;
}
}
}
}
}
}
$parameters['orderDetailFiles'] = $orderDetailFiles;
$parameters['orderDetailFlgs'] = $orderDetailFlgs;
$parameters['dateCount'] = $addCartSetting->getDateCount();
$event->setParameters($parameters);
}
/**
* マイページの購入履歴詳細にダウンロードリンクを表示する.
*
* @param TemplateEvent $event
*/
public function onRenderMyPageHistory(TemplateEvent $event)
{
$parameters = $event->getParameters();
// 商品がない場合、レンダリングしない
if (!$parameters['Order']) {
return;
}
// twigコードにカテゴリコンテンツを挿入
$sourceOrigin = $event->getSource();
$search = '× {{ orderItem.quantity|number_format }}</p>';
$snipet = $this->twig->getLoader()->getSourceContext('@Shiro8Download42/default/Mypage/history.twig')->getCode();
$source = str_replace($search, $snipet, $sourceOrigin);
$event->setSource($source);
$addCartSetting = $this->configRepository->find(1);
// twigパラメータにカテゴリコンテンツを追加
$orderDetailFiles = array();
$orderDetailFlgs = array();
$orderDetailMsgs = array();
$Order = $parameters['Order'];
//入金済みか判定
if ($Order->getPaymentDate() != '') {
$paymentDateLimit = $Order->getPaymentDate()->modify(" + " . $addCartSetting->getDateCount() . " day");
$OrderDetails = $Order->getOrderItems();
foreach ($OrderDetails as $v) {
if ($v->isProduct()) {
$OrderDetailFile = $this->shiro8OrderDetailFileRepository->findOneBy(['order_item_id' => $v->getId()]);
if ($OrderDetailFile && $OrderDetailFile->getRand() != '') {
//ダウンロード可否の判定
if ($addCartSetting->getUseFlg() == 1) {
//回数
if ($addCartSetting->getDlCount() > $OrderDetailFile->getDlCount()) {
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
$orderDetailMsgs[$v->getId()] = $this->translator->trans('plugin_shiro8_download42.mypage.button');
} else {
$orderDetailFlgs[$v->getId()] = false;
$orderDetailMsgs[$v->getId()] = $this->translator->trans('plugin_shiro8_download42.mypage.button.alert1');
}
} else if ($addCartSetting->getUseFlg() == 2) {
//無制限
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
$orderDetailMsgs[$v->getId()] = $this->translator->trans('plugin_shiro8_download42.mypage.button');
} else {
//入金日からの日数
if ($paymentDateLimit->getTimestamp() > time()) {
$orderDetailFiles[$v->getId()] = $OrderDetailFile->getRand();
$orderDetailFlgs[$v->getId()] = true;
$orderDetailMsgs[$v->getId()] = $this->translator->trans('plugin_shiro8_download42.mypage.button');
} else {
$orderDetailFlgs[$v->getId()] = false;
$orderDetailMsgs[$v->getId()] = $this->translator->trans('plugin_shiro8_download42.mypage.button.alert2');
}
}
}
}
}
}
$parameters['orderDetailFiles'] = $orderDetailFiles;
$parameters['orderDetailFlgs'] = $orderDetailFlgs;
$parameters['orderDetailMsgs'] = $orderDetailMsgs;
$event->setParameters($parameters);
}
/**
* 注文メールに文言を表示する.
*
* @param TemplateEvent $event
*/
public function onOrderReplaceForMail(EventArgs $event)
{
$message = $event->getArgument('message');
$Order = $event->getArgument('Order');
$MailTemplate = $event->getArgument('MailTemplate');
$BaseInfo = $event->getArgument('BaseInfo');
// レンダリング実行.
// twigファイルのソースコードを読み込み, 文字列化.
$view = $MailTemplate->getFileName();
$source = $this->twig->getLoader()->getSourceContext($view)->getCode();
// イベントの実行.
// プラグインにはテンプレートファイル名、文字列化されたtwigファイル、パラメータを渡す
$TemplateEvent = new TemplateEvent($view, $source, array(
'Order' => $Order,
), null);
$snipet = $this->twig->getLoader()->getSourceContext('@Shiro8Download42/default/Mail/order.twig')->getCode();
$sourceOrigin = $TemplateEvent->getSource();
$search = '数量:{{ OrderItem.quantity|number_format }}';
$source = str_replace($search, $snipet, $sourceOrigin);
$parameters = $TemplateEvent->getParameters();
// 商品がない場合、レンダリングしない
if (!$parameters['Order']) {
return;
}
// twigパラメータにカテゴリコンテンツを追加
$orderDetailFlgs = array();
$Order = $parameters['Order'];
$OrderDetails = $Order->getOrderItems();
foreach ($OrderDetails as $v) {
$OrderDetailFile = $this->shiro8OrderDetailFileRepository->findOneBy(['order_item_id' => $v->getId()]);
if ($OrderDetailFile && $OrderDetailFile->getRand() != '') {
$orderDetailFlgs[$v->getId()] = true;
}
}
$parameters['orderDetailFlgs'] = $orderDetailFlgs;
$TemplateEvent->setParameters($parameters);
$template = $this->twig->createTemplate($source);
$content = $template->render($TemplateEvent->getParameters());
// HTMLテンプレートが存在する場合
$htmlFileName = $this->getHtmlTemplate($MailTemplate->getFileName());
if (!is_null($htmlFileName)) {
$source = $this->twig->getLoader()->getSourceContext($htmlFileName)->getCode();
$TemplateEvent = new TemplateEvent($view, $source, array(
'Order' => $Order,
), null);
$snipet = $this->twig->getLoader()->getSourceContext('@Shiro8Download42/default/Mail/order.html.twig')->getCode();
$sourceOrigin = $TemplateEvent->getSource();
$search = '数量:{{ OrderItem.quantity|number_format }}<br/>';
$source = str_replace($search, $snipet, $sourceOrigin);
$parameters = $TemplateEvent->getParameters();
// 商品がない場合、レンダリングしない
if (!$parameters['Order']) {
return;
}
// twigパラメータにカテゴリコンテンツを追加
$orderDetailFlgs = array();
$Order = $parameters['Order'];
$OrderDetails = $Order->getOrderItems();
foreach ($OrderDetails as $v) {
$OrderDetailFile = $this->shiro8OrderDetailFileRepository->findOneBy(['order_item_id' => $v->getId()]);
if ($OrderDetailFile && $OrderDetailFile->getRand() != '') {
$orderDetailFlgs[$v->getId()] = true;
}
}
$parameters['orderDetailFlgs'] = $orderDetailFlgs;
$TemplateEvent->setParameters($parameters);
$template = $this->twig->createTemplate($source);
$htmlBody = $template->render($TemplateEvent->getParameters());
$message
->text($content)
->html($htmlBody);
} else {
$message->text($content);
}
$message->subject('[' . $BaseInfo->getShopName() . '] ' . $MailTemplate->getMailSubject());
}
/**
* @see Symfony\Bundle\FrameworkBundle\Controller\AbstractController
*/
private function isGranted($attribute, $subject = null): bool
{
return $this->container->get('security.authorization_checker')->isGranted($attribute, $subject);
}
/**
* [getHtmlTemplate description]
*
* @param string $templateName プレーンテキストメールのファイル名
*
* @return string|null 存在する場合はファイル名を返す
*/
private function getHtmlTemplate($templateName)
{
// メールテンプレート名からHTMLメール用テンプレート名を生成
$fileName = explode('.', $templateName);
$suffix = '.html';
$htmlFileName = $fileName[0].$suffix.'.'.$fileName[1];
// HTMLメール用テンプレートの存在チェック
if ($this->twig->getLoader()->exists($htmlFileName)) {
return $htmlFileName;
} else {
return null;
}
}
}