CategoryController::index()   F
last analyzed

Complexity

Conditions 19
Paths 159

Size

Total Lines 145

Duplication

Lines 10
Ratio 6.9 %

Code Coverage

Tests 78
CRAP Score 19.0787

Importance

Changes 0
Metric Value
cc 19
nc 159
nop 4
dl 10
loc 145
ccs 78
cts 83
cp 0.9398
crap 19.0787
rs 3.22
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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