Failed Conditions
Pull Request — experimental/3.1 (#2633)
by
unknown
58:45
created

ProductController::detail()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 39
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3.0416

Importance

Changes 0
Metric Value
cc 3
eloc 26
nc 3
nop 3
dl 0
loc 39
ccs 15
cts 18
cp 0.8333
crap 3.0416
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
25
namespace Eccube\Controller;
26
27
use Doctrine\ORM\EntityManager;
28
use Eccube\Annotation\Inject;
29
use Eccube\Application;
30
use Eccube\Common\Constant;
31
use Eccube\Entity\BaseInfo;
32
use Eccube\Entity\Master\ProductStatus;
33
use Eccube\Entity\Product;
34
use Eccube\Event\EccubeEvents;
35
use Eccube\Event\EventArgs;
36
use Eccube\Exception\CartException;
37
use Eccube\Form\Type\AddCartType;
38
use Eccube\Form\Type\Master\ProductListMaxType;
39
use Eccube\Form\Type\Master\ProductListOrderByType;
40
use Eccube\Form\Type\SearchProductType;
41
use Eccube\Repository\CustomerFavoriteProductRepository;
42
use Eccube\Repository\ProductRepository;
43
use Eccube\Service\CartService;
44
use Eccube\Service\PurchaseFlow\PurchaseFlow;
45
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
46
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
47
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
48
use Symfony\Component\EventDispatcher\EventDispatcher;
49
use Symfony\Component\Form\FormFactory;
50
use Symfony\Component\HttpFoundation\JsonResponse;
51
use Symfony\Component\HttpFoundation\Request;
52
use Symfony\Component\HttpFoundation\Session\Session;
53
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
54
55
/**
56
 * @Route(service=ProductController::class)
57
 */
58
class ProductController
59
{
60
    /**
61
     * @Inject("eccube.purchase.flow.cart")
62
     * @var PurchaseFlow
63
     */
64
    protected $purchaseFlow;
65
66
    /**
67
     * @Inject("session")
68
     * @var Session
69
     */
70
    protected $session;
71
72
    /**
73
     * @Inject(CustomerFavoriteProductRepository::class)
74
     * @var CustomerFavoriteProductRepository
75
     */
76
    protected $customerFavoriteProductRepository;
77
78
    /**
79
     * @Inject(CartService::class)
80
     * @var CartService
81
     */
82
    protected $cartService;
83
84
    /**
85
     * @Inject(ProductRepository::class)
86
     * @var ProductRepository
87
     */
88
    protected $productRepository;
89
90
    /**
91
     * @Inject("eccube.event.dispatcher")
92
     * @var EventDispatcher
93
     */
94
    protected $eventDispatcher;
95
96
    /**
97
     * @Inject("form.factory")
98
     * @var FormFactory
99
     */
100
    protected $formFactory;
101
102
    /**
103
     * @Inject("orm.em")
104
     * @var EntityManager
105
     */
106
    protected $entityManager;
107
108
    /**
109
     * @Inject(BaseInfo::class)
110
     * @var BaseInfo
111
     */
112
    protected $BaseInfo;
113
114
    private $title;
115
116
    public function __construct()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
117
    {
118
        $this->title = '';
119
    }
120
121
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$request" missing
Loading history...
122
     * 商品一覧画面.
123
     *
124
     * @Route("/products/list", name="product_list")
125
     * @Template("Product/list.twig")
126
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
127 3
    public function index(Application $app, Request $request)
128
    {
129
        // Doctrine SQLFilter
130 3
        if ($this->BaseInfo->getNostockHidden() === Constant::ENABLED) {
131
            $this->entityManager->getFilters()->enable('nostock_hidden');
132
        }
133
134
        // handleRequestは空のqueryの場合は無視するため
135 3
        if ($request->getMethod() === 'GET') {
136 3
            $request->query->set('pageno', $request->query->get('pageno', ''));
137
        }
138
139
        // searchForm
140
        /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
141 3
        $builder = $this->formFactory->createNamedBuilder('', SearchProductType::class);
142 3
        $builder->setAttribute('freeze', true);
143 3
        $builder->setAttribute('freeze_display_text', false);
144 3
        if ($request->getMethod() === 'GET') {
145 3
            $builder->setMethod('GET');
146
        }
147
148 3
        $event = new EventArgs(
149
            array(
150 3
                'builder' => $builder,
151
            ),
152 3
            $request
153
        );
154 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event);
155
156
        /* @var $searchForm \Symfony\Component\Form\FormInterface */
157 3
        $searchForm = $builder->getForm();
158
159 3
        $searchForm->handleRequest($request);
160
161
        // paginator
162 3
        $searchData = $searchForm->getData();
163 3
        $qb = $this->productRepository->getQueryBuilderBySearchData($searchData);
164
165 3
        $event = new EventArgs(
166
            array(
167 3
                'searchData' => $searchData,
168 3
                'qb' => $qb,
169
            ),
170 3
            $request
171
        );
172 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event);
173 3
        $searchData = $event->getArgument('searchData');
174
175 3
        $pagination = $app['paginator']()->paginate(
176 3
            $qb,
177 3
            !empty($searchData['pageno']) ? $searchData['pageno'] : 1,
178 3
            $searchData['disp_number']->getId()
179
        );
180
181
        // addCart form
182 3
        $forms = array();
183 3
        foreach ($pagination as $Product) {
184
            /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
185 3
            $builder = $this->formFactory->createNamedBuilder(
186 3
                '',
187 3
                AddCartType::class,
188 3
                null,
189
                array(
190 3
                    'product' => $Product,
191
                    'allow_extra_fields' => true,
192
                )
193
            );
194 3
            $addCartForm = $builder->getForm();
195
196 3
            if ($request->getMethod() === 'POST' && (string)$Product->getId() === $request->get('product_id')) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
197
                $addCartForm->handleRequest($request);
198
199
                if ($addCartForm->isValid()) {
200
                    $addCartData = $addCartForm->getData();
201
202
                    try {
203
                        $this->cartService->addProduct(
0 ignored issues
show
Bug introduced by
The method save cannot be called on $this->cartService->addP...ddCartData['quantity']) (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
204
                            $addCartData['product_class_id'],
205
                            $addCartData['quantity']
206
                        )->save();
207
                    } catch (CartException $e) {
208
                        $app->addRequestError($e->getMessage());
209
                    }
210
211
                    $event = new EventArgs(
212
                        array(
213
                            'form' => $addCartForm,
214
                            'Product' => $Product,
215
                        ),
216
                        $request
217
                    );
218
                    $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_COMPLETE, $event);
219
220
                    if ($event->getResponse() !== null) {
221
                        return $event->getResponse();
222
                    }
223
224
                    return $app->redirect($app->url('cart'));
225
                }
226
            }
227
228 3
            $forms[$Product->getId()] = $addCartForm->createView();
229
        }
230
231
        // 表示件数
232 3
        $builder = $this->formFactory->createNamedBuilder(
233 3
            'disp_number',
234 3
            ProductListMaxType::class,
235 3
            null,
236
            array(
237 3
                'required' => false,
238
                'label' => '表示件数',
239
                'allow_extra_fields' => true,
240
            )
241
        );
242 3
        if ($request->getMethod() === 'GET') {
243 3
            $builder->setMethod('GET');
244
        }
245
246 3
        $event = new EventArgs(
247
            array(
248 3
                'builder' => $builder,
249
            ),
250 3
            $request
251
        );
252 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event);
253
254 3
        $dispNumberForm = $builder->getForm();
255
256 3
        $dispNumberForm->handleRequest($request);
257
258
        // ソート順
259 3
        $builder = $this->formFactory->createNamedBuilder(
260 3
            'orderby',
261 3
            ProductListOrderByType::class,
262 3
            null,
263
            array(
264 3
                'required' => false,
265
                'label' => '表示順',
266
                'allow_extra_fields' => true,
267
            )
268
        );
269 3
        if ($request->getMethod() === 'GET') {
270 3
            $builder->setMethod('GET');
271
        }
272
273 3
        $event = new EventArgs(
274
            array(
275 3
                'builder' => $builder,
276
            ),
277 3
            $request
278
        );
279 3
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event);
280
281 3
        $orderByForm = $builder->getForm();
282
283 3
        $orderByForm->handleRequest($request);
284
285 3
        $Category = $searchForm->get('category_id')->getData();
286
287
        return [
288 3
            'subtitle' => $this->getPageTitle($searchData),
289 3
            'pagination' => $pagination,
290 3
            'search_form' => $searchForm->createView(),
291 3
            'disp_number_form' => $dispNumberForm->createView(),
292 3
            'order_by_form' => $orderByForm->createView(),
293 3
            'forms' => $forms,
294 3
            'Category' => $Category,
295
        ];
296
    }
297
298
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
299
     * 商品詳細画面.
300
     *
301
     * @Method("GET")
302
     * @Route("/products/detail/{id}", name="product_detail", requirements={"id" = "\d+"})
303
     * @Template("Product/detail.twig")
304 4
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
305
    public function detail(Application $app, Request $request, Product $Product)
306 4
    {
307
        if (!$this->checkVisibility($Product)) {
308
            throw new NotFoundHttpException();
309 4
        }
310
311 4
        $builder = $this->formFactory->createNamedBuilder(
312
            '',
313
            AddCartType::class,
314
            null,
315
            array(
316
                'product' => $Product,
317 4
                'id_add_product_id' => false,
318
            )
319
        );
320
321
        $event = new EventArgs(
322 4
            array(
323 4
                'builder' => $builder,
324 4
                'Product' => $Product,
325 4
            ),
326
            $request
327 4
        );
328
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
329
330
        $is_favorite = false;
331
        if ($app->isGranted('ROLE_USER')) {
332 4
            $Customer = $app->user();
333
            $is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
334 4
        }
335 4
336
        return [
337 4
            'title' => $this->title,
338
            'subtitle' => $Product->getName(),
339 4
            'form' => $builder->getForm()->createView(),
340
            'Product' => $Product,
341
            'is_favorite' => $is_favorite,
342 4
        ];
343
    }
344 4
345 3
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
346
     * お気に入り追加.
347 3
     *
348 2
     * @Route("/products/add_favorite/{id}", name="product_add_favorite", requirements={"id" = "\d+"})
349 2
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
350 2
    public function addFavorite(Application $app, Product $Product)
351 2
    {
352 2
        $this->checkVisibility($Product);
353 2
354
        // TODO イベント発火
355 2
356
        if ($app->isGranted('ROLE_USER')) {
357 2
            $Customer = $app->user();
358 2
            $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
359
            $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
360 2
361
            // TODO イベント発火
362 2
363
            return $app->redirect($app->url('product_detail', array('id' => $Product->getId())));
364 2
        } else {
365
            // 非会員の場合、ログイン画面を表示
366
            //  ログイン後の画面遷移先を設定
367
            $app->setLoginTargetPath($app->url('product_add_favorite', array('id' => $Product->getId())));
368 2
            $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...
369
370
            return $app->redirect($app->url('mypage_login'));
371
        }
372
    }
373
374
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
375
     * カートに追加.
376
     *
377
     * @Method("POST")
378
     * @Route("/products/add_cart/{id}", name="product_add_cart", requirements={"id" = "\d+"})
379
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
380
    public function addCart(Application $app, Request $request, Product $Product)
381
    {
382
        if (!$this->checkVisibility($Product)) {
383
            throw new NotFoundHttpException();
384
        }
385
386
        $builder = $this->formFactory->createNamedBuilder(
387
            '',
388
            AddCartType::class,
389
            null,
390
            array(
391
                'product' => $Product,
392
                'id_add_product_id' => false,
393
            )
394
        );
395
396
        // TODO イベント発火
397
//        $event = new EventArgs(
398
//            array(
399
//                'builder' => $builder,
400
//                'Product' => $Product,
401
//            ),
402
//            $request
403
//        );
404
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
405
406
        /* @var $form \Symfony\Component\Form\FormInterface */
407
        $form = $builder->getForm();
408
        $form->handleRequest($request);
409
410
        if (!$form->isValid()) {
411
            throw new NotFoundHttpException();
412
        }
413
414
        $addCartData = $form->getData();
415
416
        log_info(
417
            'カート追加処理開始',
418
            array(
419
                'product_id' => $Product->getId(),
420
                'product_class_id' => $addCartData['product_class_id'],
421
                'quantity' => $addCartData['quantity'],
422
            )
423
        );
424
425
        // カートへ追加
426
        $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
427
428
        // 明細の正規化
429
        $flow = $this->purchaseFlow;
430
        $Cart = $this->cartService->getCart();
431
        $result = $flow->calculate($Cart, $app['eccube.purchase.context']());
432
433
        // 復旧不可のエラーが発生した場合は追加した明細を削除.
434 1 View Code Duplication
        if ($result->hasError()) {
435
            $this->cartService->removeProduct($addCartData['product_class_id']);
436
            foreach ($result->getErrors() as $error) {
437
                $app->addRequestError($error->getMessage());
438 3
            }
439 3
        }
440
441
        foreach ($result->getWarning() as $warning) {
442
            $app->addRequestError($warning->getMessage());
443
        }
444
445
        $this->cartService->save();
446
447
        log_info(
448
            'カート追加処理完了',
449 4
            array(
450 4
                'product_id' => $Product->getId(),
451 2
                'product_class_id' => $addCartData['product_class_id'],
452 2
                'quantity' => $addCartData['quantity'],
453
            )
454
        );
455
456 4
        // TODO イベント発火
457 4
//        $event = new EventArgs(
458 4
//            array(
459 4
//                'form' => $form,
460 4
//                'Product' => $Product,
461
//            ),
462
//            $request
463
//        );
464
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_COMPLETE, $event);
465
//
466
//        if ($event->getResponse() !== null) {
467
//            return $event->getResponse();
468
//        }
469
470 3
        return $app->redirect($app->url('cart'));
471
472 3
    }
473
474 3
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$request" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
475 1
     * カートに追加.
476
     *
477 2
     * @Method("POST")
478
     * @Route("/products/add_cart_json/{id}", name="product_add_cart_json", requirements={"id" = "\d+"})
479
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
480
    public function addCartJson(Application $app, Request $request, Product $Product)
481
    {
482
        if (!$this->checkVisibility($Product)) {
483
            throw new NotFoundHttpException();
484
        }
485
486
        $builder = $this->formFactory->createNamedBuilder(
487
            '',
488
            AddCartType::class,
489
            null,
490
            array(
491
                'product' => $Product,
492
                'id_add_product_id' => false,
493
            )
494
        );
495
496
        // TODO イベント発火
497
//        $event = new EventArgs(
498
//            array(
499
//                'builder' => $builder,
500
//                'Product' => $Product,
501
//            ),
502
//            $request
503
//        );
504
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
505
506
        /* @var $form \Symfony\Component\Form\FormInterface */
507
        $form = $builder->getForm();
508
        $form->handleRequest($request);
509
510
//        $addCartData = $form->getData();
511
//        dump($addCartData);exit;
512
        if (!$form->isValid()) {
513
            throw new NotFoundHttpException();
514
        }
515
516
        $addCartData = $form->getData();
517
518
        log_info(
519
            'カート追加処理開始',
520
            array(
521
                'product_id' => $Product->getId(),
522
                'product_class_id' => $addCartData['product_class_id'],
523
                'quantity' => $addCartData['quantity'],
524
            )
525
        );
526
527
        // カートへ追加
528
        $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
529
530
        // 明細の正規化
531
        $flow = $this->purchaseFlow;
532
        $Cart = $this->cartService->getCart();
533
        $result = $flow->calculate($Cart, $app['eccube.purchase.context']());
534
535
        // 復旧不可のエラーが発生した場合は追加した明細を削除.
536 View Code Duplication
        if ($result->hasError()) {
537
            $this->cartService->removeProduct($addCartData['product_class_id']);
538
            foreach ($result->getErrors() as $error) {
539
                $app->addRequestError($error->getMessage());
540
            }
541
        }
542
543
        foreach ($result->getWarning() as $warning) {
544
            $app->addRequestError($warning->getMessage());
545
        }
546
547
        $this->cartService->save();
548
549
        log_info(
550
            'カート追加処理完了',
551
            array(
552
                'product_id' => $Product->getId(),
553
                'product_class_id' => $addCartData['product_class_id'],
554
                'quantity' => $addCartData['quantity'],
555
            )
556
        );
557
558
        // TODO イベント発火
559
//        $event = new EventArgs(
560
//            array(
561
//                'form' => $form,
562
//                'Product' => $Product,
563
//            ),
564
//            $request
565
//        );
566
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_COMPLETE, $event);
567
//
568
//        if ($event->getResponse() !== null) {
569
//            return $event->getResponse();
570
//        }
571
572
        /** @var \Symfony\Component\HttpFoundation\Session\Session $session */
573
        $session = $app["session"];
574
        $messages = $session->getFlashBag()->get("eccube.front.request.error");
575
576
        $done = false;
577
        if (empty($messages)){
578
            array_push($messages, 'カートに追加しました。');
579
            $done = true;
580
        }
581
        return new JsonResponse(array('done' => $done, 'messages' => $messages));
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
582
583
    }
584
    
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
585
    /**
586
     * ページタイトルの設定
587
     *
588
     * @param  null|array $searchData
589
     * @return str
590
     */
591
    private function getPageTitle($searchData)
592
    {
593
        if (isset($searchData['name']) && !empty($searchData['name'])) {
594
            return '検索結果';
595
        } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
596
            return $searchData['category_id']->getName();
597
        } else {
598
            return '全商品';
599
        }
600
    }
601
602
    /**
603
     * 閲覧可能な商品かどうかを判定
604
     * @param Product $Product
605
     * @return boolean 閲覧可能な場合はtrue
606
     */
607
    private function checkVisibility(Product $Product)
608
    {
609
        $is_admin = $this->session->has('_security_admin');
610
611
        // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
612
        if (!$is_admin) {
613
            // 在庫なし商品の非表示オプションが有効な場合.
614
            if ($this->BaseInfo->getNostockHidden()) {
615
                if (!$Product->getStockFind()) {
616
                    return false;
617
                }
618
            }
619
            // 公開ステータスでない商品は表示しない.
620
            if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
621
                return false;
622
            }
623
        }
624
        return true;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
625
    }
626
}
627