app/Plugin/ProductOption42/Event/CartEvent.php line 30

Open in your IDE?
  1. <?php
  2. /*
  3. * Plugin Name : ProductOption
  4. *
  5. * Copyright (C) BraTech Co., Ltd. All Rights Reserved.
  6. * http://www.bratech.co.jp/
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Plugin\ProductOption42\Event;
  12. use Eccube\Event\TemplateEvent;
  13. use Plugin\ProductOption42\Entity\OptionCategory;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. class CartEvent implements EventSubscriberInterface
  16. {
  17.     /**
  18.      * @return array
  19.      */
  20.     public static function getSubscribedEvents()
  21.     {
  22.         return [
  23.             'Cart/index.twig' => 'onTemplateCart',
  24.         ];
  25.     }
  26.     public function onTemplateCart(TemplateEvent $event)
  27.     {
  28.         $source $event->getSource();
  29.         if(preg_match("/url\('cart\_handle\_item'\s*,\s*\{'operation'\s*:\s*'down'\s*,\s*'productClassId'\s*:\s*ProductClass\.id/",$source$result)){
  30.             $search $result[0];
  31.             $snipet "url('productoption_cart_handle_item', {'operation': 'down', 'cartItemId': CartItem.id";
  32.             $replace $snipet;
  33.             $source str_replace($search$replace$source);
  34.         }
  35.         if(preg_match("/url\('cart\_handle\_item'\s*,\s*\{'operation'\s*:\s*'up'\s*,\s*'productClassId'\s*:\s*ProductClass\.id/",$source$result)){
  36.             $search $result[0];
  37.             $snipet "url('productoption_cart_handle_item', {'operation': 'up', 'cartItemId': CartItem.id";
  38.             $replace $snipet;
  39.             $source str_replace($search$replace$source);
  40.         }
  41.         if(preg_match("/url\('cart\_handle\_item',\s\{'operation'\:\s'remove',\s'productClassId'\:\sProductClass\.id/",$source$result)){
  42.             $search $result[0];
  43.             $snipet "url('productoption_cart_handle_item', {'operation': 'remove', 'cartItemId': CartItem.id";
  44.             $replace $snipet;
  45.             $source str_replace($search$replace$source);
  46.         }
  47.         if(preg_match("/\<\/div\>[\n|\r\n\\r]\s*<div\sclass\=\"ec\-cartRow\_\_unitPrice\"\>/",$source$result)){
  48.             $search $result[0];
  49.             $replace "{{ include('@ProductOption42/default/Cart/cart_option.twig') }}" $search;
  50.             $source str_replace($search$replace$source);
  51.         }
  52.         // 連打防止JavaScriptを{% endblock %}の前に追加
  53.         $preventDoubleClickScript = <<<'SCRIPT'
  54. <script>
  55. (function() {
  56.     'use strict';
  57.     
  58.     // カート操作の連打防止
  59.     let isProcessing = false;
  60.     let processingTimeout = null;
  61.     
  62.     document.addEventListener('DOMContentLoaded', function() {
  63.         // カート内の数量増減・削除ボタンのフォーム送信を監視
  64.         const cartForms = document.querySelectorAll('form[action*="productoption_cart_handle_item"]');
  65.         
  66.         cartForms.forEach(function(form) {
  67.             form.addEventListener('submit', function(e) {
  68.                 // 処理中の場合は送信をキャンセル
  69.                 if (isProcessing) {
  70.                     e.preventDefault();
  71.                     e.stopPropagation();
  72.                     return false;
  73.                 }
  74.                 
  75.                 // 処理中フラグを立てる
  76.                 isProcessing = true;
  77.                 
  78.                 // ボタンを無効化して視覚的フィードバック
  79.                 const submitButton = form.querySelector('button[type="submit"]');
  80.                 if (submitButton) {
  81.                     submitButton.disabled = true;
  82.                     submitButton.style.opacity = '0.5';
  83.                     submitButton.style.cursor = 'not-allowed';
  84.                 }
  85.                 
  86.                 // 3秒後にリセット(念のためのフェイルセーフ)
  87.                 if (processingTimeout) {
  88.                     clearTimeout(processingTimeout);
  89.                 }
  90.                 processingTimeout = setTimeout(function() {
  91.                     isProcessing = false;
  92.                     if (submitButton) {
  93.                         submitButton.disabled = false;
  94.                         submitButton.style.opacity = '';
  95.                         submitButton.style.cursor = '';
  96.                     }
  97.                 }, 3000);
  98.             });
  99.         });
  100.         
  101.         // ページ遷移前にフラグをリセット
  102.         window.addEventListener('beforeunload', function() {
  103.             isProcessing = false;
  104.             if (processingTimeout) {
  105.                 clearTimeout(processingTimeout);
  106.             }
  107.         });
  108.     });
  109. })();
  110. </script>
  111. SCRIPT;
  112.         // {% endblock %}の前にスクリプトを挿入
  113.         if (preg_match('/([\r\n]+\{%\s*endblock\s*%\})/'$source$matches)) {
  114.             $source str_replace($matches[1], $preventDoubleClickScript $matches[1], $source);
  115.         }
  116.         $event->setSource($source);
  117.         $parameters $event->getParameters();
  118.         $Carts $parameters['Carts'];
  119.         $isDeliveryFree $parameters['is_delivery_free'];
  120.         foreach($Carts as $Cart){
  121.             foreach($Cart->getCartItems() as $CartItem){
  122.                 $flg $CartItem->getDeliveryFreeFlg();
  123.                 if($flg == OptionCategory::ON){
  124.                     if(!$isDeliveryFree[$Cart->getCartKey()]){
  125.                         $isDeliveryFree[$Cart->getCartKey()] = true;
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.         $parameters['is_delivery_free'] = $isDeliveryFree;
  131.         $event->setParameters($parameters);
  132.     }
  133. }