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

ProductController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
crap 2
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->isNostockHidden()) {
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...
introduced by
Doc comment for parameter "$request" 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, Request $request, Product $Product)
351 2
    {
352 2
        $this->checkVisibility($Product);
353 2
354
        $event = new EventArgs(
355 2
            array(
356
                'Product' => $Product,
357 2
            ),
358 2
            $request
359
        );
360 2
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_INITIALIZE, $event);
361
362 2
363
        if ($app->isGranted('ROLE_USER')) {
364 2
            $Customer = $app->user();
365
            $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
366
            $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
367
368 2
            $event = new EventArgs(
369
                array(
370
                    'Product' => $Product,
371
                ),
372
                $request
373
            );
374
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
375
376
            return $app->redirect($app->url('product_detail', array('id' => $Product->getId())));
377 View Code Duplication
        } else {
378
            // 非会員の場合、ログイン画面を表示
379
            //  ログイン後の画面遷移先を設定
380
            $app->setLoginTargetPath($app->url('product_add_favorite', array('id' => $Product->getId())));
381
            $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...
382
383
            $event = new EventArgs(
384
                array(
385
                    'Product' => $Product,
386
                ),
387
                $request
388
            );
389
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
390
391
            return $app->redirect($app->url('mypage_login'));
392
        }
393
    }
394
395
    /**
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...
396
     * カートに追加.
397
     *
398
     * @Method("POST")
399
     * @Route("/products/add_cart/{id}", name="product_add_cart", requirements={"id" = "\d+"})
400
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
401
    public function addCart(Application $app, Request $request, Product $Product)
402
    {
403
        // エラーメッセージの配列
404
        $errorMessages = array();
405
406
        if (!$this->checkVisibility($Product)) {
407
            throw new NotFoundHttpException();
408
        }
409
410
        $builder = $this->formFactory->createNamedBuilder(
411
            '',
412
            AddCartType::class,
413
            null,
414
            array(
415
                'product' => $Product,
416
                'id_add_product_id' => false,
417
            )
418
        );
419
420
        $event = new EventArgs(
421
            array(
422
                'builder' => $builder,
423
                'Product' => $Product,
424
            ),
425
            $request
426
        );
427
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event);
428
429
        /* @var $form \Symfony\Component\Form\FormInterface */
430
        $form = $builder->getForm();
431
        $form->handleRequest($request);
432
433
        if (!$form->isValid()) {
434 1
            throw new NotFoundHttpException();
435
        }
436
437
        $addCartData = $form->getData();
438 3
439 3
        log_info(
440
            'カート追加処理開始',
441
            array(
442
                'product_id' => $Product->getId(),
443
                'product_class_id' => $addCartData['product_class_id'],
444
                'quantity' => $addCartData['quantity'],
445
            )
446
        );
447
448
        // カートへ追加
449 4
        $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
450 4
451 2
        // 明細の正規化
452 2
        $flow = $this->purchaseFlow;
453
        $Cart = $this->cartService->getCart();
454
        $result = $flow->calculate($Cart, $app['eccube.purchase.context']());
455
456 4
        // 復旧不可のエラーが発生した場合は追加した明細を削除.
457 4
        if ($result->hasError()) {
458 4
            $this->cartService->removeProduct($addCartData['product_class_id']);
459 4
            foreach ($result->getErrors() as $error) {
460 4
                array_push($errorMessages, $error->getMessage());
461
            }
462
        }
463
464
        foreach ($result->getWarning() as $warning) {
465
            array_push($errorMessages, $warning->getMessage());
466
        }
467
468
        $this->cartService->save();
469
470 3
        log_info(
471
            'カート追加処理完了',
472 3
            array(
473
                'product_id' => $Product->getId(),
474 3
                'product_class_id' => $addCartData['product_class_id'],
475 1
                'quantity' => $addCartData['quantity'],
476
            )
477 2
        );
478
479
        $event = new EventArgs(
480
            array(
481
                'form' => $form,
482
                'Product' => $Product,
483
            ),
484
            $request
485
        );
486
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event);
487
488
        if ($event->getResponse() !== null) {
489
            return $event->getResponse();
490
        }
491
        
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
492
        if ($request->isXmlHttpRequest()) {
493
            // ajaxでのリクエストの場合は結果をjson形式で返す。
494
495
        return $app->redirect($app->url('cart'));
496
            // 初期化
497
            $done = null;
0 ignored issues
show
Unused Code introduced by
// 初期化 $done = null; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
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...
498
            $messages = array();
499
500
            if (empty($errorMessages)) {
501
                // エラーが発生していない場合
502
                $done = true;
503
                array_push($messages, 'カートに追加しました。');
504
            } else {
505
                // エラーが発生している場合
506
                $done = false;
507
                $messages = $errorMessages;
508
            }
509
510
            return new JsonResponse(array('done' => $done, 'messages' => $messages));
511
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
512
        } else {
513
            // ajax以外でのリクエストの場合はカート画面へリダイレクト
514
            foreach ($errorMessages as $errorMessage) {
515
                $app->addRequestError($errorMessage);
516
            }
517
518
            return $app->redirect($app->url('cart'));
519
        }
520
    }
521
522
    /**
523
     * ページタイトルの設定
524
     *
525
     * @param  null|array $searchData
526
     * @return str
527
     */
528
    private function getPageTitle($searchData)
529
    {
530
        if (isset($searchData['name']) && !empty($searchData['name'])) {
531
            return '検索結果';
532
        } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
533
            return $searchData['category_id']->getName();
534
        } else {
535
            return '全商品';
536
        }
537
    }
538
539
    /**
540
     * 閲覧可能な商品かどうかを判定
541
     * @param Product $Product
542
     * @return boolean 閲覧可能な場合はtrue
543
     */
544
    private function checkVisibility(Product $Product)
545
    {
546
        $is_admin = $this->session->has('_security_admin');
547
548
        // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
549
        if (!$is_admin) {
550
            // 在庫なし商品の非表示オプションが有効な場合.
551
            if ($this->BaseInfo->isNostockHidden()) {
552
                if (!$Product->getStockFind()) {
553
                    return false;
554
                }
555
            }
556
            // 公開ステータスでない商品は表示しない.
557
            if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
558
                return false;
559
            }
560
        }
561
        return true;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
562
    }
563
}
564