Completed
Pull Request — experimental/3.1 (#2484)
by Kentaro
57:08 queued 35:11
created

ProductController   C

Complexity

Total Complexity 37

Size/Duplication

Total Lines 421
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Test Coverage

Coverage 66.3%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 421
ccs 120
cts 181
cp 0.663
rs 5.9125
c 1
b 0
f 0
wmc 37
lcom 1
cbo 19

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
D index() 0 170 13
D detail() 0 157 18
B getPageTitle() 0 10 5
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\Component;
29
use Eccube\Annotation\Inject;
30
use Eccube\Application;
31
use Eccube\Entity\BaseInfo;
32
use Eccube\Common\Constant;
33
use Eccube\Entity\ProductClass;
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\BaseInfoRepository;
42
use Eccube\Repository\CustomerFavoriteProductRepository;
43
use Eccube\Repository\ProductRepository;
44
use Eccube\Service\CartService;
45
use Eccube\Service\PurchaseFlow\PurchaseFlow;
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
 * @Component
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 "$id" missing
Loading history...
299
     * 商品詳細画面.
300
     *
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, $id)
305
    {
306 4
        if ($this->BaseInfo->getNostockHidden() === Constant::ENABLED) {
307
            $this->entityManager->getFilters()->enable('nostock_hidden');
308
        }
309
310
        /* @var $Product \Eccube\Entity\Product */
311 4
        $Product = $this->productRepository->get($id);
0 ignored issues
show
Deprecated Code introduced by
The method Eccube\Repository\ProductRepository::get() has been deprecated with message: Use ProductRepository::find()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
312 4
        if (!$request->getSession()->has('_security_admin') && $Product->getStatus()->getId() !== 1) {
313
            throw new NotFoundHttpException();
314
        }
315 4
        if (count($Product->getProductClasses()) < 1) {
316
            throw new NotFoundHttpException();
317
        }
318
319
        /* @var $builder \Symfony\Component\Form\FormBuilderInterface */
320 4
        $builder = $this->formFactory->createNamedBuilder(
321 4
            '',
322 4
            AddCartType::class,
323 4
            null,
324
            array(
325 4
                'product' => $Product,
326
                'id_add_product_id' => false,
327
            )
328
        );
329
330 4
        $event = new EventArgs(
331
            array(
332 4
                'builder' => $builder,
333 4
                'Product' => $Product,
334
            ),
335 4
            $request
336
        );
337 4
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
338
339
        /* @var $form \Symfony\Component\Form\FormInterface */
340 4
        $form = $builder->getForm();
341
342 4
        if ($request->getMethod() === 'POST') {
343 3
            $form->handleRequest($request);
344
345 3
            if ($form->isValid()) {
346 2
                $addCartData = $form->getData();
347 2
                if ($addCartData['mode'] === 'add_favorite') {
348 2
                    if ($app->isGranted('ROLE_USER')) {
349 2
                        $Customer = $app->user();
350 2
                        $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
351 2
                        $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
352
353 2
                        $event = new EventArgs(
354
                            array(
355 2
                                'form' => $form,
356 2
                                'Product' => $Product,
357
                            ),
358 2
                            $request
359
                        );
360 2
                        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_FAVORITE, $event);
361
362 2
                        if ($event->getResponse() !== null) {
363
                            return $event->getResponse();
364
                        }
365
366 2
                        return $app->redirect($app->url('product_detail', array('id' => $Product->getId())));
367
                    } else {
368
                        // 非会員の場合、ログイン画面を表示
369
                        //  ログイン後の画面遷移先を設定
370
                        $app->setLoginTargetPath($app->url('product_detail', array('id' => $Product->getId())));
371
                        $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...
372
373
                        return $app->redirect($app->url('mypage_login'));
374
                    }
375
                } elseif ($addCartData['mode'] === 'add_cart') {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
376
377
                    log_info(
378
                        'カート追加処理開始',
379
                        array(
380
                            'product_id' => $Product->getId(),
381
                            'product_class_id' => $addCartData['product_class_id'],
382
                            'quantity' => $addCartData['quantity'],
383
                        )
384
                    );
385
386
                    // カートを取得
387
                    $Cart = $this->cartService->getCart();
388
389
                    // カートへ追加
390
                    $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']);
391
392
                    // 明細の正規化
393
                    $flow = $this->purchaseFlow;
394
                    $result = $flow->calculate($Cart, $app['eccube.purchase.context']());
395
396
                    // 復旧不可のエラーが発生した場合は追加した明細を削除.
397
                    if ($result->hasError()) {
398
                        $Cart->removeCartItemByIdentifier(ProductClass::class, $addCartData['product_class_id']);
399
                        foreach ($result->getErrors() as $error) {
400
                            $app->addRequestError($error->getMessage());
401
                        }
402
                    }
403
404
                    foreach ($result->getWarning() as $warning) {
405
                        $app->addRequestError($warning->getMessage());
406
                    }
407
408
                    $this->cartService->save();
409
410
                    log_info(
411
                        'カート追加処理完了',
412
                        array(
413
                            'product_id' => $Product->getId(),
414
                            'product_class_id' => $addCartData['product_class_id'],
415
                            'quantity' => $addCartData['quantity'],
416
                        )
417
                    );
418
419
                    $event = new EventArgs(
420
                        array(
421
                            'form' => $form,
422
                            'Product' => $Product,
423
                        ),
424
                        $request
425
                    );
426
                    $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_COMPLETE, $event);
427
428
                    if ($event->getResponse() !== null) {
429
                        return $event->getResponse();
430
                    }
431
432 1
                    return $app->redirect($app->url('cart'));
433
                }
434
            }
435
        } else {
436 3
            $addFavorite = $this->session->getFlashBag()->get('eccube.add.favorite');
437 3
            if (!empty($addFavorite)) {
438
                // お気に入り登録時にログインされていない場合、ログイン後にお気に入り追加処理を行う
439
                if ($app->isGranted('ROLE_USER')) {
440
                    $Customer = $app->user();
441
                    $this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
442
                    $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
443
                }
444
            }
445
        }
446
447 4
        $is_favorite = false;
448 4
        if ($app->isGranted('ROLE_USER')) {
449 2
            $Customer = $app->user();
450 2
            $is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
451
        }
452
453
        return [
454 4
            'title' => $this->title,
455 4
            'subtitle' => $Product->getName(),
456 4
            'form' => $form->createView(),
457 4
            'Product' => $Product,
458 4
            'is_favorite' => $is_favorite,
459
        ];
460
    }
461
462
    /**
463
     * ページタイトルの設定
464
     *
465
     * @param  null|array $searchData
466
     * @return str
467
     */
468 3
    private function getPageTitle($searchData)
469
    {
470 3
        if (isset($searchData['name']) && !empty($searchData['name'])) {
471
            return '検索結果';
472 3
        } elseif (isset($searchData['category_id']) && $searchData['category_id']) {
473 1
            return $searchData['category_id']->getName();
474
        } else {
475 2
            return '全商品';
476
        }
477
    }
478
}
479