<?php
namespace Plugin\TaxManagement42;
use Eccube\Entity\Product;
use Eccube\Event\TemplateEvent;
use Eccube\Event\EventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Plugin\TaxManagement42\Repository\ConfigRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Plugin\TaxManagement42\Services\Simple_html_dom;
class Event implements EventSubscriberInterface
{
private $container;
/**
* @var ConfigRepository
*/
protected $configRepository;
const DETAIL_PRICE_TAG = "<span class=\"ec-price__tax\">{{ '税込'|trans }}</span>";
const LIST_PRICE_TAG = "{{ Product.getPrice02IncTaxMin|price }}";
const EC_CUBE_LIST_SALE_PRICE_TAG_REGEX = '/class=(("|"([^"]*)\s)price02-default("|\s([^"]*)"))/m';
const TAX_MANAGEMENT_SALE_PRICE_CLASSNAME = '.tax_management-sale_price';
const TAX_MANAGEMENT_SALE_PRICE_TAG_REGEX = '/class=(("|"([^"]*)\s)tax_management-sale_price("|\s([^"]*)"))/m';
const TAX_MANAGEMENT_DISCOUNT_RATE_TAG_REGEX = '/class=(("|"([^"]*)\s)tax_management-discount_rate("|\s([^"]*)"))/m';
/**
* SynchronizeReviewDataEvent constructor.
*
* @param ContainerInterface $container
*/
public function __construct(
ContainerInterface $container,
ConfigRepository $configRepository)
{
$this->container = $container;
$this->configRepository = $configRepository;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
'Product/detail.twig' => 'onProductDetailTwig',
'Product/list.twig' => 'onProductListTwig',
'@admin/Store/plugin.twig' => 'onAdminStorePluginIndexTwig'
];
}
/**
* 商品詳細ページ 割引率の表示
* @param TemplateEvent $event
*/
public function onProductDetailTwig(TemplateEvent $event)
{
$parameters = $event->getParameters();
if (is_null($parameters['Product'])) {
return;
}
$Product = $parameters['Product'];
$TaxManagementConfig = $this->configRepository->get();
$requestStack = $this->container->get('request_stack');
$request = $requestStack->getMasterRequest();
$request->attributes->set('TaxManagementConfig', $TaxManagementConfig);
try {
if($TaxManagementConfig !== null) {
$parameters['TaxManagementConfig'] = $TaxManagementConfig;
$source = $event->getSource();
$twig = $this->container->get('twig');
$search1 = '/({# 通常価格 #})[\s\S]+?({# 商品コード #})/s';
preg_match($search1, $source, $matches);
if($matches) {
$source = preg_replace($search1, '<!-- tax_management_通常価格 -->' . '$0' . '<!-- tax_management_商品コード -->', $source);
$event->setSource($source);
}
$discountRates = $this->calculateDiscountRates($Product, $TaxManagementConfig->isDiscountRateFlag());
$Product->discountRatesJson = json_encode($discountRates['class_categories']);
$Product->discountRateMax = $discountRates['discountRateMax'];
$Product->discountRateMin = $discountRates['discountRateMin'];
$Product->price02Values = json_encode(
array(
'price02NoTaxMin' => number_format($Product->getPrice02Min()),
'price02NoTaxMax' => number_format($Product->getPrice02Max()),
'price02IncTaxMin' => number_format($Product->getPrice02IncTaxMin()),
'price02IncTaxMax' => number_format($Product->getPrice02IncTaxMax()))
);
$Product->price01Values = json_encode(
array(
'price01NoTaxMin' => $Product->getPrice01Min() !== null ? number_format($Product->getPrice01Min()): null,
'price01NoTaxMax' => $Product->getPrice01Min() !== null ? number_format($Product->getPrice01Max()): null,
'price01IncTaxMin' => $Product->getPrice01Min() !== null ? number_format($Product->getPrice01IncTaxMin()): null,
'price01IncTaxMax' => $Product->getPrice01Min() !== null ? number_format($Product->getPrice01IncTaxMax()): null)
);
$parameters['Product'] = $Product;
$event->setParameters($parameters);
$event->addAsset('@TaxManagement42/default/Product/detail_discount_rate_style.twig');
$event->addSnippet('@TaxManagement42/default/Product/detail_discount_rate_script.twig');
}
} catch (\Throwable $th) {
log_error($th);
}
}
public function onProductListTwig(TemplateEvent $event)
{
$parameters = $event->getParameters();
if (is_null($parameters['pagination'])){
return;
}
$pagination = $parameters['pagination'];
$TaxManagementConfig = $this->configRepository->get();
$requestStack = $this->container->get('request_stack');
$request = $requestStack->getMasterRequest();
$request->attributes->set('TaxManagementConfig', $TaxManagementConfig);
$source = $event->getSource();
$source = preg_replace_callback(self::EC_CUBE_LIST_SALE_PRICE_TAG_REGEX, function ($matches) {
$classNames = explode('"', $matches[1]);
if(isset($classNames[1]) && strpos($classNames[1], ' tax_management_id_{{Product.id}}') === false) {
$matches[0] = str_replace($matches[1], '"' . $classNames[1] . ' tax_management_id_{{Product.id}}"', $matches[0]);
}
return $matches[0];
}, $source);
$source = preg_replace_callback(self::TAX_MANAGEMENT_SALE_PRICE_TAG_REGEX, function ($matches) {
$classNames = explode('"', $matches[1]);
if(isset($classNames[1]) && strpos($classNames[1], ' tax_management_id_{{Product.id}}') === false) {
$matches[0] = str_replace($matches[1], '"' . $classNames[1] . ' tax_management_id_{{Product.id}}"', $matches[0]);
}
return $matches[0];
}, $source);
$event->setSource($source);
try {
if($TaxManagementConfig !== null) {
$parameters['TaxManagementConfig'] = $TaxManagementConfig;
foreach ($pagination as $Product) {
// 01:通常価格, 02:販売価格
$discountRates = $this->calculateDiscountRates($Product, $TaxManagementConfig->isDiscountRateFlag());
$Product->discountRatesJson = json_encode($discountRates['class_categories']);
$Product->discountRateMax = $discountRates['discountRateMax'];
$Product->discountRateMin = $discountRates['discountRateMin'];
$Product->price02Values = json_encode(
array(
'price02NoTaxMin' => number_format($Product->getPrice02Min()),
'price02NoTaxMax' => number_format($Product->getPrice02Max()),
'price02IncTaxMin' => number_format($Product->getPrice02IncTaxMin()),
'price02IncTaxMax' => number_format($Product->getPrice02IncTaxMax()))
);
$Product->price01Values = json_encode(
array(
'price01NoTaxMin' => $Product->getPrice01Min() != null ? number_format($Product->getPrice01Min()) : null,
'price01NoTaxMax' => $Product->getPrice01Min() != null ? number_format($Product->getPrice01Max()) : null,
'price01IncTaxMin' => $Product->getPrice01Min() != null ? number_format($Product->getPrice01IncTaxMin()) : null,
'price01IncTaxMax' => $Product->getPrice01Min() != null ? number_format($Product->getPrice01IncTaxMax()) : null
)
);
}
//set parameter for twig files
$parameters['pagination'] = $pagination;
$event->setParameters($parameters);
$request->attributes->set('tax_management_products', $pagination);
$event->addAsset('@TaxManagement42/default/Product/list_discount_rate_style.twig');
$event->addSnippet('@TaxManagement42/default/Product/list_discount_rate_script.twig');
}
} catch (\Throwable $th) {
log_error($th);
}
}
/**
* calculate discount rate max and discount rate min
* they will be a number in range (1,99) or null
*
* @param Eccube\Entity\Product $Product
* @param bool $discountRateFlag
* @return array()
*
*/
private function calculateDiscountRates($Product, $discountRateFlag) {
$class_categories = [
'__unselected' => [
'__unselected' => [
'name' => trans('common.select'),
'product_class_id' => '',
],
],
];
$minDiscountRate = 0;
$maxDiscountRate = 0;
foreach ($Product->getProductClasses() as $ProductClass) {
/** @var ProductClass $ProductClass */
if (!$ProductClass->isVisible()) {
continue;
}
/* @var $ProductClass \Eccube\Entity\ProductClass */
$ClassCategory1 = $ProductClass->getClassCategory1();
$ClassCategory2 = $ProductClass->getClassCategory2();
if ($ClassCategory2 && !$ClassCategory2->isVisible()) {
continue;
}
$price01 = $ProductClass->getPrice01();
$price02 = $ProductClass->getPrice02();
$discountRate = 0;
if ((int)$price01 > 0 ) {
$rate = sprintf('%.3f', (1.0 - ($price02 / $price01)) * 100.0);
$TaxManagementConfig = $this->configRepository->get();
// 0: round up for discount value
// 1: round down for discount value
// 2: display decimal value with round for discount value
if ($TaxManagementConfig->getDisplayDiscountType() === 1) {
$discountRate = (int)floor($rate);
} elseif ($TaxManagementConfig->getDisplayDiscountType() === 2) {
$discountRate = (int)round($rate);
} else {
$discountRate = (int)ceil($rate);
}
if ($discountRate <= 0 or $discountRate >= 100 or !$discountRateFlag) {
$discountRate = 0;
}
if($discountRate <= $minDiscountRate || $minDiscountRate == 0) {
$minDiscountRate = $discountRate;
}
if($discountRate >= $maxDiscountRate || $maxDiscountRate == 0) {
$maxDiscountRate = $discountRate;
}
}
$class_category_id1 = $ClassCategory1 ? (string) $ClassCategory1->getId() : '__unselected2';
$class_category_id2 = $ClassCategory2 ? (string) $ClassCategory2->getId() : '';
$class_categories[$class_category_id1]['#'] = array(
'classcategory_id2' => '',
'name' => trans('common.select'),
'product_class_id' => '',
);
$class_categories[$class_category_id1]['#'.$class_category_id2] = array(
'classcategory_id2' => $class_category_id2,
'discount_rate' => $discountRate
);
}
$result = array(
'class_categories' => $class_categories,
'discountRateMax' => $maxDiscountRate,
'discountRateMin' => $minDiscountRate,
);
return $result;
}
public function onAdminStorePluginIndexTwig(TemplateEvent $event)
{
$em = $this->container->get('doctrine.orm.entity_manager');
$conn = $em->getConnection();
$driver = '';
$conn = $em->getConnection();
$params = $conn->getParams();
if (isset($params['driver'])){
$driver = $params['driver'];
}
if ($driver == 'pdo_mysql') {
} elseif ($driver == 'pdo_pgsql') {
// shop_name_top_flg
$stmt = $conn->executeQuery("SELECT column_name FROM information_schema.columns WHERE table_name='plg_tax_management_config' and column_name='display_discount_type'");
$cnt = $stmt->fetchOne();
if (!$cnt) {
$stmt = $conn->executeQuery("ALTER TABLE plg_tax_management_config ADD COLUMN display_discount_type INT DEFAULT 0");
}
}
}
}