Failed Conditions
Pull Request — experimental/3.1 (#2630)
by Kiyotaka
110:46 queued 60:24
created

ProductController::addFavorite()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2.0017

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 2
dl 0
loc 23
ccs 12
cts 13
cp 0.9231
crap 2.0017
rs 9.0856
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\Request;
51
use Symfony\Component\HttpFoundation\Session\Session;
52
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
53
54
/**
55
 * @Route(service=ProductController::class)
56
 */
57
class ProductController
58
{
59
    /**
60
     * @Inject("eccube.purchase.flow.cart")
61
     * @var PurchaseFlow
62
     */
63
    protected $purchaseFlow;
64
65
    /**
66
     * @Inject("session")
67
     * @var Session
68
     */
69
    protected $session;
70
71
    /**
72
     * @Inject(CustomerFavoriteProductRepository::class)
73
     * @var CustomerFavoriteProductRepository
74
     */
75
    protected $customerFavoriteProductRepository;
76
77
    /**
78
     * @Inject(CartService::class)
79
     * @var CartService
80
     */
81
    protected $cartService;
82
83
    /**
84
     * @Inject(ProductRepository::class)
85
     * @var ProductRepository
86
     */
87
    protected $productRepository;
88
89
    /**
90
     * @Inject("eccube.event.dispatcher")
91
     * @var EventDispatcher
92
     */
93
    protected $eventDispatcher;
94
95
    /**
96
     * @Inject("form.factory")
97
     * @var FormFactory
98
     */
99
    protected $formFactory;
100
101
    /**
102
     * @Inject("orm.em")
103
     * @var EntityManager
104
     */
105
    protected $entityManager;
106
107
    /**
108
     * @Inject(BaseInfo::class)
109
     * @var BaseInfo
110
     */
111
    protected $BaseInfo;
112
113
    private $title;
114
115
    public function __construct()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
116
    {
117
        $this->title = '';
118
    }
119
120
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$request" missing
Loading history...
121
     * 商品一覧画面.
122
     *
123
     * @Route("/products/list", name="product_list")
124
     * @Template("Product/list.twig")
125
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
126
    public function index(Application $app, Request $request)
127 3
    {
128
        // Doctrine SQLFilter
129
        if ($this->BaseInfo->getNostockHidden() === Constant::ENABLED) {
130 3
            $this->entityManager->getFilters()->enable('nostock_hidden');
131
        }
132
133
        // handleRequestは空のqueryの場合は無視するため
134
        if ($request->getMethod() === 'GET') {
135 3
            $request->query->set('pageno', $request->query->get('pageno', ''));
136 3
        }
137
138
        // searchForm
139
        /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
140
        $builder = $this->formFactory->createNamedBuilder('', SearchProductType::class);
141 3
        $builder->setAttribute('freeze', true);
142 3
        $builder->setAttribute('freeze_display_text', false);
143 3
        if ($request->getMethod() === 'GET') {
144 3
            $builder->setMethod('GET');
145 3
        }
146
147
        $event = new EventArgs(
148 3
            array(
149
                'builder' => $builder,
150 3
            ),
151
            $request
152 3
        );
153
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event);
154 3
155
        /* @var $searchForm \Symfony\Component\Form\FormInterface */
156
        $searchForm = $builder->getForm();
157 3
158
        $searchForm->handleRequest($request);
159 3
160
        // paginator
161
        $searchData = $searchForm->getData();
162 3
        $qb = $this->productRepository->getQueryBuilderBySearchData($searchData);
163 3
164
        $event = new EventArgs(
165 3
            array(
166
                'searchData' => $searchData,
167 3
                'qb' => $qb,
168 3
            ),
169
            $request
170 3
        );
171
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event);
172 3
        $searchData = $event->getArgument('searchData');
173 3
174
        $pagination = $app['paginator']()->paginate(
175 3
            $qb,
176 3
            !empty($searchData['pageno']) ? $searchData['pageno'] : 1,
177 3
            $searchData['disp_number']->getId()
178 3
        );
179
180
        // addCart form
181
        $forms = array();
182 3
        foreach ($pagination as $Product) {
183 3
            /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
184
            $builder = $this->formFactory->createNamedBuilder(
185 3
                '',
186 3
                AddCartType::class,
187 3
                null,
188 3
                array(
189
                    'product' => $Product,
190 3
                    'allow_extra_fields' => true,
191
                )
192
            );
193
            $addCartForm = $builder->getForm();
194 3
195
            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...
196 3
                $addCartForm->handleRequest($request);
197
198
                if ($addCartForm->isValid()) {
199
                    $addCartData = $addCartForm->getData();
200
201
                    try {
202
                        $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...
203
                            $addCartData['product_class_id'],
204
                            $addCartData['quantity']
205
                        )->save();
206
                    } catch (CartException $e) {
207
                        $app->addRequestError($e->getMessage());
208
                    }
209
210
                    $event = new EventArgs(
211
                        array(
212
                            'form' => $addCartForm,
213
                            'Product' => $Product,
214
                        ),
215
                        $request
216
                    );
217
                    $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_COMPLETE, $event);
218
219
                    if ($event->getResponse() !== null) {
220
                        return $event->getResponse();
221
                    }
222
223
                    return $app->redirect($app->url('cart'));
224
                }
225
            }
226
227
            $forms[$Product->getId()] = $addCartForm->createView();
228 3
        }
229
230
        // 表示件数
231
        $builder = $this->formFactory->createNamedBuilder(
232 3
            'disp_number',
233 3
            ProductListMaxType::class,
234 3
            null,
235 3
            array(
236
                'required' => false,
237 3
                'label' => '表示件数',
238
                'allow_extra_fields' => true,
239
            )
240
        );
241
        if ($request->getMethod() === 'GET') {
242 3
            $builder->setMethod('GET');
243 3
        }
244
245
        $event = new EventArgs(
246 3
            array(
247
                'builder' => $builder,
248 3
            ),
249
            $request
250 3
        );
251
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event);
252 3
253
        $dispNumberForm = $builder->getForm();
254 3
255
        $dispNumberForm->handleRequest($request);
256 3
257
        // ソート順
258
        $builder = $this->formFactory->createNamedBuilder(
259 3
            'orderby',
260 3
            ProductListOrderByType::class,
261 3
            null,
262 3
            array(
263
                'required' => false,
264 3
                'label' => '表示順',
265
                'allow_extra_fields' => true,
266
            )
267
        );
268
        if ($request->getMethod() === 'GET') {
269 3
            $builder->setMethod('GET');
270 3
        }
271
272
        $event = new EventArgs(
273 3
            array(
274
                'builder' => $builder,
275 3
            ),
276
            $request
277 3
        );
278
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event);
279 3
280
        $orderByForm = $builder->getForm();
281 3
282
        $orderByForm->handleRequest($request);
283 3
284
        $Category = $searchForm->get('category_id')->getData();
285 3
286
        return [
287
            'subtitle' => $this->getPageTitle($searchData),
288 3
            'pagination' => $pagination,
289 3
            'search_form' => $searchForm->createView(),
290 3
            'disp_number_form' => $dispNumberForm->createView(),
291 3
            'order_by_form' => $orderByForm->createView(),
292 3
            'forms' => $forms,
293 3
            'Category' => $Category,
294 3
        ];
295
    }
296
297
    /**
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...
298
     * 商品詳細画面.
299
     *
300
     * @Method("GET")
301
     * @Route("/products/detail/{id}", name="product_detail", requirements={"id" = "\d+"})
302
     * @Template("Product/detail.twig")
303
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
304 4
    public function detail(Application $app, Request $request, Product $Product)
305
    {
306 4
        if (!$this->checkVisibility($Product)) {
307
            throw new NotFoundHttpException();
308
        }
309 4
310
        $builder = $this->formFactory->createNamedBuilder(
311 4
            '',
312
            AddCartType::class,
313
            null,
314
            array(
315
                'product' => $Product,
316
                'id_add_product_id' => false,
317 4
            )
318
        );
319
320
        $event = new EventArgs(
321
            array(
322 4
                'builder' => $builder,
323 4
                'Product' => $Product,
324 4
            ),
325 4
            $request
326
        );
327 4
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
328
329
        $is_favorite = false;
330
        if ($app->isGranted('ROLE_USER')) {
331
            $Customer = $app->user();
332 4
            $is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
333
        }
334 4
335 4
        return [
336
            'title' => $this->title,
337 4
            'subtitle' => $Product->getName(),
338
            'form' => $builder->getForm()->createView(),
339 4
            'Product' => $Product,
340
            'is_favorite' => $is_favorite,
341
        ];
342 4
    }
343
344 4
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
introduced by
Doc comment for parameter "$Product" missing
Loading history...
345 3
     * お気に入り追加.
346
     *
347 3
     * @Route("/products/add_favorite/{id}", name="product_add_favorite", requirements={"id" = "\d+"})
348 2
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
349 2
    public function addFavorite(Application $app, Product $Product)
350 2
    {
351 2
        $this->checkVisibility($Product);
352 2
353 2
        // TODO イベント発火
354
355 2
        if ($app->isGranted('ROLE_USER')) {
356
            $Customer = $app->user();
357 2
            $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
358 2
            $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
359
360 2
            // TODO イベント発火
361
362 2
            return $app->redirect($app->url('product_detail', array('id' => $Product->getId())));
363
        } else {
364 2
            // 非会員の場合、ログイン画面を表示
365
            //  ログイン後の画面遷移先を設定
366
            $app->setLoginTargetPath($app->url('product_add_favorite', array('id' => $Product->getId())));
367
            $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...
368 2
369
            return $app->redirect($app->url('mypage_login'));
370
        }
371
    }
372
373
    /**
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...
374
     * カートに追加.
375
     *
376
     * @Method("POST")
377
     * @Route("/products/add_cart/{id}", name="product_add_cart", requirements={"id" = "\d+"})
378
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
379
    public function addCart(Application $app, Request $request, Product $Product)
380
    {
381
        if (!$this->checkVisibility($Product)) {
382
            throw new NotFoundHttpException();
383
        }
384
385
        $builder = $this->formFactory->createNamedBuilder(
386
            '',
387
            AddCartType::class,
388
            null,
389
            array(
390
                'product' => $Product,
391
                'id_add_product_id' => false,
392
            )
393
        );
394
395
        // TODO イベント発火
396
//        $event = new EventArgs(
397
//            array(
398
//                'builder' => $builder,
399
//                'Product' => $Product,
400
//            ),
401
//            $request
402
//        );
403
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
404
405
        /* @var $form \Symfony\Component\Form\FormInterface */
406
        $form = $builder->getForm();
407
        $form->handleRequest($request);
408
409
        if (!$form->isValid()) {
410
            throw new NotFoundHttpException();
411
        }
412
413
        $addCartData = $form->getData();
414
415
        log_info(
416
            'カート追加処理開始',
417
            array(
418
                'product_id' => $Product->getId(),
419
                'product_class_id' => $addCartData['product_class_id'],
420
                'quantity' => $addCartData['quantity'],
421
            )
422
        );
423
424
        // カートへ追加
425
        $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
426
427
        // 明細の正規化
428
        $flow = $this->purchaseFlow;
429
        $Cart = $this->cartService->getCart();
430
        $result = $flow->calculate($Cart, $app['eccube.purchase.context']());
431
432
        // 復旧不可のエラーが発生した場合は追加した明細を削除.
433
        if ($result->hasError()) {
434 1
            $this->cartService->removeProduct($addCartData['product_class_id']);
435
            foreach ($result->getErrors() as $error) {
436
                $app->addRequestError($error->getMessage());
437
            }
438 3
        }
439 3
440
        foreach ($result->getWarning() as $warning) {
441
            $app->addRequestError($warning->getMessage());
442
        }
443
444
        $this->cartService->save();
445
446
        log_info(
447
            'カート追加処理完了',
448
            array(
449 4
                'product_id' => $Product->getId(),
450 4
                'product_class_id' => $addCartData['product_class_id'],
451 2
                'quantity' => $addCartData['quantity'],
452 2
            )
453
        );
454
455
        // TODO イベント発火
456 4
//        $event = new EventArgs(
457 4
//            array(
458 4
//                'form' => $form,
459 4
//                'Product' => $Product,
460 4
//            ),
461
//            $request
462
//        );
463
//        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_COMPLETE, $event);
464
//
465
//        if ($event->getResponse() !== null) {
466
//            return $event->getResponse();
467
//        }
468
469
        return $app->redirect($app->url('cart'));
470 3
471
    }
472 3
473
    /**
474 3
     * ページタイトルの設定
475 1
     *
476
     * @param  null|array $searchData
477 2
     * @return str
478
     */
479
    private function getPageTitle($searchData)
480
    {
481
        if (isset($searchData['name']) && !empty($searchData['name'])) {
482
            return '検索結果';
483
        } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
484
            return $searchData['category_id']->getName();
485
        } else {
486
            return '全商品';
487
        }
488
    }
489
490
    /**
491
     * 閲覧可能な商品かどうかを判定
492
     * @param Product $Product
493
     * @return boolean 閲覧可能な場合はtrue
494
     */
495
    private function checkVisibility(Product $Product)
496
    {
497
        $is_admin = $this->session->has('_security_admin');
498
499
        // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
500
        if (!$is_admin) {
501
            // 在庫なし商品の非表示オプションが有効な場合.
502
            if ($this->BaseInfo->getNostockHidden()) {
503
                if (!$Product->getStockFind()) {
504
                    return false;
505
                }
506
            }
507
            // 公開ステータスでない商品は表示しない.
508
            if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
509
                return false;
510
            }
511
        }
512
        return true;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
513
    }
514
}
515