<?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 Eccube\Event\TemplateEvent;
use Plugin\ProductOption42\Entity\OptionCategory;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CartEvent implements EventSubscriberInterface
{
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
'Cart/index.twig' => 'onTemplateCart',
];
}
public function onTemplateCart(TemplateEvent $event)
{
$source = $event->getSource();
if(preg_match("/url\('cart\_handle\_item'\s*,\s*\{'operation'\s*:\s*'down'\s*,\s*'productClassId'\s*:\s*ProductClass\.id/",$source, $result)){
$search = $result[0];
$snipet = "url('productoption_cart_handle_item', {'operation': 'down', 'cartItemId': CartItem.id";
$replace = $snipet;
$source = str_replace($search, $replace, $source);
}
if(preg_match("/url\('cart\_handle\_item'\s*,\s*\{'operation'\s*:\s*'up'\s*,\s*'productClassId'\s*:\s*ProductClass\.id/",$source, $result)){
$search = $result[0];
$snipet = "url('productoption_cart_handle_item', {'operation': 'up', 'cartItemId': CartItem.id";
$replace = $snipet;
$source = str_replace($search, $replace, $source);
}
if(preg_match("/url\('cart\_handle\_item',\s\{'operation'\:\s'remove',\s'productClassId'\:\sProductClass\.id/",$source, $result)){
$search = $result[0];
$snipet = "url('productoption_cart_handle_item', {'operation': 'remove', 'cartItemId': CartItem.id";
$replace = $snipet;
$source = str_replace($search, $replace, $source);
}
if(preg_match("/\<\/div\>[\n|\r\n\\r]\s*<div\sclass\=\"ec\-cartRow\_\_unitPrice\"\>/",$source, $result)){
$search = $result[0];
$replace = "{{ include('@ProductOption42/default/Cart/cart_option.twig') }}" . $search;
$source = str_replace($search, $replace, $source);
}
// 連打防止JavaScriptを{% endblock %}の前に追加
$preventDoubleClickScript = <<<'SCRIPT'
<script>
(function() {
'use strict';
// カート操作の連打防止
let isProcessing = false;
let processingTimeout = null;
document.addEventListener('DOMContentLoaded', function() {
// カート内の数量増減・削除ボタンのフォーム送信を監視
const cartForms = document.querySelectorAll('form[action*="productoption_cart_handle_item"]');
cartForms.forEach(function(form) {
form.addEventListener('submit', function(e) {
// 処理中の場合は送信をキャンセル
if (isProcessing) {
e.preventDefault();
e.stopPropagation();
return false;
}
// 処理中フラグを立てる
isProcessing = true;
// ボタンを無効化して視覚的フィードバック
const submitButton = form.querySelector('button[type="submit"]');
if (submitButton) {
submitButton.disabled = true;
submitButton.style.opacity = '0.5';
submitButton.style.cursor = 'not-allowed';
}
// 3秒後にリセット(念のためのフェイルセーフ)
if (processingTimeout) {
clearTimeout(processingTimeout);
}
processingTimeout = setTimeout(function() {
isProcessing = false;
if (submitButton) {
submitButton.disabled = false;
submitButton.style.opacity = '';
submitButton.style.cursor = '';
}
}, 3000);
});
});
// ページ遷移前にフラグをリセット
window.addEventListener('beforeunload', function() {
isProcessing = false;
if (processingTimeout) {
clearTimeout(processingTimeout);
}
});
});
})();
</script>
SCRIPT;
// {% endblock %}の前にスクリプトを挿入
if (preg_match('/([\r\n]+\{%\s*endblock\s*%\})/', $source, $matches)) {
$source = str_replace($matches[1], $preventDoubleClickScript . $matches[1], $source);
}
$event->setSource($source);
$parameters = $event->getParameters();
$Carts = $parameters['Carts'];
$isDeliveryFree = $parameters['is_delivery_free'];
foreach($Carts as $Cart){
foreach($Cart->getCartItems() as $CartItem){
$flg = $CartItem->getDeliveryFreeFlg();
if($flg == OptionCategory::ON){
if(!$isDeliveryFree[$Cart->getCartKey()]){
$isDeliveryFree[$Cart->getCartKey()] = true;
}
}
}
}
$parameters['is_delivery_free'] = $isDeliveryFree;
$event->setParameters($parameters);
}
}