app/Customize/Controller/CustomShoppingController.php line 230

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  * 
  12.  * 
  13.  * 2023/07/13
  14.  * カートに追加→注文手続き画面の間に留意点チェック画面、画像アップロード画面を追加
  15.  * cartとshoppingの間を想定
  16.  * 2024/02/05 k.saito
  17.  * ログイン画面とイメージ画像アップロード画面を逆(アップロード画面を先に表示する)
  18.  * 2024/02/13 k.saito
  19.  *  留意点、カートページを削除
  20.  *  スペルの揺らぎを整理
  21.  *  sendErrorNotifi ⇒ sendErrorNotifiService
  22.  * 2024/04/16 k.saito
  23.  *  すでにアップロード画像があれば、再度アップロード画面に遷移する際に、fileListとしてデータ連携する(imageUpload関数内)
  24.  * 2024/04/24 k.saito
  25.  *  時間切れ、または予約不可のアラートメッセージを追加
  26.  * 2024/05/02 k.saito
  27.  *  アラートメッセージに\nを含んでいた部分を削除
  28.  * 2024/05/06 k.saito
  29.  *  再アップロード対応(一度アップロード済なら、新たなアップロードがあれば更新、新たなアップロードがなくとも次の画面に遷移する)
  30.  * 2024/05/07 k.saito
  31.  *  DBに項目 position を追加し、画像の表示順を管理・制御する
  32.  * 2024/06/20 k.saito
  33.  *  過去の、画像一時フォルダは削除する
  34.  * 
  35.  */
  36. namespace Customize\Controller;
  37. use Eccube\Controller\ShoppingController;
  38. use Eccube\Entity\CustomerAddress;
  39. use Eccube\Entity\Order;
  40. use Eccube\Entity\Shipping;
  41. use Eccube\Event\EccubeEvents;
  42. use Eccube\Event\EventArgs;
  43. use Eccube\Exception\ShoppingException;
  44. use Eccube\Form\Type\Front\CustomerLoginType;
  45. use Eccube\Form\Type\Front\ShoppingShippingType;
  46. use Eccube\Form\Type\Shopping\CustomerAddressType;
  47. use Eccube\Form\Type\Shopping\OrderType;
  48. use Eccube\Repository\OrderRepository;
  49. use Eccube\Repository\TradeLawRepository;
  50. //use Eccube\Service\CartService;
  51. use Eccube\Service\MailService;
  52. //use Eccube\Service\OrderHelper;
  53. use Eccube\Service\Payment\PaymentDispatcher;
  54. use Eccube\Service\Payment\PaymentMethodInterface;
  55. use Eccube\Service\PurchaseFlow\PurchaseContext;
  56. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  57. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  58. use Symfony\Component\DependencyInjection\ContainerInterface;
  59. use Symfony\Component\Form\FormInterface;
  60. use Symfony\Component\HttpFoundation\Request;
  61. use Symfony\Component\HttpFoundation\Response;
  62. use Symfony\Component\Routing\Annotation\Route;
  63. use Symfony\Component\Routing\RouterInterface;
  64. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  65. //追加
  66. //各フォーム用
  67. use Customize\Form\Type\Shopping\AttentionCheckType//留意点チェックフォーム
  68. use Customize\Form\Type\Shopping\imageUploadType//画像アップロードフォーム
  69. use Customize\Entity\Image;
  70. use Eccube\Entity\OrderItem//DB:dtb_order_item
  71. use Customize\Service\categorizationCountFormService;
  72. use Doctrine\ORM\EntityManagerInterface;
  73. use Customize\Service\imageUploadService//画像に名前を付けて保存しファイル名を返す
  74. use Customize\Service\imageUploadInfomationService//画像アップロード用の情報を返す
  75. use Customize\Form\Type\Shopping\CustomOrderType//お届け日、時間帯設定のため
  76. use Customize\Service\getProductOptionService;
  77. use Customize\Service\CustomCartService as CartService;
  78. use Customize\Service\CustomOrderHelper as OrderHelper;
  79. //kintone連携用
  80. use Customize\Service\sendErrorNotifiService//エラー通知用
  81. use Customize\Service\kintoneAddToClientAppService//注文完了時に顧客アプリにレコードを追加する
  82. use Customize\Service\kintoneAddToCaseAppService//注文完了時に案件アプリにレコードを追加する
  83. use Customize\Service\kintoneUpdToScheduleAppService//注文完了時に予定アプリのレコードを更新する
  84. use DateTime;
  85. class CustomShoppingController extends ShoppingController
  86. {
  87.     /**
  88.      * @var CartService
  89.      */
  90.     protected $cartService;
  91.     /**
  92.      * @var MailService
  93.      */
  94.     protected $mailService;
  95.     /**
  96.      * @var OrderHelper
  97.      */
  98.     protected $orderHelper;
  99.     /**
  100.      * @var OrderRepository
  101.      */
  102.     protected $orderRepository;
  103.     /**
  104.      * @var ContainerInterface
  105.      */
  106.     protected $serviceContainer;
  107.     /**
  108.      * @var TradeLawRepository
  109.      */
  110.     protected TradeLawRepository $tradeLawRepository;
  111.     //追加
  112.     //画像アップロードフォーム数判定用
  113.     /**
  114.      * @var categorizationCountFormService
  115.      */
  116.     private $categorizationCountFormService;
  117.     /**
  118.      * @var EntityManagerInterface
  119.      */
  120.     protected $entityManager;
  121.     /**
  122.      * @var imageUploadService
  123.      */
  124.     private $imageUploadService;
  125.     /**
  126.      * @var imageUploadInfomationService
  127.      */
  128.     private $imageUploadInfomationService;
  129.     /**
  130.      * @var getProductOptionService
  131.      */
  132.     protected $getProductOptionService;
  133.     /**
  134.      * @var sendErrorNotifiService
  135.      */
  136.     private $sendErrorNotifiService;
  137.     /**
  138.      * @var kintoneAddToClientAppService
  139.      * 注文完了時にkintone顧客アプリにレコードを登録する
  140.      */
  141.     private $kintoneAddToClientAppService;
  142.     /**
  143.      * @var kintoneAddToCaseAppService
  144.      * 注文完了時にkintone案件アプリにレコードを登録する
  145.      */
  146.     private $kintoneAddToCaseAppService;
  147.     /**
  148.      * @var kintoneUpdToScheduleAppService
  149.      * 注文完了時にkintone予定アプリのレコードを更新する
  150.      */
  151.     private $kintoneUpdToScheduleAppService;
  152.     //追加 ここまで
  153.     public function __construct(
  154.         CartService $cartService,
  155.         MailService $mailService,
  156.         OrderRepository $orderRepository,
  157.         OrderHelper $orderHelper,
  158.         ContainerInterface $serviceContainer,
  159.         TradeLawRepository $tradeLawRepository,
  160.         //追加
  161.         categorizationCountFormService $categorizationCountFormService,
  162.         EntityManagerInterface $entityManager,
  163.         imageUploadService $imageUploadService,
  164.         imageUploadInfomationService $imageUploadInfomationService,
  165.         getProductOptionService $getProductOptionService,
  166.         sendErrorNotifiService $sendErrorNotifiService,
  167.         kintoneAddToClientAppService $kintoneAddToClientAppService,
  168.         kintoneAddToCaseAppService $kintoneAddToCaseAppService,
  169.         kintoneUpdToScheduleAppService $kintoneUpdToScheduleAppService
  170.     ) {
  171.         $this->cartService $cartService;
  172.         $this->mailService $mailService;
  173.         $this->orderRepository $orderRepository;
  174.         $this->orderHelper $orderHelper;
  175.         $this->serviceContainer $serviceContainer;
  176.         $this->tradeLawRepository $tradeLawRepository;
  177.         //追加
  178.         $this->categorizationCountFormService $categorizationCountFormService;
  179.         $this->entityManager $entityManager;  // EntityManager -> entityManager
  180.         $this->imageUploadService $imageUploadService;
  181.         $this->imageUploadInfomationService $imageUploadInfomationService;
  182.         $this->getProductOptionService $getProductOptionService;
  183.         $this->sendErrorNotifiService $sendErrorNotifiService;
  184.         $this->kintoneAddToClientAppService $kintoneAddToClientAppService//kintone顧客アプリにレコードを追加する
  185.         $this->kintoneAddToCaseAppService $kintoneAddToCaseAppService//kintone案件アプリにレコードを追加する
  186.         $this->kintoneUpdToScheduleAppService $kintoneUpdToScheduleAppService//kintone予定アプリのレコードを更新する
  187.     }
  188.     /**
  189.      * 注文手続き画面を表示する
  190.      *
  191.      * 未ログインまたはRememberMeログインの場合はログイン画面に遷移させる.
  192.      * ただし、非会員でお客様情報を入力済の場合は遷移させない.
  193.      *
  194.      * カート情報から受注データを生成し, `pre_order_id`でカートと受注の紐付けを行う.
  195.      * 既に受注が生成されている場合(pre_order_idで取得できる場合)は, 受注の生成を行わずに画面を表示する.
  196.      *
  197.      * purchaseFlowの集計処理実行後, warningがある場合はカートど同期をとるため, カートのPurchaseFlowを実行する.
  198.      *
  199.      * @Route("/shopping", name="shopping", methods={"GET"})
  200.      * @Template("Shopping/index.twig")
  201.      */
  202.     public function index(PurchaseFlow $cartPurchaseFlow)
  203.     {
  204.         // カートチェック.
  205.         log_debug('カスタムカートへ移動');
  206.         $Cart $this->cartService->getCart();
  207.         if (!($Cart && $this->orderHelper->verifyCart($Cart))) {
  208.             // フラッシュメッセージを設定する
  209.             $this->addFlash('worning''お手続き時間が超過したか、ご指定の工事日が予約不可となった可能性があります。申し訳ありませんが、再度お手続きをお願いいたします。');
  210.             log_info('[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.');
  211.             return $this->redirectToRoute('cart');
  212.         }
  213.         //ob_start();
  214.         //画像をアップロードしていない場合は留意点チェック画面に移動 -> 先の画面に進まない
  215.         $cartID $Cart->getID();
  216.         $imageDbData $this->entityManager->getRepository(Image::class)->findBy(['cart_id' => $cartID]);
  217.         //dump($imageDbData);
  218.         if (empty($imageDbData)) {
  219.             // log_info('DBに画像が存在しないので留意点チェック画面に移動_index');
  220.             // return $this->redirectToRoute('attention_check');
  221.             log_info('DBに画像が存在しないのでイメージアップロード画面に戻る');
  222.             return $this->redirectToRoute('image_upload');
  223.         }
  224.         log_info('画像アップロードあり、商品追加なし。通常移動');
  225.         //画像をアップロードしていない場合は留意点チェック画面に移動 end -> 先の画面に進まない
  226.         // ログイン状態のチェック.
  227.         if ($this->orderHelper->isLoginRequired()) {
  228.             log_info('[注文手続] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
  229.             return $this->redirectToRoute('shopping_login');
  230.         }
  231.         // 受注の初期化.
  232.         log_info('[注文手続] 受注の初期化処理を開始します.');
  233.         $Customer $this->getUser() ? $this->getUser() : $this->orderHelper->getNonMember();
  234.         $Order $this->orderHelper->initializeOrder($Cart$Customer);
  235.         // 集計処理.
  236.         log_info('[注文手続] 集計処理を開始します.', [$Order->getId()]);
  237.         $flowResult $this->executePurchaseFlow($Orderfalse);
  238.         //dump($flowResult);
  239.         $this->entityManager->flush();
  240.         //追加 注文情報をImageDBにセットする
  241.         $orderID $Order->getId();
  242.         foreach ($imageDbData as $targetImage) {
  243.             $targetImageId $targetImage->getID();
  244.             $targetImageIdEntity $this->entityManager->getRepository(Image::class)->find($targetImageId); //entityManager
  245.             //dump($targetImageIdEntity);
  246.             $targetImage->setOrder($Order);
  247.         }
  248.         $this->entityManager->persist($targetImage); // Docterineにプロジェクトの保存を伝える
  249.         $this->entityManager->flush(); // クエリ実行(インサート)
  250.         //追加 終わり
  251.         if ($flowResult->hasError()) {
  252.             log_info('[注文手続] Errorが発生したため購入エラー画面へ遷移します.', [$flowResult->getErrors()]);
  253.             return $this->redirectToRoute('shopping_error');
  254.         }
  255.         if ($flowResult->hasWarning()) {
  256.             log_info('[注文手続] Warningが発生しました.', [$flowResult->getWarning()]);
  257.             // 受注明細と同期をとるため, CartPurchaseFlowを実行する
  258.             $cartPurchaseFlow->validate($Cart, new PurchaseContext($Cart$this->getUser()));
  259.             // 注文フローで取得されるカートの入れ替わりを防止する
  260.             // @see https://github.com/EC-CUBE/ec-cube/issues/4293
  261.             $this->cartService->setPrimary($Cart->getCartKey());
  262.         }
  263.         // マイページで会員情報が更新されていれば, Orderの注文者情報も更新する.
  264.         // getIdメソッドは実装されていない。オブジェクトで判定する。
  265.         // if ($Customer->getId()) {
  266.         if ($Customer != null) {
  267.             $this->orderHelper->updateCustomerInfo($Order$Customer);
  268.             $this->entityManager->flush();
  269.         }
  270.         $activeTradeLaws $this->tradeLawRepository->findBy(['displayOrderScreen' => true], ['sortNo' => 'ASC']);
  271.         //お届け日時、お届け時間帯を商品オプションの設置希望日、時間帯に設定する
  272.         //$form = $this->createForm(OrderType::class, $Order);
  273.         //追加 カスタマイズしたShippingTypeを使用するため
  274.         $form $this->createForm(CustomOrderType::class, $Order);
  275.         //対象日・時間帯を非表示ブロックでテンプレートに表示させJSに設定してもらう
  276.         //追加 商品オプションIDから設置希望日、設置希望時間帯を取得する
  277.         //商品オプションのデータを取得
  278.         //dump($this->test());
  279.         //追加 商品オプションIDから設置希望日を取得する
  280.         //dump($Order);
  281.         //dump($orderID);
  282.         //dtb_order_itemから現在追加している商品を取得
  283.         $targetOrderItems = [];
  284.         $OrderItems $this->entityManager->getRepository(OrderItem::class)->findBy(['Order' => $orderID]); //entityManager
  285.         foreach ($OrderItems as $OrderItem) {
  286.             if (!($OrderItem['product_name'] === '手数料' || $OrderItem['product_name'] === '送料')) {
  287.                 $targetOrderItems[] = $OrderItem;
  288.             }
  289.         }
  290.         //dump($targetOrderItems);
  291.         $scheduleDateID $this->serviceContainer->getParameter('option_schedule_date'); //設置希望日のDbIDを取得
  292.         $scheduleTimeID $this->serviceContainer->getParameter('option_schedule_time'); //設置希望時間帯のDbIDを取得
  293.         //$scheduleData = $this->getScheduleData($scheduleOptionID, $targetOrderItems);
  294.         $schedule = [];
  295.         // $scheduleID = $this->container->getParameter($scheduleOption); //商品オプションのDbIDを取得
  296.         $productOption '';
  297.         //$OrderItems = $Shipping->getProductOrderItems();
  298.         //$scheduleは1注文1商品が前提
  299.         foreach ($targetOrderItems as $targetOrderItem) {
  300.             $productOption $targetOrderItem->getOptionSerial(); //商品オプションを取得
  301.             $scheduleDate $this->getProductOptionService->getTextOptionData($productOption$scheduleDateID);
  302.             $schedule['date'] = str_replace('-''/'$scheduleDate);
  303.             $schedule['time'] = $this->getProductOptionService->getTextOptionData($productOption$scheduleTimeID);
  304.         }
  305.         //dump($schedule);
  306.         //追加 ここまで
  307.         return [
  308.             'form' => $form->createView(),
  309.             'Order' => $Order,
  310.             'activeTradeLaws' => $activeTradeLaws,
  311.             'schedule' => $schedule
  312.         ];
  313.     }
  314.     /**
  315.      * 留意点チェック画面
  316.      *
  317.      * @Route("/shopping/check", name="attention_check", methods={"POST","GET"})
  318.      * @Template("/Shopping/attention_check.twig")
  319.      * 
  320.      */
  321.     public function check(Request $request)
  322.     {
  323.         //全てのチェックが完了すると次の画面へ遷移する
  324.         log_info('留意点チェック画面');
  325.         $Cart $this->cartService->getCart(); //現在のカート情報を取得
  326.         //セッションが切れた場合はカート画面へリダイレクトさせる        
  327.         if (!($Cart && $this->orderHelper->verifyCart($Cart))) {
  328.             log_info('[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.');
  329.             return $this->redirectToRoute('cart');
  330.         }
  331.         $categoryId $this->categorizationCountFormService->returnFormNumber(); //カテゴリのDBIDを取得
  332.         //dump($categoryId);
  333.         $formArray = array();
  334.         foreach ($categoryId as $categoryIdData) {
  335.             $fieldData $this->imageUploadInfomationService->returnFormInfomation($categoryIdData);
  336.             //dump($fieldData);
  337.             if (is_array($fieldData)) {
  338.                 $formArray[] = $fieldData;
  339.             }
  340.         }
  341.         foreach ($formArray as $formArrayData) {
  342.             $check_form_data $formArrayData['check_data'];
  343.         }
  344.         $form $this->createForm(AttentionCheckType::class, null,  ['check_data' => $check_form_data]); //
  345.         $form->handleRequest($request);
  346.         if ($form->isSubmitted() && $form->isValid()) {
  347.             /*
  348.             $check1 = $form->get('1')->getData();
  349.             */
  350.             log_info('全てチェック済み、画像アップロード画面に遷移する');
  351.             return $this->redirectToRoute('image_upload');
  352.         } else {
  353.             log_info('留意点チェックなし。警告を表示する');
  354.         }
  355.         return [
  356.             //'request' => $request,
  357.             'form' => $form->createView(),
  358.             'formArray' => $formArray
  359.         ];
  360.     }
  361.     /**
  362.      * 画像アップロード画面
  363.      *
  364.      * @Route("/shopping/image_upload", name="image_upload", methods={"GET","POST"})
  365.      * @Template("/Shopping/image_upload.twig")
  366.      */
  367.     public function imageUpload(Request $request)
  368.     {
  369.         //全てのチェックが完了すると次の画面へ遷移する
  370.         log_info('画像アップロード画面 imageUpload start');
  371.         //二重投稿になるためcartidがある場合は以前のデータを削除する
  372.         $Cart $this->cartService->getCart(); //現在のカート情報を取得
  373.         //セッションが切れた場合はカート画面へリダイレクトさせる
  374.         if (!($Cart && $this->orderHelper->verifyCart($Cart))) {
  375.             // フラッシュメッセージを設定する
  376.             $this->addFlash('worning''お手続き時間が超過したか、ご指定の工事日が予約不可となった可能性があります。申し訳ありませんが、再度お手続きをお願いいたします。');
  377.             log_info('[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.');
  378.             return $this->redirectToRoute('cart');
  379.         }
  380.         $cartID $Cart->getID();
  381.         //条件:cartID一致、upload_order 降順、position 昇順
  382.         $imageDbData $this->entityManager->getRepository(Image::class)->findBy(['cart_id' => $cartID], ['upload_order' => 'desc''position' => 'asc']);   //entityManager
  383.         //dump($imageDbData);
  384.         //アップロード画像があれば、一時フォルダ作成
  385.         $imagePath $this->imageUploadService->getPriveteImagePath();  //from path;
  386.         log_info('imagePath: '.$imagePath);
  387.         $tempPathCart '';
  388.         $tempPathCartForJs '';
  389.         $fileList = [];
  390.         if (count($imageDbData) > 0) {
  391.             $tempPath $this->imageUploadService->getTemporaryImagePath();
  392.             //日付が昨日以前のフォルダがあれば削除する
  393.             // 昨日の日付を取得
  394.             $yesterday = (new DateTime('yesterday'))->setTime(00);
  395.             // 指定されたフォルダの下のサブフォルダを取得
  396.             $directories array_filter(glob($tempPath '/*'), 'is_dir');
  397.             foreach ($directories as $dir) {
  398.                 log_info('dir: '.$dir);
  399.                 // フォルダの作成日時を取得
  400.                 $creationTime filemtime($dir);
  401.                 log_info('creationTime: '.$creationTime);
  402.                 log_info('dir_timestamp: '.$yesterday->getTimestamp());
  403.                 // 昨日までのフォルダのみ削除
  404.                 if ($creationTime $yesterday->getTimestamp()) {
  405.                     $this->deleteDirectory($dir);
  406.                 }
  407.             }
  408.             $tempPathCart $tempPath.$cartID.'/';
  409.             $tempPathCartForJs '/temp/'.$cartID.'/';  //homeのrootからのパス
  410.             log_info('tempPathCart: '.$tempPathCart);
  411.             if (!is_dir($tempPathCart)) {    //フォルダがなかったら、作成
  412.                 mkdir($tempPathCart0755);  //カートIDのフォルダを生成  //to path
  413.             } else {
  414.                 //内部のファイルを削除
  415.                 $files glob($tempPathCart.'*.*');
  416.                 foreach ($files as $file) {
  417.                     unlink($file);
  418.                     log_info('delete file: '.$file);
  419.                 }
  420.             }
  421.             $firstFlg true;
  422.             $save_uploadOrder '1';
  423.             foreach ($imageDbData as $imageData) {
  424.                 if ($firstFlg) {
  425.                     $save_uploadOrder $imageData->getUploadOrder();
  426.                     $firstFlg false;
  427.                 }
  428.                 $uploadOrder $imageData->getUploadOrder();
  429.                 if ($uploadOrder != $save_uploadOrder) {
  430.                     log_info('uploadOrderが変わった');
  431.                     break;  //uploadOrderが変わったら処理終了
  432.                 }
  433.                 log_info('ファイル名:');
  434.                 log_info($imageData->getName());
  435.                 log_info('UploadOrder:');
  436.                 log_info($imageData->getUploadOrder());
  437.                 $fileName $imageData->getName();
  438.                 //ファイルをコピー
  439.                 copy($imagePath.$fileName$tempPathCart.$fileName);
  440.                 $fileList[] = $tempPathCartForJs.$fileName;
  441.             }
  442.         }
  443.         $uploadOrder 1//何回目の投稿か? 1回目の投稿
  444.         if (!empty($imageDbData)) {
  445.             log_info('カート情報が存在するので、判別の為に何回目の投稿かアップロード順を登録');
  446.             $uploadOrder $imageDbData[0]->getUploadOrder();
  447.             $uploadOrder++;
  448.         }
  449.         $categoryId $this->categorizationCountFormService->returnFormNumber();
  450.         //dump($categoryId);
  451.         $formArray = array();
  452.         foreach ($categoryId as $categoryIdData) {
  453.             $fieldData $this->imageUploadInfomationService->returnFormInfomation($categoryIdData);
  454.             //dump($fieldData);
  455.             if (is_array($fieldData)) {
  456.                 $formArray[] = $fieldData;
  457.             }
  458.         }
  459.         //dump($formArray);
  460.         //画像アップロードフォームの数 複数商品をカートに入れた場合はその分フォーム数を増やす(現在は1カート1商品のみなので増える事はない))
  461.         $upload_field_max 0;
  462.         foreach ($formArray as $formArrayData) {
  463.             $upload_field_max += $formArrayData['upload_field_max'];
  464.         }
  465.         //dump($numberOfForms);
  466.         $Image = new Image;
  467.         $form $this->createForm(imageUploadType::class, $Image, ['upload_field_max' => $upload_field_max]);
  468.         //form追加後 
  469.         $form->handleRequest($request);
  470.         if (
  471.             $form->isSubmitted() && $form->isValid()
  472.         ) {
  473.             //写真が新規にアップロードされた場合
  474.             if ($Image instanceof Image) {
  475.                 log_info('Image2');
  476.                 $file = array();
  477.                 for ($i 0$i $upload_field_max$i++) {
  478.                     $file[] = $form['image' $i]->getData();
  479.                 }
  480.                 log_debug('image_dataの配列データ:');
  481.                 log_debug(print_r($filetrue));
  482.                 if (!empty($file)) {
  483.                     // カートサービスからカート内の商品情報を取得
  484.                     $Cart $this->cartService->getCart();
  485.                     $cartID $Cart->getID();
  486.                     // ファイルアップロード
  487.                     $count 0;
  488.                     foreach ($file as $upload_image) {
  489.                         $count++;
  490.                         log_debug($upload_image);
  491.                         $filename $this->imageUploadService->upload($upload_image);
  492.                         //dump($filename);
  493.                         //DBにファイル名とカートキーを書き込み
  494.                         //dump($Cart);
  495.                         $Image = new Image;
  496.                         $Image->setCartID($cartID);
  497.                         $Image->setName($filename);
  498.                         $Image->setUploadOrder($uploadOrder);
  499.                         $Image->setPosition($count 1);    //表示位置セット
  500.                         //dump($Image);
  501.                         $this->entityManager->persist($Image); // Docterineにプロジェクトの保存を伝える
  502.                         $this->entityManager->flush(); // クエリ実行(インサート)
  503.                     }
  504.                     return $this->redirectToRoute('shopping');
  505.                 }
  506.             } else {
  507.                 log_error('画像がありません');
  508.                 if (count($imageDbData) > 0) {  //再アップロードなら、次画面に遷移
  509.                     log_error('画像の変更なし');
  510.                     return $this->redirectToRoute('shopping');
  511.                 }
  512.             }
  513.         } else if ($form->isSubmitted()) {
  514.             // debug
  515.             //写真が再アップロードされた場合
  516.             log_info('debug image_upload: not isValid ');
  517.             if ($Image instanceof Image) {
  518.                 $file = array();
  519.                 for ($i 0$i $upload_field_max$i++) {
  520.                     $file[] = $form['image' $i]->getData();
  521.                 }
  522.                 log_debug('image_dataの配列データ:');
  523.                 log_debug(print_r($filetrue));
  524.                 if (count($imageDbData) > 0) {  //再アップロードなら、次画面に遷移
  525.                     log_info('Image 再アップロード');
  526.                     // カートサービスからカート内の商品情報を取得
  527.                     $Cart $this->cartService->getCart();
  528.                     $cartID $Cart->getID();
  529.                     // ファイルアップロード
  530.                     $count 0;
  531.                     foreach ($file as $upload_image) {
  532.                         $count++;
  533.                         if ($upload_image == '') {
  534.                             //空白の場合は、orderのみ更新
  535.                             log_info('orderのみ更新');
  536.                             $Image $imageDbData[$count 1];
  537.                             $Image->setUploadOrder($uploadOrder);
  538.                             $Image->setPosition($count 1);    //表示位置セット
  539.                             $this->entityManager->persist($Image); // Docterineにプロジェクトの保存を伝える
  540.                             $this->entityManager->flush(); // クエリ実行(インサート)
  541.                         } else {
  542.                             //画像変更
  543.                             log_debug($upload_image);
  544.                             $filename $this->imageUploadService->upload($upload_image);
  545.                             //dump($filename);
  546.                             //DBにファイル名とカートキーを書き込み
  547.                             //dump($Cart);
  548.                             $Image = new Image;
  549.                             $Image->setCartID($cartID);
  550.                             $Image->setPosition($count 1);    //表示位置セット
  551.                             $Image->setName($filename);
  552.                             $Image->setUploadOrder($uploadOrder);
  553.                             //dump($Image);
  554.                             $this->entityManager->persist($Image); // Docterineにプロジェクトの保存を伝える
  555.                             $this->entityManager->flush(); // クエリ実行(インサート)
  556.                         }
  557.                     }
  558.                     return $this->redirectToRoute('shopping');
  559.                 }
  560.             }
  561.         } else {
  562.             //debug
  563.             log_info('debug image_upload: not isValid and not isSubmitted');
  564.         }
  565.         //form追加後 end
  566.         return [
  567.             'request' => $request,
  568.             'formArray' => $formArray,
  569.             'fileList' => $fileList,
  570.             'form' => $form->createView(),
  571.         ];
  572.     }
  573.     /**
  574.      * 注文確認画面を表示する.
  575.      *
  576.      * ここではPaymentMethod::verifyがコールされます.
  577.      * PaymentMethod::verifyではクレジットカードの有効性チェック等, 注文手続きを進められるかどうかのチェック処理を行う事を想定しています.
  578.      * PaymentMethod::verifyでエラーが発生した場合は, 注文手続き画面へリダイレクトします.
  579.      *
  580.      * @Route("/shopping/confirm", name="shopping_confirm", methods={"POST"})
  581.      * @Template("Shopping/confirm.twig")
  582.      */
  583.     public function confirm(Request $request)
  584.     {
  585.         log_info('注文確認画面 confirm(url: shopping_confirm) start');
  586.         // ログイン状態のチェック.
  587.         if ($this->orderHelper->isLoginRequired()) {
  588.             log_info('[注文確認] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
  589.             return $this->redirectToRoute('shopping_login');
  590.         }
  591.         // 受注の存在チェック
  592.         $preOrderId $this->cartService->getPreOrderId();
  593.         $Order $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
  594.         if (!$Order) {
  595.             log_info('[注文確認] 購入処理中の受注が存在しません.', [$preOrderId]);
  596.             return $this->redirectToRoute('shopping_error');
  597.         }
  598.         //画像をアップロードしていない場合は留意点チェック画面に移動⇒画像アップロード画面の移動する
  599.         //画像がある場合は画像のURLを配列に格納する
  600.         $orderId $Order->getId();
  601.         $imageDbData $this->entityManager->getRepository(Image::class)->findBy(['Order' => $orderId]);    //entityManager
  602.         //dump($imageDbData);
  603.         if (empty($imageDbData)) {
  604.             log_info('DBに画像が存在しないので画像アップロード画面の移動');
  605.             // return $this->redirectToRoute('attention_check');
  606.             return $this->redirectToRoute('image_upload');
  607.         }
  608.         $imageNameArray = [];
  609.         foreach ($imageDbData as $imageData) {
  610.             $imageNameArray[] = $imageData->getName();
  611.         }
  612.         dump($imageNameArray);
  613.         //画像をアップロードしていない場合は留意点チェック画面に移動 end
  614.         $activeTradeLaws $this->tradeLawRepository->findBy(['displayOrderScreen' => true], ['sortNo' => 'ASC']);
  615.         $form $this->createForm(OrderType::class, $Order);
  616.         $form->handleRequest($request);
  617.         if ($form->isSubmitted() && $form->isValid()) {
  618.             log_info('[注文確認] 集計処理を開始します.', [$Order->getId()]);
  619.             $response $this->executePurchaseFlow($Order);
  620.             $this->entityManager->flush();
  621.             if ($response) {
  622.                 return $response;
  623.             }
  624.             log_info('[注文確認] PaymentMethod::verifyを実行します.', [$Order->getPayment()->getMethodClass()]);
  625.             $paymentMethod $this->createPaymentMethod($Order$form);
  626.             $PaymentResult $paymentMethod->verify();
  627.             if ($PaymentResult) {
  628.                 if (!$PaymentResult->isSuccess()) {
  629.                     $this->entityManager->rollback();
  630.                     foreach ($PaymentResult->getErrors() as $error) {
  631.                         $this->addError($error);
  632.                     }
  633.                     log_info('[注文確認] PaymentMethod::verifyのエラーのため, 注文手続き画面へ遷移します.', [$PaymentResult->getErrors()]);
  634.                     return $this->redirectToRoute('shopping');
  635.                 }
  636.                 $response $PaymentResult->getResponse();
  637.                 if ($response instanceof Response && ($response->isRedirection() || $response->isSuccessful())) {
  638.                     $this->entityManager->flush();
  639.                     log_info('[注文確認] PaymentMethod::verifyが指定したレスポンスを表示します.');
  640.                     return $response;
  641.                 }
  642.             }
  643.             dump('confirm start');
  644.             dump($Order);
  645.             $this->entityManager->flush();
  646.             dump('confirm 1');
  647.             log_info('[注文確認] 注文確認画面を表示します.');
  648.             return [
  649.                 'form' => $form->createView(),
  650.                 'Order' => $Order,
  651.                 'activeTradeLaws' => $activeTradeLaws,
  652.                 'imageNameArray' => $imageNameArray
  653.             ];
  654.         }
  655.         dump($form->getErrors());
  656.         dump($form->getErrors(true));
  657.         log_info('[注文確認] フォームエラーのため, 注文手続画面を表示します.', [$Order->getId()]);
  658.         $template = new Template([
  659.             'owner' => [$this'confirm'],
  660.             'template' => 'Shopping/index.twig',
  661.         ]);
  662.         $request->attributes->set('_template'$template);
  663.         return [
  664.             'form' => $form->createView(),
  665.             'Order' => $Order,
  666.             'activeTradeLaws' => $activeTradeLaws,
  667.         ];
  668.     }
  669.     /**
  670.      * 注文処理を行う.
  671.      *
  672.      * 決済プラグインによる決済処理および注文の確定処理を行います.
  673.      *
  674.      * @Route("/shopping/checkout", name="shopping_checkout", methods={"POST"})
  675.      * @Template("Shopping/confirm.twig")
  676.      */
  677.     public function checkout(Request $request)
  678.     {
  679.         // ログイン状態のチェック.
  680.         if ($this->orderHelper->isLoginRequired()) {
  681.             log_info('[注文処理] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
  682.             return $this->redirectToRoute('shopping_login');
  683.         }
  684.         // 受注の存在チェック
  685.         $preOrderId $this->cartService->getPreOrderId();
  686.         $Order $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
  687.         if (!$Order) {
  688.             log_info('[注文処理] 購入処理中の受注が存在しません.', [$preOrderId]);
  689.             return $this->redirectToRoute('shopping_error');
  690.         }
  691.         //画像をアップロードしていない場合は留意点チェック画面に移動⇒画像アップロード画面に移動する
  692.         $orderId $Order->getId();
  693.         $imageDbData $this->entityManager->getRepository(Image::class)->findBy(['Order' => $orderId]);    //entityManager
  694.         //dump($imageDbData);
  695.         if (empty($imageDbData)) {
  696.             // log_info('DBに画像が存在しないので留意点チェック画面に移動_checkout');
  697.             log_info('DBに画像が存在しないので画像アップロード画面に移動');
  698.             // return $this->redirectToRoute('attention_check');
  699.             return $this->redirectToRoute('image_upload');
  700.         }
  701.         //画像をアップロードしていない場合は留意点チェック画面に移動 end
  702.         // フォームの生成.
  703.         $form $this->createForm(OrderType::class, $Order, [
  704.             // 確認画面から注文処理へ遷移する場合は, Orderエンティティで値を引き回すためフォーム項目の定義をスキップする.
  705.             'skip_add_form' => true,
  706.         ]);
  707.         $form->handleRequest($request);
  708.         if ($form->isSubmitted() && $form->isValid()) {
  709.             log_info('[注文処理] 注文処理を開始します.', [$Order->getId()]);
  710.             try {
  711.                 /*
  712.                  * 集計処理
  713.                  */
  714.                 log_info('[注文処理] 集計処理を開始します.', [$Order->getId()]);
  715.                 $response $this->executePurchaseFlow($Order);
  716.                 $this->entityManager->flush();
  717.                 if ($response) {
  718.                     return $response;
  719.                 }
  720.                 log_info('[注文処理] PaymentMethodを取得します.', [$Order->getPayment()->getMethodClass()]);
  721.                 $paymentMethod $this->createPaymentMethod($Order$form);
  722.                 /*
  723.                  * 決済実行(前処理)
  724.                  */
  725.                 log_info('[注文処理] PaymentMethod::applyを実行します.');
  726.                 if ($response $this->executeApply($paymentMethod)) {
  727.                     return $response;
  728.                 }
  729.                 /*
  730.                  * 決済実行
  731.                  *
  732.                  * PaymentMethod::checkoutでは決済処理が行われ, 正常に処理出来た場合はPurchaseFlow::commitがコールされます.
  733.                  */
  734.                 log_info('[注文処理] PaymentMethod::checkoutを実行します.');
  735.                 if ($response $this->executeCheckout($paymentMethod)) {
  736.                     return $response;
  737.                 }
  738.                 $this->entityManager->flush();
  739.                 //修正 追加
  740.                 /*
  741.                  * 注文完了時に顧客アプリ、案件アプリ、予定アプリにkintoneにレコードを追加する
  742.                  */
  743.                 $CustomerSearchKey ''//顧客検索キー
  744.                 log_info('[注文処理] kintone顧客アプリに注文情報を追加します。', [$Order->getId()]);
  745.                 dump('[注文処理] kintone顧客アプリに注文情報を追加します。', [$Order->getId()]);
  746.                 dump($Order);
  747.                 $CustomerSearchKey $this->kintoneAddToClientAppService->insClientRecordFromShopping($Order);
  748.                 dump($CustomerSearchKey);
  749.                 if ($CustomerSearchKey === false) {
  750.                     $errormsg __LINE__ '注文完了時:kintone顧客アプリのレコード追加でエラーが発生。';
  751.                     log_error($errormsg);
  752.                     $this->sendErrorNotifiService->errorNotifi($errormsg);
  753.                     throw new ShoppingException('予期しないエラーが発生しました.');
  754.                 }
  755.                 //案件アプリにレコード追加。追加が完了した場合はコメントを投稿する
  756.                 log_info('[注文処理] kintone案件アプリに注文情報を追加します。', [$Order->getId()]);
  757.                 //追加に成功した際は追加した案件アプリのレコード番号、予定アプリで使用する情報が入る
  758.                 $scheduleAppInfo $this->kintoneAddToCaseAppService->insCaseRecordFromShopping($Order$CustomerSearchKey);
  759.                 if ($scheduleAppInfo === false) {
  760.                     $errormsg __LINE__ '注文完了時:kintone案件アプリのレコード追加でエラーが発生。';
  761.                     log_error($errormsg);
  762.                     $this->sendErrorNotifiService->errorNotifi($errormsg);
  763.                     throw new ShoppingException('予期しないエラーが発生しました.');
  764.                 }
  765.                 //予定アプリのレコード更新
  766.                 log_info('[注文処理] kintone予定アプリに注文情報を追加します。', [$Order->getId()]);
  767.                 $scheduleAppResult $this->kintoneUpdToScheduleAppService->updScheduleRecordFromShopping($scheduleAppInfo);
  768.                 if ($scheduleAppResult === false) {
  769.                     $errormsg __LINE__ '注文完了時:kintone予定アプリのレコード更新でエラーが発生。';
  770.                     log_error($errormsg);
  771.                     $this->sendErrorNotifiService->errorNotifi($errormsg);
  772.                     throw new ShoppingException('予期しないエラーが発生しました.');
  773.                 }
  774.                 //修正 終わり
  775.                 log_info('[注文処理] 注文処理が完了しました.', [$Order->getId()]);
  776.             } catch (ShoppingException $e) {
  777.                 log_error('[注文処理] 購入エラーが発生しました.', [$e->getMessage()]);
  778.                 $this->entityManager->rollback();
  779.                 $this->addError($e->getMessage());
  780.                 return $this->redirectToRoute('shopping_error');
  781.             } catch (\Exception $e) {
  782.                 log_error('[注文処理] 予期しないエラーが発生しました.', [$e->getMessage()]);
  783.                 $this->entityManager->rollback(); //FIXME ユニットテストで There is no active transaction エラーになってしまう
  784.                 $this->addError('front.shopping.system_error');
  785.                 return $this->redirectToRoute('shopping_error');
  786.             }
  787.             // カート削除
  788.             log_info('[注文処理] カートをクリアします.', [$Order->getId()]);
  789.             $this->cartService->clear();
  790.             // 受注IDをセッションにセット
  791.             $this->session->set(OrderHelper::SESSION_ORDER_ID$Order->getId());
  792.             // メール送信
  793.             log_info('[注文処理] 注文メールの送信を行います.', [$Order->getId()]);
  794.             $this->mailService->sendOrderMail($Order);
  795.             $this->entityManager->flush();
  796.             log_info('[注文処理] 注文処理が完了しました. 購入完了画面へ遷移します.', [$Order->getId()]);
  797.             return $this->redirectToRoute('shopping_complete');
  798.         }
  799.         log_info('[注文処理] フォームエラーのため, 購入エラー画面へ遷移します.', [$Order->getId()]);
  800.         return $this->redirectToRoute('shopping_error');
  801.     }
  802.     /**
  803.      * 購入完了画面を表示する.
  804.      *
  805.      * @Route("/shopping/complete", name="shopping_complete", methods={"GET"})
  806.      * @Template("Shopping/complete.twig")
  807.      */
  808.     public function complete(Request $request)
  809.     {
  810.         log_info('[注文完了] 注文完了画面を表示します.');
  811.         // 受注IDを取得
  812.         $orderId $this->session->get(OrderHelper::SESSION_ORDER_ID);
  813.         if (empty($orderId)) {
  814.             log_info('[注文完了] 受注IDを取得できないため, トップページへ遷移します.');
  815.             return $this->redirectToRoute('homepage');
  816.         }
  817.         $Order $this->orderRepository->find($orderId);
  818.         $event = new EventArgs(
  819.             [
  820.                 'Order' => $Order,
  821.             ],
  822.             $request
  823.         );
  824.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_SHOPPING_COMPLETE_INITIALIZE);
  825.         if ($event->getResponse() !== null) {
  826.             return $event->getResponse();
  827.         }
  828.         log_info('[注文完了] 購入フローのセッションをクリアします. ');
  829.         $this->orderHelper->removeSession();
  830.         $hasNextCart = !empty($this->cartService->getCarts());
  831.         log_info('[注文完了] 注文完了画面を表示しました. ', [$hasNextCart]);
  832.         return [
  833.             'Order' => $Order,
  834.             'hasNextCart' => $hasNextCart,
  835.         ];
  836.     }
  837.     /**
  838.      * PaymentMethodをコンテナから取得する.
  839.      *
  840.      * @param Order $Order
  841.      * @param FormInterface $form
  842.      *
  843.      * @return PaymentMethodInterface
  844.      */
  845.     private function createPaymentMethod(Order $OrderFormInterface $form)
  846.     {
  847.         $PaymentMethod $this->serviceContainer->get($Order->getPayment()->getMethodClass());
  848.         $PaymentMethod->setOrder($Order);
  849.         $PaymentMethod->setFormType($form);
  850.         return $PaymentMethod;
  851.     }
  852.     /**
  853.      * PaymentMethod::applyを実行する.
  854.      *
  855.      * @param PaymentMethodInterface $paymentMethod
  856.      *
  857.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
  858.      */
  859.     protected function executeApply(PaymentMethodInterface $paymentMethod)
  860.     {
  861.         $dispatcher $paymentMethod->apply(); // 決済処理中.
  862.         // リンク式決済のように他のサイトへ遷移する場合などは, dispatcherに処理を移譲する.
  863.         if ($dispatcher instanceof PaymentDispatcher) {
  864.             $response $dispatcher->getResponse();
  865.             $this->entityManager->flush();
  866.             // dispatcherがresponseを保持している場合はresponseを返す
  867.             if ($response instanceof Response && ($response->isRedirection() || $response->isSuccessful())) {
  868.                 log_info('[注文処理] PaymentMethod::applyが指定したレスポンスを表示します.');
  869.                 return $response;
  870.             }
  871.             // forwardすることも可能.
  872.             if ($dispatcher->isForward()) {
  873.                 log_info(
  874.                     '[注文処理] PaymentMethod::applyによりForwardします.',
  875.                     [$dispatcher->getRoute(), $dispatcher->getPathParameters(), $dispatcher->getQueryParameters()]
  876.                 );
  877.                 return $this->forwardToRoute(
  878.                     $dispatcher->getRoute(),
  879.                     $dispatcher->getPathParameters(),
  880.                     $dispatcher->getQueryParameters()
  881.                 );
  882.             } else {
  883.                 log_info(
  884.                     '[注文処理] PaymentMethod::applyによりリダイレクトします.',
  885.                     [$dispatcher->getRoute(), $dispatcher->getPathParameters(), $dispatcher->getQueryParameters()]
  886.                 );
  887.                 return $this->redirectToRoute(
  888.                     $dispatcher->getRoute(),
  889.                     array_merge($dispatcher->getPathParameters(), $dispatcher->getQueryParameters())
  890.                 );
  891.             }
  892.         }
  893.     }
  894.     /**
  895.      * PaymentMethod::checkoutを実行する.
  896.      *
  897.      * @param PaymentMethodInterface $paymentMethod
  898.      *
  899.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response|null
  900.      */
  901.     protected function executeCheckout(PaymentMethodInterface $paymentMethod)
  902.     {
  903.         $PaymentResult $paymentMethod->checkout();
  904.         $response $PaymentResult->getResponse();
  905.         // PaymentResultがresponseを保持している場合はresponseを返す
  906.         if ($response instanceof Response && ($response->isRedirection() || $response->isSuccessful())) {
  907.             $this->entityManager->flush();
  908.             log_info('[注文処理] PaymentMethod::checkoutが指定したレスポンスを表示します.');
  909.             return $response;
  910.         }
  911.         // エラー時はロールバックして購入エラーとする.
  912.         if (!$PaymentResult->isSuccess()) {
  913.             $this->entityManager->rollback();
  914.             foreach ($PaymentResult->getErrors() as $error) {
  915.                 $this->addError($error);
  916.             }
  917.             log_info('[注文処理] PaymentMethod::checkoutのエラーのため, 購入エラー画面へ遷移します.', [$PaymentResult->getErrors()]);
  918.             return $this->redirectToRoute('shopping_error');
  919.         }
  920.         return null;
  921.     }
  922.     // ディレクトリを削除する関数
  923.     protected function deleteDirectory($dirPath) {
  924.         if (substr($dirPathstrlen($dirPath) - 11) != '/') {
  925.             $dirPath .= '/';
  926.         }
  927.         $files glob($dirPath '*'GLOB_MARK);
  928.         foreach ($files as $file) {
  929.             unlink($file);  //内部ファイルを削除
  930.         }
  931.         rmdir($dirPath);    //フォルダ削除
  932.     }
  933. }