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

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