app/Customize/Controller/Admin/SetProduct/SetProductController.php line 752

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. namespace Customize\Controller\Admin\SetProduct;
  13. use Customize\Repository\SchoolRepository;
  14. use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
  15. use Eccube\Common\Constant;
  16. use Eccube\Controller\AbstractController;
  17. use Eccube\Entity\BaseInfo;
  18. use Eccube\Entity\Master\ProductStatus;
  19. use Eccube\Entity\Product;
  20. use Eccube\Entity\ProductCategory;
  21. use Eccube\Entity\ProductClass;
  22. use Eccube\Entity\ProductStock;
  23. use Customize\Entity\SetProductImage;
  24. use Customize\Entity\SetProduct;
  25. use Eccube\Event\EccubeEvents;
  26. use Eccube\Entity\ProductImage;
  27. use Eccube\Event\EventArgs;
  28. use Customize\Form\Type\Admin\SetProductType;
  29. use Customize\Form\Type\Admin\SearchSetProductType;
  30. use Eccube\Repository\BaseInfoRepository;
  31. use Eccube\Repository\CategoryRepository;
  32. use Eccube\Repository\Master\PageMaxRepository;
  33. use Eccube\Repository\Master\ProductStatusRepository;
  34. use Customize\Repository\SetProductRepository;
  35. use Customize\Repository\SetProductImageRepository;
  36. use Customize\Repository\SetProductProductRepository;
  37. use Customize\Repository\RecommendRepository;
  38. use Eccube\Repository\ProductImageRepository;
  39. use Eccube\Repository\ProductRepository;
  40. use Eccube\Repository\ProductClassRepository;
  41. use Eccube\Repository\ProductStockRepository;
  42. use Eccube\Repository\Master\SaleTypeRepository;
  43. use Eccube\Util\CacheUtil;
  44. use Eccube\Util\FormUtil;
  45. use Knp\Component\Pager\PaginatorInterface;
  46. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  47. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  48. use Symfony\Component\Filesystem\Filesystem;
  49. use Symfony\Component\HttpFoundation\File\File;
  50. use Symfony\Component\HttpFoundation\RedirectResponse;
  51. use Symfony\Component\HttpFoundation\Request;
  52. use Symfony\Component\HttpFoundation\StreamedResponse;
  53. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  54. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  55. use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
  56. use Symfony\Component\Routing\Annotation\Route;
  57. use Symfony\Component\Routing\RouterInterface;
  58. class SetProductController extends AbstractController
  59. {
  60.     /**
  61.      * @var SetProductImageRepository
  62.      */
  63.     protected $setProductImageRepository;
  64.     /**
  65.      * @var ProductImageRepository
  66.      */
  67.     protected $productImageRepository;
  68.     /**
  69.      * @var CategoryRepository
  70.      */
  71.     protected $categoryRepository;
  72.     /**
  73.      * @var SetProductRepository
  74.      */
  75.     protected $setProductRepository;
  76.     /**
  77.      * @var SetProductProductRepository
  78.      */
  79.     protected $setProductProductRepository;
  80.     /**
  81.      * @var ProductRepository
  82.      */
  83.     protected $productRepository;
  84.     /**
  85.      * @var ProductClassRepository
  86.      */
  87.     protected $productClassRepository;
  88.     /**
  89.      * @var ProductStockRepository
  90.      */
  91.     protected $productStockRepository;
  92.     /**
  93.      * @var BaseInfo
  94.      */
  95.     protected $BaseInfo;
  96.     /**
  97.      * @var PageMaxRepository
  98.      */
  99.     protected $pageMaxRepository;
  100.     /**
  101.      * @var ProductStatusRepository
  102.      */
  103.     protected $productStatusRepository;
  104.     /**
  105.      * @var SchoolRepository
  106.      */
  107.     protected $schoolRepository;
  108.     /**
  109.      * @var SaleTypeRepository
  110.      */
  111.     protected $saleTypeRepository;
  112.     /**
  113.      * @var RecommendRepository
  114.      */
  115.     protected $recommendRepository;
  116.     /**
  117.      * SetProductController constructor.
  118.      *
  119.      * @param SetProductImageRepository $setProductImageRepository
  120.      * @param CategoryRepository $categoryRepository
  121.      * @param ProductRepository $productRepository
  122.      * @param BaseInfoRepository $baseInfoRepository
  123.      * @param PageMaxRepository $pageMaxRepository
  124.      * @param ProductStatusRepository $productStatusRepository
  125.      * @param SchoolRepository $schoolRepository
  126.      * @param SetProductProductRepository $setProductProductRepository
  127.      * @param ProductClassRepository $productClassRepository
  128.      * @param ProductStockRepository $productStockRepository
  129.      * @param ProductImageRepository $productImageRepository
  130.      * @param RecommendRepository $recommendRepository
  131.      */
  132.     public function __construct(
  133.         SetProductImageRepository $setProductImageRepository,
  134.         CategoryRepository $categoryRepository,
  135.         ProductRepository $productRepository,
  136.         BaseInfoRepository $baseInfoRepository,
  137.         PageMaxRepository $pageMaxRepository,
  138.         ProductStatusRepository $productStatusRepository,
  139.         SchoolRepository $schoolRepository,
  140.         SetProductRepository $setProductRepository,
  141.         SetProductProductRepository $setProductProductRepository,
  142.         ProductClassRepository $productClassRepository,
  143.         ProductStockRepository $productStockRepository,
  144.         SaleTypeRepository $saleTypeRepository,
  145.         ProductImageRepository $productImageRepository,
  146.         RecommendRepository $recommendRepository
  147.     ) {
  148.         $this->setProductImageRepository $setProductImageRepository;
  149.         $this->categoryRepository $categoryRepository;
  150.         $this->productRepository $productRepository;
  151.         $this->BaseInfo $baseInfoRepository->get();
  152.         $this->pageMaxRepository $pageMaxRepository;
  153.         $this->productStatusRepository $productStatusRepository;
  154.         $this->schoolRepository $schoolRepository;
  155.         $this->setProductRepository $setProductRepository;
  156.         $this->setProductProductRepository $setProductProductRepository;
  157.         $this->productClassRepository $productClassRepository;
  158.         $this->productStockRepository $productStockRepository;
  159.         $this->saleTypeRepository $saleTypeRepository;
  160.         $this->productImageRepository $productImageRepository;
  161.         $this->recommendRepository $recommendRepository;
  162.     }
  163.     /**
  164.      * @Route("/%eccube_admin_route%/product/set_product", name="admin_set_product", methods={"GET", "POST"})
  165.      * @Route("/%eccube_admin_route%/product/set_product/page/{page_no}", requirements={"page_no" = "\d+"}, name="admin_set_product_page", methods={"GET", "POST"})
  166.      * @Template("@admin/SetProduct/index.twig")
  167.      */
  168.     public function index(Request $requestPaginatorInterface $paginator$page_no null)
  169.     {
  170.         $builder $this->formFactory
  171.             ->createBuilder(SearchSetProductType::class);
  172.         $event = new EventArgs(
  173.             [
  174.                 'builder' => $builder,
  175.             ],
  176.             $request
  177.         );
  178.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_INDEX_INITIALIZE);
  179.         $searchForm $builder->getForm();
  180.         /**
  181.          * ページの表示件数は, 以下の順に優先される.
  182.          * - リクエストパラメータ
  183.          * - セッション
  184.          * - デフォルト値
  185.          * また, セッションに保存する際は mtb_page_maxと照合し, 一致した場合のみ保存する.
  186.          **/
  187.         $page_count $this->session->get(
  188.             'eccube.admin.set_product.search.page_count',
  189.             $this->eccubeConfig->get('eccube_default_page_count')
  190.         );
  191.         $page_count_param = (int) $request->get('page_count');
  192.         $pageMaxis $this->pageMaxRepository->findAll();
  193.         if ($page_count_param) {
  194.             foreach ($pageMaxis as $pageMax) {
  195.                 if ($page_count_param == $pageMax->getName()) {
  196.                     $page_count $pageMax->getName();
  197.                     $this->session->set('eccube.admin.set_product.search.page_count'$page_count);
  198.                     break;
  199.                 }
  200.             }
  201.         }
  202.         if ('POST' === $request->getMethod()) {
  203.             $searchForm->handleRequest($request);
  204.             if ($searchForm->isValid()) {
  205.                 /**
  206.                  * 検索が実行された場合は, セッションに検索条件を保存する.
  207.                  * ページ番号は最初のページ番号に初期化する.
  208.                  */
  209.                 $page_no 1;
  210.                 $searchData $searchForm->getData();
  211.                 // 検索条件, ページ番号をセッションに保持.
  212.                 $this->session->set('eccube.admin.set_product.search'FormUtil::getViewData($searchForm));
  213.                 $this->session->set('eccube.admin.set_product.search.page_no'$page_no);
  214.             } else {
  215.                 // 検索エラーの際は, 詳細検索枠を開いてエラー表示する.
  216.                 return [
  217.                     'searchForm' => $searchForm->createView(),
  218.                     'pagination' => [],
  219.                     'pageMaxis' => $pageMaxis,
  220.                     'page_no' => $page_no,
  221.                     'page_count' => $page_count,
  222.                     'has_errors' => true,
  223.                 ];
  224.             }
  225.         } else {
  226.             if (null !== $page_no || $request->get('resume')) {
  227.                 /*
  228.                  * ページ送りの場合または、他画面から戻ってきた場合は, セッションから検索条件を復旧する.
  229.                  */
  230.                 if ($page_no) {
  231.                     // ページ送りで遷移した場合.
  232.                     $this->session->set('eccube.admin.set_product.search.page_no', (int) $page_no);
  233.                 } else {
  234.                     // 他画面から遷移した場合.
  235.                     $page_no $this->session->get('eccube.admin.set_product.search.page_no'1);
  236.                 }
  237.                 $viewData $this->session->get('eccube.admin.set_product.search', []);
  238.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  239.             } else {
  240.                 /**
  241.                  * 初期表示の場合.
  242.                  */
  243.                 $page_no 1;
  244.                 // submit default value
  245.                 $viewData FormUtil::getViewData($searchForm);
  246.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  247.                 // セッション中の検索条件, ページ番号を初期化.
  248.                 $this->session->set('eccube.admin.set_product.search'$viewData);
  249.                 $this->session->set('eccube.admin.set_product.search.page_no'$page_no);
  250.             }
  251.         }
  252.         $qb $this->setProductRepository->getQueryBuilderBySearchDataForAdmin($searchData);
  253.         $event = new EventArgs(
  254.             [
  255.                 'qb' => $qb,
  256.                 'searchData' => $searchData,
  257.             ],
  258.             $request
  259.         );
  260.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_INDEX_SEARCH);
  261.         $sortKey $searchData['sortkey'];
  262.         if (empty($this->productRepository::COLUMNS[$sortKey]) || $sortKey == 'code' || $sortKey == 'status') {
  263.             $pagination $paginator->paginate(
  264.                 $qb,
  265.                 $page_no,
  266.                 $page_count
  267.             );
  268.         } else {
  269.             $pagination $paginator->paginate(
  270.                 $qb,
  271.                 $page_no,
  272.                 $page_count,
  273.                 ['wrap-queries' => true]
  274.             );
  275.         }
  276.         foreach ($pagination as $key => $set_product) {
  277.             $product_for_set $this->productRepository->findOneBy(['set_product_id' => $set_product->getId(), 'product_type' => 'set']);
  278.             if ($product_for_set) {
  279.                 $pagination[$key]->pid $product_for_set->getId();
  280.             }
  281.         }
  282.         return [
  283.             'searchForm' => $searchForm->createView(),
  284.             'pagination' => $pagination,
  285.             'pageMaxis' => $pageMaxis,
  286.             'page_no' => $page_no,
  287.             'page_count' => $page_count,
  288.             'has_errors' => false,
  289.         ];
  290.     }
  291.     private function getProductByCateogory($cat_id)
  292.     {
  293.         $searchData = [];
  294.         $searchData['category_id'] = $this->categoryRepository->findOneById($cat_id);
  295.         $qb $this->productRepository->getQueryBuilderBySearchDataForAdmin($searchData);
  296.         $products $qb
  297.             ->getQuery()
  298.             ->useResultCache(true$this->eccubeConfig['eccube_result_cache_lifetime_short'])
  299.             ->getResult();
  300.         $result = array();
  301.         foreach ($products as $p) {
  302.             array_push($result, ['id' => $p->getID(), 'name' => $p->getName(), 'price' => $p->getPrice02Min()]);
  303.         }
  304.         return $result;
  305.     }
  306.     /**
  307.      * @Route("/%eccube_admin_route%/product/set_product/get_category_product", name="admin_set_product_category_product", methods={"GET"})
  308.      */
  309.     public function ajaxGetProductByCateogory(Request $request)
  310.     {
  311.         return $this->json(['products' => $this->getProductByCateogory($request->get('category_id'))], 200);
  312.     }
  313.     /**
  314.      * @Route("/%eccube_admin_route%/product/set_product/image/add", name="admin_set_product_image_add", methods={"POST"})
  315.      */
  316.     public function addImage(Request $request)
  317.     {
  318.         if (!$request->isXmlHttpRequest() && $this->isTokenValid()) {
  319.             throw new BadRequestHttpException();
  320.         }
  321.         $images $request->files->get('admin_set_product');
  322.         $allowExtensions = ['gif''jpg''jpeg''png'];
  323.         $files = [];
  324.         if (count($images) > 0) {
  325.             foreach ($images as $img) {
  326.                 foreach ($img as $image) {
  327.                     //ファイルフォーマット検証
  328.                     $mimeType $image->getMimeType();
  329.                     if (!== strpos($mimeType'image')) {
  330.                         throw new UnsupportedMediaTypeHttpException();
  331.                     }
  332.                     // 拡張子
  333.                     $extension $image->getClientOriginalExtension();
  334.                     if (!in_array(strtolower($extension), $allowExtensions)) {
  335.                         throw new UnsupportedMediaTypeHttpException();
  336.                     }
  337.                     $filename date('mdHis') . uniqid('_') . '.' $extension;
  338.                     $image->move($this->eccubeConfig['eccube_temp_image_dir'], $filename);
  339.                     $files[] = $filename;
  340.                 }
  341.             }
  342.         }
  343.         $event = new EventArgs(
  344.             [
  345.                 'images' => $images,
  346.                 'files' => $files,
  347.             ],
  348.             $request
  349.         );
  350.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_ADD_IMAGE_COMPLETE);
  351.         $files $event->getArgument('files');
  352.         return $this->json(['files' => $files], 200);
  353.     }
  354.     /**
  355.      * @Route("/%eccube_admin_route%/product/set_product/new", name="admin_product_set_product_new", methods={"GET", "POST"})
  356.      * @Route("/%eccube_admin_route%/product/set_product/{id}/edit", requirements={"id" = "\d+"}, name="admin_product_set_product_edit", methods={"GET", "POST"})
  357.      * @Template("@admin/SetProduct/set_product.twig")
  358.      */
  359.     public function edit(Request $requestRouterInterface $routerCacheUtil $cacheUtil$id null)
  360.     {
  361.         $has_class false;
  362.         if (is_null($id)) {
  363.             $SetProduct = new SetProduct();
  364.             $SetProductStatus $this->productStatusRepository->find(ProductStatus::DISPLAY_HIDE);
  365.             $SetProduct
  366.                 ->setStatus($SetProductStatus);
  367.         } else {
  368.             $SetProduct $this->setProductRepository->find($id);
  369.             if (!$SetProduct) {
  370.                 throw new NotFoundHttpException();
  371.             }
  372.         }
  373.         //Create Product to process Set as One Product
  374.         $Product $this->productRepository->findOneBy(['set_product_id' => $SetProduct->getId(), 'product_type' => 'set']);
  375.         if (!$Product) {
  376.             $Product = new Product();
  377.         }
  378.         $builder $this->formFactory
  379.             ->createBuilder(SetProductType::class, $SetProduct);
  380.         $event = new EventArgs(
  381.             [
  382.                 'builder' => $builder,
  383.                 'SetProduct' => $SetProduct,
  384.             ],
  385.             $request
  386.         );
  387.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_EDIT_INITIALIZE);
  388.         $form $builder->getForm();
  389.         // ファイルの登録
  390.         $images = [];
  391.         $SetProductImages $SetProduct->getSetProductImage();
  392.         foreach ($SetProductImages as $SetProductImage) {
  393.             $images[] = $SetProductImage->getFileName();
  394.         }
  395.         $form['images']->setData($images);
  396.         //学校インプットのデーターを用意
  397.         $School = [];
  398.         $SetProductSchools $SetProduct->getSetProductSchool();
  399.         foreach ($SetProductSchools as $SetProductSchool) {
  400.             $School[] = $SetProductSchool->getSchool();
  401.         }
  402.         $form['school']->setData($School);
  403.         $ProductList = [];
  404.         $ProductsInSet $SetProduct->getSetProductProduct();
  405.         foreach ($ProductsInSet as $ProductInSet) {
  406.             $product_content = [];
  407.             $cat_id $ProductInSet->getCategory()->getId();
  408.             $product_content['item_cat'] = $cat_id;
  409.             $product_content['item_pct'] = $ProductInSet->getProduct()->getId();
  410.             $product_content['item_price'] = $ProductInSet->getSetProductPrice();
  411.             $product_content['category_products'] = $this->getProductByCateogory($cat_id);
  412.             $ProductList[] =  $product_content;
  413.         }
  414.         $form['product_list']->setData($ProductList);
  415.         $categories = [];
  416.         $AllCategories $this->categoryRepository->findAll();
  417.         foreach ($AllCategories as $category) {
  418.             $categories[] = $category;
  419.         }
  420.         if ('POST' === $request->getMethod()) {
  421.             $form->handleRequest($request);
  422.             if ($form->isValid()) {
  423.                 log_info('商品登録開始', [$id]);
  424.                 $SetProduct $form->getData();
  425.                 $Schools $form->get('school')->getData();
  426.                 $this->entityManager->persist($SetProduct);
  427.                 $this->entityManager->flush();
  428.                 // 学校の登録
  429.                 // 一度クリア
  430.                 foreach ($SetProduct->getSetProductSchool() as $SetProductSchool) {
  431.                     $SetProduct->removeSetProductSchool($SetProductSchool);
  432.                     $this->entityManager->remove($SetProductSchool);
  433.                 }
  434.                 $this->entityManager->persist($SetProduct);
  435.                 $this->entityManager->flush();
  436.                 // 学校の保存
  437.                 foreach ($Schools as $School) {
  438.                     $SetProductSchool = new \Customize\Entity\SetProductSchool();
  439.                     $SetProductSchool
  440.                         ->setSetProduct($SetProduct)
  441.                         ->setSchool($School);
  442.                     $SetProduct->addSetProductSchool($SetProductSchool);
  443.                     $this->entityManager->persist($SetProductSchool);
  444.                 }
  445.                 // 画像の登録
  446.                 $add_images $form->get('add_images')->getData();
  447.                 foreach ($add_images as $add_image) {
  448.                     $SetProductImage = new \Customize\Entity\SetProductImage();
  449.                     $SetProductImage
  450.                         ->setFileName($add_image)
  451.                         ->setSetProduct($SetProduct)
  452.                         ->setSortNo(1);
  453.                     $SetProduct->addSetProductImage($SetProductImage);
  454.                     $this->entityManager->persist($SetProductImage);
  455.                     // 移動
  456.                     $file = new File($this->eccubeConfig['eccube_temp_image_dir'] . '/' $add_image);
  457.                     $file->move($this->eccubeConfig['eccube_save_image_dir']);
  458.                 }
  459.                 // 画像の削除
  460.                 $delete_images $form->get('delete_images')->getData();
  461.                 $fs = new Filesystem();
  462.                 foreach ($delete_images as $delete_image) {
  463.                     $SetProductImage $this->setProductImageRepository->findOneBy([
  464.                         'SetProduct' => $SetProduct,
  465.                         'file_name' => $delete_image,
  466.                     ]);
  467.                     if ($SetProductImage instanceof SetProductImage) {
  468.                         $SetProduct->removeSetProductImage($SetProductImage);
  469.                         $this->entityManager->remove($SetProductImage);
  470.                         $this->entityManager->flush();
  471.                         // 他に同じ画像を参照する商品がなければ画像ファイルを削除
  472.                         if (!$this->setProductImageRepository->findOneBy(['file_name' => $delete_image])) {
  473.                             $fs->remove($this->eccubeConfig['eccube_save_image_dir'] . '/' $delete_image);
  474.                         }
  475.                     } else {
  476.                         // 追加してすぐに削除した画像は、Entityに追加されない
  477.                         $fs->remove($this->eccubeConfig['eccube_temp_image_dir'] . '/' $delete_image);
  478.                     }
  479.                 }
  480.                 $this->entityManager->flush();
  481.                 $this->setProductRepository->emptySetProductProduct($SetProduct);
  482.                 $params_for_input $request->request->all();
  483.                 $cat_ids $params_for_input['item_cats'];
  484.                 $pct_ids $params_for_input['item_ids'];
  485.                 $pct_prices $params_for_input['item_prices'];
  486.                 $new_set_price 0;
  487.                 for ($i 0$i count($pct_ids); $i++) {
  488.                     $ProductItem $this->productRepository->findOneBy(['id' => $pct_ids[$i]]);
  489.                     $ProductCategory $this->categoryRepository->findOneBy(['id' => $cat_ids[$i]]);
  490.                     $SetProductProduct = new \Customize\Entity\SetProductProduct();
  491.                     $SetProductProduct
  492.                         ->setSetProduct($SetProduct)
  493.                         ->setCategory($ProductCategory)
  494.                         ->setProduct($ProductItem)
  495.                         ->setSetProductPrice($pct_prices[$i])
  496.                         ->setSortNo($i 1);
  497.                     $new_set_price += $pct_prices[$i];
  498.                     $this->entityManager->persist($SetProductProduct);
  499.                 }
  500.                 $this->entityManager->flush();
  501.                 $SetProduct->setFee(isset($params_for_input['fee']) ? array_sum($params_for_input['fee']) : 0);
  502.                 $SetProduct->setShippingFee(isset($params_for_input['shipping_fee']) ? array_sum($params_for_input['shipping_fee']) : 0);
  503.                 $SetProduct->setDiscount(isset($params_for_input['discount']) ? array_sum($params_for_input['discount']) : 0);
  504.                 $new_set_price += $SetProduct->getFee() + $SetProduct->getShippingFee() + $SetProduct->getDiscount();
  505.                 $SetProduct->setTotal($new_set_price);
  506.                 $this->entityManager->persist($SetProduct);
  507.                 $this->entityManager->flush();
  508.                 $sortNos $request->get('sort_no_images');
  509.                 if ($sortNos) {
  510.                     foreach ($sortNos as $sortNo) {
  511.                         list($filename$sortNo_val) = explode('//'$sortNo);
  512.                         $SetProductImage $this->setProductImageRepository
  513.                             ->findOneBy([
  514.                                 'file_name' => $filename,
  515.                                 'SetProduct' => $SetProduct,
  516.                             ]);
  517.                         $SetProductImage->setSortNo($sortNo_val);
  518.                         $this->entityManager->persist($SetProductImage);
  519.                     }
  520.                 }
  521.                 $this->entityManager->flush();
  522.                 $SetProduct->setUpdateDate(new \DateTime());
  523.                 $this->entityManager->flush();
  524.                 if ($SetProduct->getSex())
  525.                     $set_target_sex $SetProduct->getSex()->getId() == "男子" "女子";
  526.                 else
  527.                     $set_target_sex "";
  528.                 $Product->setSetProductId($SetProduct->getId())
  529.                     ->setProductType('set')
  530.                     ->setName($SetProduct->getSetName())
  531.                     ->setStatus($SetProduct->getStatus())
  532.                     ->setNote($SetProduct->getNote())
  533.                     ->setDescriptionList($SetProduct->getDescriptionList())
  534.                     ->setDescriptionDetail($SetProduct->getDescriptionDetail())
  535.                     ->setSearchWord($set_target_sex $SetProduct->getSearchWord())
  536.                     ->setFreeArea($SetProduct->getFreeArea());
  537.                 $this->entityManager->persist($Product);
  538.                 $this->entityManager->flush();
  539.                 foreach ($Product->getProductSchool() as $ProductSchool) {
  540.                     $Product->removeProductSchool($ProductSchool);
  541.                     $this->entityManager->remove($ProductSchool);
  542.                 }
  543.                 $this->entityManager->persist($Product);
  544.                 $this->entityManager->flush();
  545.                 foreach ($Schools as $School) {
  546.                     $ProductSchool = new \Customize\Entity\ProductSchool();
  547.                     $ProductSchool
  548.                         ->setProduct($Product)
  549.                         ->setSchool($School);
  550.                     $Product->addProductSchool($ProductSchool);
  551.                     $this->entityManager->persist($ProductSchool);
  552.                 }
  553.                 $this->entityManager->flush();
  554.                 // 画像の登録
  555.                 foreach ($add_images as $add_image) {
  556.                     $ProductImage = new \Eccube\Entity\ProductImage();
  557.                     $ProductImage
  558.                         ->setFileName($add_image)
  559.                         ->setProduct($Product)
  560.                         ->setSortNo(1);
  561.                     $Product->addProductImage($ProductImage);
  562.                     $this->entityManager->persist($ProductImage);
  563.                 }
  564.                 // 画像の削除
  565.                 foreach ($delete_images as $delete_image) {
  566.                     $ProductImage $this->productImageRepository->findOneBy([
  567.                         'Product' => $Product,
  568.                         'file_name' => $delete_image,
  569.                     ]);
  570.                     if ($ProductImage instanceof ProductImage) {
  571.                         $Product->removeProductImage($ProductImage);
  572.                         $this->entityManager->remove($ProductImage);
  573.                         $this->entityManager->flush();
  574.                     }
  575.                 }
  576.                 $ProductClass $this->productClassRepository->findOneBy(['Product' => $Product]);
  577.                 if (!$ProductClass) {
  578.                     $ProductClass = new ProductClass();
  579.                 }
  580.                 $SaleType $this->saleTypeRepository->findOneBy([], ['sort_no' => 'ASC']);
  581.                 $ProductClass->setProduct($Product)
  582.                     ->setProductType('set')
  583.                     ->setVisible(1)
  584.                     ->setStockUnlimited(1)
  585.                     ->setSaleType($SaleType)
  586.                     ->setPrice02($SetProduct->getTotal());
  587.                 $this->entityManager->persist($ProductClass);
  588.                 $this->entityManager->flush();
  589.                 $ProductStock $this->productStockRepository->findOneBy(['ProductClass' => $ProductClass]);
  590.                 if (!$ProductStock) {
  591.                     $ProductStock = new ProductStock();
  592.                 }
  593.                 $ProductStock->setProductClass($ProductClass);
  594.                 $this->entityManager->persist($ProductStock);
  595.                 $this->entityManager->flush();
  596.                 log_info('商品登録完了', [$id]);
  597.                 // $event = new EventArgs(
  598.                 //     [
  599.                 //         'form' => $form,
  600.                 //         'SetProduct' => $SetProduct,
  601.                 //     ],
  602.                 //     $request
  603.                 // );
  604.                 // $this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_PRODUCT_EDIT_COMPLETE);
  605.                 $this->addSuccess('admin.common.save_complete''admin');
  606.                 if ($returnLink $form->get('return_link')->getData()) {
  607.                     try {
  608.                         // $returnLinkはpathの形式で渡される. pathが存在するかをルータでチェックする.
  609.                         $pattern '/^' preg_quote($request->getBasePath(), '/') . '/';
  610.                         $returnLink preg_replace($pattern''$returnLink);
  611.                         $result $router->match($returnLink);
  612.                         // パラメータのみ抽出
  613.                         $params array_filter($result, function ($key) {
  614.                             return !== \strpos($key'_');
  615.                         }, ARRAY_FILTER_USE_KEY);
  616.                         // pathからurlを再構築してリダイレクト.
  617.                         return $this->redirectToRoute($result['_route'], $params);
  618.                     } catch (\Exception $e) {
  619.                         // マッチしない場合はログ出力してスキップ.
  620.                         log_warning('URLの形式が不正です。');
  621.                     }
  622.                 }
  623.                 $cacheUtil->clearDoctrineCache();
  624.                 return $this->redirectToRoute('admin_product_set_product_edit', ['id' => $SetProduct->getId()]);
  625.             }
  626.         }
  627.         //
  628.         // 検索結果の保持
  629.         $builder $this->formFactory
  630.             ->createBuilder(SearchSetProductType::class);
  631.         $event = new EventArgs(
  632.             [
  633.                 'builder' => $builder,
  634.                 'SetProduct' => $SetProduct,
  635.             ],
  636.             $request
  637.         );
  638.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_EDIT_SEARCH);
  639.         $searchForm $builder->getForm();
  640.         $AllSchools $this->schoolRepository->findAll();
  641.         if ('POST' === $request->getMethod()) {
  642.             $searchForm->handleRequest($request);
  643.         }
  644.         return [
  645.             'SetProduct' => $SetProduct,
  646.             'form' => $form->createView(),
  647.             'searchForm' => $searchForm->createView(),
  648.             'id' => $id,
  649.             'all_schools' => $AllSchools,
  650.             'all_categories' => $categories,
  651.             'ProductForSet' => $Product,
  652.         ];
  653.     }
  654.     /**
  655.      * @Route("/%eccube_admin_route%/product/set_product/{id}/delete", requirements={"id" = "\d+"}, name="admin_product_set_product_delete", methods={"DELETE"})
  656.      */
  657.     public function delete(Request $request$id nullCacheUtil $cacheUtil)
  658.     {
  659.         $this->isTokenValid();
  660.         $session $request->getSession();
  661.         $page_no intval($session->get('eccube.admin.set_product.search.page_no'));
  662.         $page_no $page_no $page_no Constant::ENABLED;
  663.         $message null;
  664.         $success false;
  665.         if (!is_null($id)) {
  666.             /* @var $SetProduct \Customize\Entity\SetProduct */
  667.             $SetProduct $this->setProductRepository->find($id);
  668.             if (!$SetProduct) {
  669.                 if ($request->isXmlHttpRequest()) {
  670.                     $message trans('admin.common.delete_error_already_deleted');
  671.                     return $this->json(['success' => $success'message' => $message]);
  672.                 } else {
  673.                     $this->deleteMessage();
  674.                     $rUrl $this->generateUrl('admin_set_product_page', ['page_no' => $page_no]) . '?resume=' Constant::ENABLED;
  675.                     return $this->redirect($rUrl);
  676.                 }
  677.             }
  678.             if ($SetProduct instanceof SetProduct) {
  679.                 log_info('商品削除開始', [$id]);
  680.                 $deleteImages $SetProduct->getSetProductImage();
  681.                 $deleteProductForSet $this->productRepository->findOneBy(['set_product_id' => $SetProduct->getId(), 'product_type' => 'set']);
  682.                 try {
  683.                     $this->setProductRepository->delete($SetProduct);
  684.                     if ($deleteProductForSet)
  685.                         $this->productRepository->delete($deleteProductForSet);
  686.                     $this->entityManager->flush();
  687.                     $event = new EventArgs(
  688.                         [
  689.                             'Product' => $SetProduct,
  690.                             'ProductClass' => null,
  691.                             'deleteImages' => $deleteImages,
  692.                         ],
  693.                         $request
  694.                     );
  695.                     $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_SET_PRODUCT_DELETE_COMPLETE);
  696.                     $deleteImages $event->getArgument('deleteImages');
  697.                     // 画像ファイルの削除(commit後に削除させる)
  698.                     /** @var SetProductImage $deleteImage */
  699.                     foreach ($deleteImages as $deleteImage) {
  700.                         if ($this->setProductImageRepository->findOneBy(['file_name' => $deleteImage->getFileName()])) {
  701.                             continue;
  702.                         }
  703.                         try {
  704.                             $fs = new Filesystem();
  705.                             $fs->remove($this->eccubeConfig['eccube_save_image_dir'] . '/' $deleteImage);
  706.                         } catch (\Exception $e) {
  707.                             // エラーが発生しても無視する
  708.                         }
  709.                     }
  710.                     log_info('商品削除完了', [$id]);
  711.                     $success true;
  712.                     $message trans('admin.common.delete_complete');
  713.                     $cacheUtil->clearDoctrineCache();
  714.                 } catch (ForeignKeyConstraintViolationException $e) {
  715.                     log_info('商品削除エラー', [$id]);
  716.                     $message trans('admin.common.delete_error_foreign_key', ['%name%' => $SetProduct->getSetName()]);
  717.                 }
  718.             } else {
  719.                 log_info('商品削除エラー', [$id]);
  720.                 $message trans('admin.common.delete_error');
  721.             }
  722.         } else {
  723.             log_info('商品削除エラー', [$id]);
  724.             $message trans('admin.common.delete_error');
  725.         }
  726.         if ($request->isXmlHttpRequest()) {
  727.             return $this->json(['success' => $success'message' => $message]);
  728.         } else {
  729.             if ($success) {
  730.                 $this->addSuccess($message'admin');
  731.             } else {
  732.                 $this->addError($message'admin');
  733.             }
  734.             $rUrl $this->generateUrl('admin_set_product_page', ['page_no' => $page_no]) . '?resume=' Constant::ENABLED;
  735.             return $this->redirect($rUrl);
  736.         }
  737.     }
  738.     /**
  739.      * Bulk public action
  740.      *
  741.      * @Route("/%eccube_admin_route%/product/bulk/set_product-status/{id}", requirements={"id" = "\d+"}, name="admin_product_bulk_set_product_status", methods={"POST"})
  742.      *
  743.      * @param Request $request
  744.      * @param ProductStatus $ProductStatus
  745.      *
  746.      * @return RedirectResponse
  747.      */
  748.     public function bulkProductStatus(Request $requestProductStatus $ProductStatusCacheUtil $cacheUtil)
  749.     {
  750.         $this->isTokenValid();
  751.         /** @var Product[] $SetProducts */
  752.         $SetProducts $this->setProductRepository->findBy(['set_product_id' => $request->get('ids')]);
  753.         $count 0;
  754.         foreach ($SetProducts as $SetProduct) {
  755.             try {
  756.                 $SetProduct->setStatus($ProductStatus);
  757.                 $this->setProductRepository->save($SetProduct);
  758.                 $Product $this->productRepository->findOneBy(['set_product_id' => $SetProduct->getId(), 'product_type' => 'set']);
  759.                 if ($Product) {
  760.                     $Product->setStatus($ProductStatus);
  761.                     $this->productRepository->save($Product);
  762.                 }
  763.                 $count++;
  764.             } catch (\Exception $e) {
  765.                 $this->addError($e->getMessage(), 'admin');
  766.             }
  767.         }
  768.         try {
  769.             if ($count) {
  770.                 $this->entityManager->flush();
  771.                 $msg $this->translator->trans('admin.product.bulk_change_status_complete', [
  772.                     '%count%' => $count,
  773.                     '%status%' => $ProductStatus->getName(),
  774.                 ]);
  775.                 $this->addSuccess($msg'admin');
  776.                 $cacheUtil->clearDoctrineCache();
  777.             }
  778.         } catch (\Exception $e) {
  779.             $this->addError($e->getMessage(), 'admin');
  780.         }
  781.         return $this->redirectToRoute('admin_set_product', ['resume' => Constant::ENABLED]);
  782.     }
  783.     /**
  784.      * @Route("/%eccube_admin_route%/product/set_product/{id}/copy", requirements={"id" = "\d+"}, name="admin_product_set_product_copy", methods={"POST"})
  785.      */
  786.     public function copy(Request $request$id null)
  787.     {
  788.         $this->isTokenValid();
  789.         if (!is_null($id)) {
  790.             $SetProduct $this->setProductRepository->find($id);
  791.             if ($SetProduct instanceof SetProduct) {
  792.                 $CopyProduct = clone $SetProduct;
  793.                 $CopyProduct->copy();
  794.                 $ProductStatus $this->productStatusRepository->find(ProductStatus::DISPLAY_HIDE);
  795.                 $CopyProduct->setStatus($ProductStatus);
  796.                 $Images $CopyProduct->getSetProductImage();
  797.                 foreach ($Images as $Image) {
  798.                     // 画像ファイルを新規作成
  799.                     $extension pathinfo($Image->getFileName(), PATHINFO_EXTENSION);
  800.                     $filename date('mdHis') . uniqid('_') . '.' $extension;
  801.                     try {
  802.                         $fs = new Filesystem();
  803.                         $fs->copy($this->eccubeConfig['eccube_save_image_dir'] . '/' $Image->getFileName(), $this->eccubeConfig['eccube_save_image_dir'] . '/' $filename);
  804.                     } catch (\Exception $e) {
  805.                         // エラーが発生しても無視する
  806.                     }
  807.                     $Image->setFileName($filename);
  808.                     $this->entityManager->persist($Image);
  809.                 }
  810.                 $this->entityManager->persist($CopyProduct);
  811.                 $this->entityManager->flush();
  812.                 $event = new EventArgs(
  813.                     [
  814.                         'SetProduct' => $SetProduct,
  815.                         'CopyProduct' => $CopyProduct,
  816.                         'images' => $Images
  817.                     ],
  818.                     $request
  819.                 );
  820.                 $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_COPY_COMPLETE);
  821.                 $this->addSuccess('admin.product.copy_complete''admin');
  822.                 return $this->redirectToRoute('admin_product_set_product_edit', ['id' => $CopyProduct->getId()]);
  823.             } else {
  824.                 $this->addError('admin.product.copy_error''admin');
  825.             }
  826.         } else {
  827.             $msg trans('admin.product.copy_error');
  828.             $this->addError($msg'admin');
  829.         }
  830.         return $this->redirectToRoute('admin_product');
  831.     }
  832. }