src/Eccube/Controller/Admin/Product/CategoryController.php line 67

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 Eccube\Controller\Admin\Product;
  13. use Eccube\Controller\AbstractController;
  14. use Eccube\Entity\Category;
  15. use Eccube\Entity\Master\CsvType;
  16. use Eccube\Event\EccubeEvents;
  17. use Eccube\Event\EventArgs;
  18. use Eccube\Form\Type\Admin\CategoryType;
  19. use Eccube\Repository\CategoryRepository;
  20. use Eccube\Service\CsvExportService;
  21. use Eccube\Util\CacheUtil;
  22. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\HttpFoundation\StreamedResponse;
  26. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  27. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  28. use Symfony\Component\Routing\Annotation\Route;
  29. use Symfony\Component\Filesystem\Filesystem;
  30. use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
  31. class CategoryController extends AbstractController
  32. {
  33.     /**
  34.      * @var CsvExportService
  35.      */
  36.     protected $csvExportService;
  37.     /**
  38.      * @var CategoryRepository
  39.      */
  40.     protected $categoryRepository;
  41.     /**
  42.      * CategoryController constructor.
  43.      *
  44.      * @param CsvExportService $csvExportService
  45.      * @param CategoryRepository $categoryRepository
  46.      */
  47.     public function __construct(
  48.         CsvExportService $csvExportService,
  49.         CategoryRepository $categoryRepository
  50.     ) {
  51.         $this->csvExportService $csvExportService;
  52.         $this->categoryRepository $categoryRepository;
  53.     }
  54.     /**
  55.      * @Route("/%eccube_admin_route%/product/category", name="admin_product_category", methods={"GET", "POST"})
  56.      * @Route("/%eccube_admin_route%/product/category/{parent_id}", requirements={"parent_id" = "\d+"}, name="admin_product_category_show", methods={"GET", "POST"})
  57.      * @Route("/%eccube_admin_route%/product/category/{id}/edit", requirements={"id" = "\d+"}, name="admin_product_category_edit", methods={"GET", "POST"})
  58.      * @Template("@admin/Product/category.twig")
  59.      */
  60.     public function index(Request $requestCacheUtil $cacheUtil$parent_id null$id null)
  61.     {
  62.         if ($parent_id) {
  63.             /** @var Category $Parent */
  64.             $Parent $this->categoryRepository->find($parent_id);
  65.             if (!$Parent) {
  66.                 throw new NotFoundHttpException();
  67.             }
  68.         } else {
  69.             $Parent null;
  70.         }
  71.         if ($id) {
  72.             $TargetCategory $this->categoryRepository->find($id);
  73.             if (!$TargetCategory) {
  74.                 throw new NotFoundHttpException();
  75.             }
  76.             $Parent $TargetCategory->getParent();
  77.         } else {
  78.             $TargetCategory = new \Eccube\Entity\Category();
  79.             $TargetCategory->setParent($Parent);
  80.             if ($Parent) {
  81.                 $TargetCategory->setHierarchy($Parent->getHierarchy() + 1);
  82.             } else {
  83.                 $TargetCategory->setHierarchy(1);
  84.             }
  85.         }
  86.         $Categories $this->categoryRepository->getList($Parent);
  87.         // ツリー表示のため、ルートからのカテゴリを取得
  88.         $TopCategories $this->categoryRepository->getList(null);
  89.         $builder $this->formFactory
  90.             ->createBuilder(CategoryType::class, $TargetCategory);
  91.         $event = new EventArgs(
  92.             [
  93.                 'builder' => $builder,
  94.                 'Parent' => $Parent,
  95.                 'TargetCategory' => $TargetCategory,
  96.             ],
  97.             $request
  98.         );
  99.         $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_CATEGORY_INDEX_INITIALIZE);
  100.         $form $builder->getForm();
  101.         $forms = [];
  102.         foreach ($Categories as $Category) {
  103.             $forms[$Category->getId()] = $this->formFactory
  104.                 ->createNamed('category_'.$Category->getId(), CategoryType::class, $Category);
  105.         }
  106.         if ($request->getMethod() === 'POST') {
  107.             $form->handleRequest($request);
  108.             if ($form->isSubmitted() && $form->isValid()) {
  109.                 if ($this->eccubeConfig['eccube_category_nest_level'] < $TargetCategory->getHierarchy()) {
  110.                     throw new BadRequestHttpException();
  111.                 }
  112.                 log_info('カテゴリ登録開始', [$id]);
  113.                 // ファイルアップロード追記
  114.                 $file $form['category_image']->getData();
  115.                 $fs = new Filesystem();
  116.                 if ($file && $fs->exists($this->getParameter('eccube_temp_image_dir').'/'.$file)) {
  117.                     $fs->rename(
  118.                         $this->getParameter('eccube_temp_image_dir').'/'.$file,
  119.                         $this->getParameter('eccube_save_image_dir').'/'.$file
  120.                     );
  121.                 }
  122.                 $this->categoryRepository->save($TargetCategory);
  123.                 log_info('カテゴリ登録完了', [$id]);
  124.                 // $formが保存されたフォーム
  125.                 // 下の編集用フォームの場合とイベント名が共通のため
  126.                 // このイベントのリスナーではsubmitされているフォームを判定する必要がある
  127.                 $event = new EventArgs(
  128.                     [
  129.                         'form' => $form,
  130.                         'Parent' => $Parent,
  131.                         'TargetCategory' => $TargetCategory,
  132.                     ],
  133.                     $request
  134.                 );
  135.                 $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_CATEGORY_INDEX_COMPLETE);
  136.                 $this->addSuccess('admin.common.save_complete''admin');
  137.                 $cacheUtil->clearDoctrineCache();
  138.                 if ($Parent) {
  139.                     return $this->redirectToRoute('admin_product_category_show', ['parent_id' => $Parent->getId()]);
  140.                 } else {
  141.                     return $this->redirectToRoute('admin_product_category');
  142.                 }
  143.             }
  144.             foreach ($forms as $editForm) {
  145.                 $editForm->handleRequest($request);
  146.                 if ($editForm->isSubmitted() && $editForm->isValid()) {
  147.                     // ファイルアップロード 追記
  148.                     $file $editForm['category_image']->getData();
  149.                     $fs = new Filesystem();
  150.                     if ($file && $fs->exists($this->getParameter('eccube_temp_image_dir').'/'.$file)) {
  151.                         $fs->rename(
  152.                             $this->getParameter('eccube_temp_image_dir').'/'.$file,
  153.                             $this->getParameter('eccube_save_image_dir').'/'.$file
  154.                         );
  155.                     }
  156.                     $this->categoryRepository->save($editForm->getData());
  157.                     // $editFormが保存されたフォーム
  158.                     // 上の新規登録用フォームの場合とイベント名が共通のため
  159.                     // このイベントのリスナーではsubmitされているフォームを判定する必要がある
  160.                     $event = new EventArgs(
  161.                         [
  162.                             'form' => $form,
  163.                             'editForm' => $editForm,
  164.                             'Parent' => $Parent,
  165.                             'TargetCategory' => $editForm->getData(),
  166.                         ],
  167.                         $request
  168.                     );
  169.                     $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_CATEGORY_INDEX_COMPLETE);
  170.                     $this->addSuccess('admin.common.save_complete''admin');
  171.                     $cacheUtil->clearDoctrineCache();
  172.                     if ($Parent) {
  173.                         return $this->redirectToRoute('admin_product_category_show', ['parent_id' => $Parent->getId()]);
  174.                     } else {
  175.                         return $this->redirectToRoute('admin_product_category');
  176.                     }
  177.                 }
  178.             }
  179.         }
  180.         $formViews = [];
  181.         $formErrors = [];
  182.         foreach ($forms as $key => $value) {
  183.             $formViews[$key] = $value->createView();
  184.             $formErrors[$key]['count'] = $value->getErrors(true)->count();
  185.         }
  186.         $Ids = [];
  187.         if ($Parent && $Parent->getParents()) {
  188.             foreach ($Parent->getParents() as $item) {
  189.                 $Ids[] = $item['id'];
  190.             }
  191.         }
  192.         $Ids[] = intval($parent_id);
  193.         return [
  194.             'form' => $form->createView(),
  195.             'Parent' => $Parent,
  196.             'Ids' => $Ids,
  197.             'Categories' => $Categories,
  198.             'TopCategories' => $TopCategories,
  199.             'TargetCategory' => $TargetCategory,
  200.             'forms' => $formViews,
  201.             'error_forms' => $formErrors,
  202.         ];
  203.     }
  204.     /**
  205.      * @Route("/%eccube_admin_route%/product/category/{id}/delete", requirements={"id" = "\d+"}, name="admin_product_category_delete", methods={"DELETE"})
  206.      */
  207.     public function delete(Request $request$idCacheUtil $cacheUtil)
  208.     {
  209.         $this->isTokenValid();
  210.         $TargetCategory $this->categoryRepository->find($id);
  211.         if (!$TargetCategory) {
  212.             $this->deleteMessage();
  213.             return $this->redirectToRoute('admin_product_category');
  214.         }
  215.         $Parent $TargetCategory->getParent();
  216.         log_info('カテゴリ削除開始', [$id]);
  217.         try {
  218.             $this->categoryRepository->delete($TargetCategory);
  219.             $event = new EventArgs(
  220.                 [
  221.                     'Parent' => $Parent,
  222.                     'TargetCategory' => $TargetCategory,
  223.                 ],
  224.                 $request
  225.             );
  226.             $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_CATEGORY_DELETE_COMPLETE);
  227.             $this->addSuccess('admin.common.delete_complete''admin');
  228.             log_info('カテゴリ削除完了', [$id]);
  229.             $cacheUtil->clearDoctrineCache();
  230.         } catch (\Exception $e) {
  231.             log_info('カテゴリ削除エラー', [$id$e]);
  232.             $message trans('admin.common.delete_error_foreign_key', ['%name%' => $TargetCategory->getName()]);
  233.             $this->addError($message'admin');
  234.         }
  235.         if ($Parent) {
  236.             return $this->redirectToRoute('admin_product_category_show', ['parent_id' => $Parent->getId()]);
  237.         } else {
  238.             return $this->redirectToRoute('admin_product_category');
  239.         }
  240.     }
  241.     /**
  242.      * @Route("/%eccube_admin_route%/product/category/sort_no/move", name="admin_product_category_sort_no_move", methods={"POST"})
  243.      */
  244.     public function moveSortNo(Request $requestCacheUtil $cacheUtil)
  245.     {
  246.         if (!$request->isXmlHttpRequest()) {
  247.             throw new BadRequestHttpException();
  248.         }
  249.         if ($this->isTokenValid()) {
  250.             $sortNos $request->request->all();
  251.             foreach ($sortNos as $categoryId => $sortNo) {
  252.                 /* @var $Category \Eccube\Entity\Category */
  253.                 $Category $this->categoryRepository
  254.                     ->find($categoryId);
  255.                 $Category->setSortNo($sortNo);
  256.                 $this->entityManager->persist($Category);
  257.             }
  258.             $this->entityManager->flush();
  259.             $cacheUtil->clearDoctrineCache();
  260.             return new Response('Successful');
  261.         }
  262.     }
  263.     /**
  264.      * カテゴリCSVの出力.
  265.      *
  266.      * @Route("/%eccube_admin_route%/product/category/export", name="admin_product_category_export", methods={"GET"})
  267.      *
  268.      * @param Request $request
  269.      *
  270.      * @return StreamedResponse
  271.      */
  272.     public function export(Request $request)
  273.     {
  274.         // タイムアウトを無効にする.
  275.         set_time_limit(0);
  276.         // sql loggerを無効にする.
  277.         $em $this->entityManager;
  278.         $em->getConfiguration()->setSQLLogger(null);
  279.         $response = new StreamedResponse();
  280.         $response->setCallback(function () use ($request) {
  281.             // CSV種別を元に初期化.
  282.             $this->csvExportService->initCsvType(CsvType::CSV_TYPE_CATEGORY);
  283.             // ヘッダ行の出力.
  284.             $this->csvExportService->exportHeader();
  285.             $qb $this->categoryRepository
  286.                 ->createQueryBuilder('c')
  287.                 ->orderBy('c.sort_no''DESC');
  288.             // データ行の出力.
  289.             $this->csvExportService->setExportQueryBuilder($qb);
  290.             $this->csvExportService->exportData(function ($entity$csvService) use ($request) {
  291.                 $Csvs $csvService->getCsvs();
  292.                 /** @var $Category \Eccube\Entity\Category */
  293.                 $Category $entity;
  294.                 // CSV出力項目と合致するデータを取得.
  295.                 $ExportCsvRow = new \Eccube\Entity\ExportCsvRow();
  296.                 foreach ($Csvs as $Csv) {
  297.                     $ExportCsvRow->setData($csvService->getData($Csv$Category));
  298.                     $event = new EventArgs(
  299.                         [
  300.                             'csvService' => $csvService,
  301.                             'Csv' => $Csv,
  302.                             'Category' => $Category,
  303.                             'ExportCsvRow' => $ExportCsvRow,
  304.                         ],
  305.                         $request
  306.                     );
  307.                     $this->eventDispatcher->dispatch($eventEccubeEvents::ADMIN_PRODUCT_CATEGORY_CSV_EXPORT);
  308.                     $ExportCsvRow->pushData();
  309.                 }
  310.                 // $row[] = number_format(memory_get_usage(true));
  311.                 // 出力.
  312.                 $csvService->fputcsv($ExportCsvRow->getRow());
  313.             });
  314.         });
  315.         $now = new \DateTime();
  316.         $filename 'category_'.$now->format('YmdHis').'.csv';
  317.         $response->headers->set('Content-Type''application/octet-stream');
  318.         $response->headers->set('Content-Disposition''attachment; filename='.$filename);
  319.         log_info('カテゴリCSV出力ファイル名', [$filename]);
  320.         return $response;
  321.     }
  322.     /**追記 */
  323.     /**
  324.      * @Route("/%eccube_admin_route%/product/category/image/add", name="admin_product_category_image_add")
  325.      */
  326.     public function imageAdd(Request $request)
  327.     {
  328.         if (!$request->isXmlHttpRequest()) {
  329.             throw new BadRequestHttpException();
  330.         }
  331.         $allowExtensions = ['gif''jpg''jpeg''png'];
  332.         $filename null;
  333.         $files $request->files->all();
  334.         foreach ($files as $images) {
  335.             if (isset($images['category_file'])) {
  336.                 $image $images['category_file'];
  337.                 //ファイルフォーマット検証
  338.                 $mimeType $image->getMimeType();
  339.                 if (!== strpos($mimeType'image')) {
  340.                     throw new UnsupportedMediaTypeHttpException();
  341.                 }
  342.                 // 拡張子
  343.                 $extension $image->getClientOriginalExtension();
  344.                 if (!in_array(strtolower($extension), $allowExtensions)) {
  345.                     throw new UnsupportedMediaTypeHttpException();
  346.                 }
  347.                 $filename date('mdHis').uniqid('_').'.'.$extension;
  348.                 $image->move($this->getParameter('eccube_temp_image_dir'), $filename);
  349.             }
  350.         }
  351.         return $this->json(['filename' => $filename], 200);
  352.     }
  353. }