Failed Conditions
Branch experimental/sf (68db07)
by Kentaro
42:17 queued 33:39
created

ProductController::index()   B

Complexity

Conditions 7
Paths 32

Size

Total Lines 138

Duplication

Lines 15
Ratio 10.87 %

Code Coverage

Tests 71
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
nc 32
nop 2
dl 15
loc 138
rs 7.0666
c 0
b 0
f 0
ccs 71
cts 71
cp 1
crap 7

How to fix   Long Method   

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) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.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;
15
16
use Eccube\Entity\BaseInfo;
17
use Eccube\Entity\Master\ProductStatus;
18
use Eccube\Entity\Product;
19
use Eccube\Event\EccubeEvents;
20
use Eccube\Event\EventArgs;
21
use Eccube\Form\Type\AddCartType;
22
use Eccube\Form\Type\Master\ProductListMaxType;
23
use Eccube\Form\Type\Master\ProductListOrderByType;
24
use Eccube\Form\Type\SearchProductType;
25
use Eccube\Repository\CustomerFavoriteProductRepository;
26
use Eccube\Repository\ProductRepository;
27
use Eccube\Service\CartService;
28
use Eccube\Service\PurchaseFlow\PurchaseContext;
29
use Eccube\Service\PurchaseFlow\PurchaseFlow;
30
use Knp\Component\Pager\Paginator;
31
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
32
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
33
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
34
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
35
use Symfony\Component\HttpFoundation\JsonResponse;
36
use Symfony\Component\HttpFoundation\Request;
37
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
38
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
39
40
class ProductController extends AbstractController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
41
{
42
    /**
43
     * @var PurchaseFlow
44
     */
45
    protected $purchaseFlow;
46
47
    /**
48
     * @var CustomerFavoriteProductRepository
49
     */
50
    protected $customerFavoriteProductRepository;
51
52
    /**
53
     * @var CartService
54
     */
55
    protected $cartService;
56
57
    /**
58
     * @var ProductRepository
59
     */
60
    protected $productRepository;
61
62
    /**
63
     * @var BaseInfo
64
     */
65
    protected $BaseInfo;
66
67
    /**
68
     * @var AuthenticationUtils
69
     */
70
    protected $helper;
71
72
    private $title = '';
73
74
    /**
75
     * ProductController constructor.
76
     *
77
     * @param PurchaseFlow $cartPurchaseFlow
0 ignored issues
show
introduced by
Expected 22 spaces after parameter type; 1 found
Loading history...
78
     * @param CustomerFavoriteProductRepository $customerFavoriteProductRepository
79
     * @param CartService $cartService
0 ignored issues
show
introduced by
Expected 23 spaces after parameter type; 1 found
Loading history...
80
     * @param ProductRepository $productRepository
0 ignored issues
show
introduced by
Expected 17 spaces after parameter type; 1 found
Loading history...
81
     * @param BaseInfo $BaseInfo
0 ignored issues
show
introduced by
Expected 26 spaces after parameter type; 1 found
Loading history...
82
     * @param AuthenticationUtils $helper
0 ignored issues
show
introduced by
Expected 15 spaces after parameter type; 1 found
Loading history...
83
     */
84 46
    public function __construct(
85
        PurchaseFlow $cartPurchaseFlow,
86
        CustomerFavoriteProductRepository $customerFavoriteProductRepository,
87
        CartService $cartService,
88
        ProductRepository $productRepository,
89
        BaseInfo $BaseInfo,
90
        AuthenticationUtils $helper
91
    ) {
92 46
        $this->purchaseFlow = $cartPurchaseFlow;
93 46
        $this->customerFavoriteProductRepository = $customerFavoriteProductRepository;
94 46
        $this->cartService = $cartService;
95 46
        $this->productRepository = $productRepository;
96 46
        $this->BaseInfo = $BaseInfo;
97 46
        $this->helper = $helper;
98
    }
99
100
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$paginator" missing
Loading history...
101
     * 商品一覧画面.
102
     *
103
     * @Route("/products/list", name="product_list")
104
     * @Template("Product/list.twig")
105
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
106 3
    public function index(Request $request, Paginator $paginator)
107
    {
108
        // Doctrine SQLFilter
109
        // if ($this->BaseInfo->isOptionNostockHidden()) {
110
        //     $this->entityManager->getFilters()->enable('option_nostock_hidden');
111
        // }
112
113
        // handleRequestは空のqueryの場合は無視するため
114 3
        if ($request->getMethod() === 'GET') {
115 3
            $request->query->set('pageno', $request->query->get('pageno', ''));
116
        }
117
118
        // searchForm
119
        /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
120 3
        $builder = $this->formFactory->createNamedBuilder('', SearchProductType::class);
121 3
        $builder->setAttribute('freeze', true);
122 3
        $builder->setAttribute('freeze_display_text', false);
123 3
        if ($request->getMethod() === 'GET') {
124 3
            $builder->setMethod('GET');
125
        }
126
127 3
        $event = new EventArgs(
128
            [
129 3
                'builder' => $builder,
130
            ],
131 3
            $request
132
        );
133 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event);
134
135
        /* @var $searchForm \Symfony\Component\Form\FormInterface */
136 3
        $searchForm = $builder->getForm();
137
138 3
        $searchForm->handleRequest($request);
139
140
        // paginator
141 3
        $searchData = $searchForm->getData();
142 3
        $qb = $this->productRepository->getQueryBuilderBySearchData($searchData);
143
144 3
        $event = new EventArgs(
145
            [
146 3
                'searchData' => $searchData,
147 3
                'qb' => $qb,
148
            ],
149 3
            $request
150
        );
151 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event);
152 3
        $searchData = $event->getArgument('searchData');
153
154 3
        $pagination = $paginator->paginate(
155 3
            $qb,
156 3
            !empty($searchData['pageno']) ? $searchData['pageno'] : 1,
157 3
            $searchData['disp_number']->getId()
158
        );
159
160
        // addCart form
161 3
        $forms = [];
162 3 View Code Duplication
        foreach ($pagination as $Product) {
0 ignored issues
show
Bug introduced by
The expression $pagination of type object<Knp\Component\Pag...on\PaginationInterface> is not traversable.
Loading history...
163
            /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
164 3
            $builder = $this->formFactory->createNamedBuilder(
165 3
                '',
166 3
                AddCartType::class,
167 3
                null,
168
                [
169 3
                    'product' => $Product,
170
                    'allow_extra_fields' => true,
171
                ]
172
            );
173 3
            $addCartForm = $builder->getForm();
174
175 3
            $forms[$Product->getId()] = $addCartForm->createView();
176
        }
177
178
        // 表示件数
179 3
        $builder = $this->formFactory->createNamedBuilder(
180 3
            'disp_number',
181 3
            ProductListMaxType::class,
182 3
            null,
183
            [
184 3
                'required' => false,
185 3
                'label' => trans('productcontroller.label.result'),
186
                'allow_extra_fields' => true,
187
            ]
188
        );
189 3
        if ($request->getMethod() === 'GET') {
190 3
            $builder->setMethod('GET');
191
        }
192
193 3
        $event = new EventArgs(
194
            [
195 3
                'builder' => $builder,
196
            ],
197 3
            $request
198
        );
199 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event);
200
201 3
        $dispNumberForm = $builder->getForm();
202
203 3
        $dispNumberForm->handleRequest($request);
204
205
        // ソート順
206 3
        $builder = $this->formFactory->createNamedBuilder(
207 3
            'orderby',
208 3
            ProductListOrderByType::class,
209 3
            null,
210
            [
211 3
                'required' => false,
212 3
                'label' => trans('productcontroller.label.sort'),
213
                'allow_extra_fields' => true,
214
            ]
215
        );
216 3
        if ($request->getMethod() === 'GET') {
217 3
            $builder->setMethod('GET');
218
        }
219
220 3
        $event = new EventArgs(
221
            [
222 3
                'builder' => $builder,
223
            ],
224 3
            $request
225
        );
226 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event);
227
228 3
        $orderByForm = $builder->getForm();
229
230 3
        $orderByForm->handleRequest($request);
231
232 3
        $Category = $searchForm->get('category_id')->getData();
233
234
        return [
235 3
            'subtitle' => $this->getPageTitle($searchData),
236 3
            'pagination' => $pagination,
237 3
            'search_form' => $searchForm->createView(),
238 3
            'disp_number_form' => $dispNumberForm->createView(),
239 3
            'order_by_form' => $orderByForm->createView(),
240 3
            'forms' => $forms,
241 3
            'Category' => $Category,
242
        ];
243
    }
244
245
    /**
246
     * 商品詳細画面.
247
     *
248
     * @Method("GET")
249
     * @Route("/products/detail/{id}", name="product_detail", requirements={"id" = "\d+"})
250
     * @Template("Product/detail.twig")
251
     * @ParamConverter("Product", options={"repository_method" = "findWithSortedClassCategories"})
252
     *
253
     * @param Request $request
254
     * @param Product $Product
255
     *
256
     * @return array
257
     */
258 11
    public function detail(Request $request, Product $Product)
259
    {
260 11
        if (!$this->checkVisibility($Product)) {
261
            throw new NotFoundHttpException();
262
        }
263
264 11
        $builder = $this->formFactory->createNamedBuilder(
265 11
            '',
266 11
            AddCartType::class,
267 11
            null,
268
            [
269 11
                'product' => $Product,
270
                'id_add_product_id' => false,
271
            ]
272
        );
273
274 11
        $event = new EventArgs(
275
            [
276 11
                'builder' => $builder,
277 11
                'Product' => $Product,
278
            ],
279 11
            $request
280
        );
281 11
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
282
283 11
        $is_favorite = false;
284 11
        if ($this->isGranted('ROLE_USER')) {
285 2
            $Customer = $this->getUser();
286 2
            $is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
0 ignored issues
show
Documentation introduced by
$Customer is of type null|object, but the function expects a object<Eccube\Entity\Customer>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
287
        }
288
289
        return [
290 11
            'title' => $this->title,
291 11
            'subtitle' => $Product->getName(),
292 11
            'form' => $builder->getForm()->createView(),
293 11
            'Product' => $Product,
294 11
            'is_favorite' => $is_favorite,
295
        ];
296
    }
297
298
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
299
     * お気に入り追加.
300
     *
301
     * @Route("/products/add_favorite/{id}", name="product_add_favorite", requirements={"id" = "\d+"})
302
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
303 3
    public function addFavorite(Request $request, Product $Product)
304
    {
305 3
        $this->checkVisibility($Product);
306
307 3
        $event = new EventArgs(
308
            [
309 3
                'Product' => $Product,
310
            ],
311 3
            $request
312
        );
313 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_INITIALIZE, $event);
314
315 3
        if ($this->isGranted('ROLE_USER')) {
316 2
            $Customer = $this->getUser();
317 2
            $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
0 ignored issues
show
Documentation introduced by
$Customer is of type null|object, but the function expects a object<Eccube\Entity\Customer>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
318 2
            $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
319
320 2
            $event = new EventArgs(
321
                [
322 2
                    'Product' => $Product,
323
                ],
324 2
                $request
325
            );
326 2
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
327
328 2
            return $this->redirectToRoute('product_detail', ['id' => $Product->getId()]);
329
        } else {
330
            // 非会員の場合、ログイン画面を表示
331
            //  ログイン後の画面遷移先を設定
332 1
            $this->setLoginTargetPath($this->generateUrl('product_add_favorite', ['id' => $Product->getId()]));
333 1
            $this->session->getFlashBag()->set('eccube.add.favorite', true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
334
335 1
            $event = new EventArgs(
336
                [
337 1
                    'Product' => $Product,
338
                ],
339 1
                $request
340
            );
341 1
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
342
343 1
            return $this->redirectToRoute('mypage_login');
344
        }
345
    }
346
347
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
348
     * カートに追加.
349
     *
350
     * @Method("POST")
351
     * @Route("/products/add_cart/{id}", name="product_add_cart", requirements={"id" = "\d+"})
352
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
353 37
    public function addCart(Request $request, Product $Product)
354
    {
355
        // エラーメッセージの配列
356 37
        $errorMessages = [];
357 37
        if (!$this->checkVisibility($Product)) {
358 1
            throw new NotFoundHttpException();
359
        }
360
361 36
        $builder = $this->formFactory->createNamedBuilder(
362 36
            '',
363 36
            AddCartType::class,
364 36
            null,
365
            [
366 36
                'product' => $Product,
367
                'id_add_product_id' => false,
368
            ]
369
        );
370
371 36
        $event = new EventArgs(
372
            [
373 36
                'builder' => $builder,
374 36
                'Product' => $Product,
375
            ],
376 36
            $request
377
        );
378 36
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event);
379
380
        /* @var $form \Symfony\Component\Form\FormInterface */
381 36
        $form = $builder->getForm();
382 36
        $form->handleRequest($request);
383
384 36
        if (!$form->isValid()) {
385 1
            throw new NotFoundHttpException();
386
        }
387
388 35
        $addCartData = $form->getData();
389
390 35
        log_info(
391 35
            'カート追加処理開始',
392
            [
393 35
                'product_id' => $Product->getId(),
394 35
                'product_class_id' => $addCartData['product_class_id'],
395 35
                'quantity' => $addCartData['quantity'],
396
            ]
397
        );
398
399
        // カートへ追加
400 35
        $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
401
402
        // 明細の正規化
403 35
        $Carts = $this->cartService->getCarts();
404 35
        foreach ($Carts as $Cart) {
405 35
            $result = $this->purchaseFlow->calculate($Cart, new PurchaseContext($Cart, $this->getUser()));
406
            // 復旧不可のエラーが発生した場合は追加した明細を削除.
407 35
            if ($result->hasError()) {
408
                $this->cartService->removeProduct($addCartData['product_class_id']);
409
                foreach ($result->getErrors() as $error) {
410
                    $errorMessages[] = $error->getMessage();
411
                }
412
            }
413 35
            foreach ($result->getWarning() as $warning) {
414 35
                $errorMessages[] = $warning->getMessage();
415
            }
416
        }
417
418 35
        $this->cartService->save();
419
420 35
        log_info(
421 35
            'カート追加処理完了',
422
            [
423 35
                'product_id' => $Product->getId(),
424 35
                'product_class_id' => $addCartData['product_class_id'],
425 35
                'quantity' => $addCartData['quantity'],
426
            ]
427
        );
428
429 35
        $event = new EventArgs(
430
            [
431 35
                'form' => $form,
432 35
                'Product' => $Product,
433
            ],
434 35
            $request
435
        );
436 35
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event);
437
438 35
        if ($event->getResponse() !== null) {
439
            return $event->getResponse();
440
        }
441
442 35
        if ($request->isXmlHttpRequest()) {
443
            // ajaxでのリクエストの場合は結果をjson形式で返す。
444
445
            // 初期化
446
            $done = null;
0 ignored issues
show
Unused Code introduced by
$done is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
447
            $messages = [];
448
449
            if (empty($errorMessages)) {
450
                // エラーが発生していない場合
451
                $done = true;
452
                array_push($messages, 'カートに追加しました。');
453
            } else {
454
                // エラーが発生している場合
455
                $done = false;
456
                $messages = $errorMessages;
457
            }
458
459
            return new JsonResponse(['done' => $done, 'messages' => $messages]);
460
        } else {
461
            // ajax以外でのリクエストの場合はカート画面へリダイレクト
462 35
            foreach ($errorMessages as $errorMessage) {
463 5
                $this->addRequestError($errorMessage);
464
            }
465
466 35
            return $this->redirectToRoute('cart');
467
        }
468
    }
469
470
    /**
471
     * ページタイトルの設定
472
     *
473
     * @param  null|array $searchData
474
     *
475
     * @return str
476
     */
477 3
    private function getPageTitle($searchData)
478
    {
479 3
        if (isset($searchData['name']) && !empty($searchData['name'])) {
480
            return trans('productcontroller.text.return.search');
481 3
        } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
482 1
            return $searchData['category_id']->getName();
483
        } else {
484 2
            return trans('productcontroller.text.return.all_products');
485
        }
486
    }
487
488
    /**
489
     * 閲覧可能な商品かどうかを判定
490
     *
491
     * @param Product $Product
492
     *
493
     * @return boolean 閲覧可能な場合はtrue
494
     */
495 43
    private function checkVisibility(Product $Product)
496
    {
497 43
        $is_admin = $this->session->has('_security_admin');
498
499
        // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
500 43
        if (!$is_admin) {
501
            // 在庫なし商品の非表示オプションが有効な場合.
502
            // if ($this->BaseInfo->isOptionNostockHidden()) {
503
            //     if (!$Product->getStockFind()) {
504
            //         return false;
505
            //     }
506
            // }
507
            // 公開ステータスでない商品は表示しない.
508 43
            if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
509 1
                return false;
510
            }
511
        }
512
513 43
        return true;
514
    }
515
}
516