These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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\BaseInfoRepository; |
||
26 | use Eccube\Repository\CustomerFavoriteProductRepository; |
||
27 | use Eccube\Repository\Master\ProductListMaxRepository; |
||
28 | use Eccube\Repository\ProductRepository; |
||
29 | use Eccube\Service\CartService; |
||
30 | use Eccube\Service\PurchaseFlow\PurchaseContext; |
||
31 | use Eccube\Service\PurchaseFlow\PurchaseFlow; |
||
32 | use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination; |
||
33 | use Knp\Component\Pager\Paginator; |
||
34 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
||
35 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
||
36 | use Symfony\Component\HttpFoundation\Request; |
||
37 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
||
38 | use Symfony\Component\Routing\Annotation\Route; |
||
39 | use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; |
||
40 | |||
41 | class ProductController extends AbstractController |
||
42 | { |
||
43 | /** |
||
44 | * @var PurchaseFlow |
||
45 | */ |
||
46 | protected $purchaseFlow; |
||
47 | |||
48 | /** |
||
49 | * @var CustomerFavoriteProductRepository |
||
50 | */ |
||
51 | protected $customerFavoriteProductRepository; |
||
52 | |||
53 | /** |
||
54 | * @var CartService |
||
55 | */ |
||
56 | protected $cartService; |
||
57 | |||
58 | /** |
||
59 | * @var ProductRepository |
||
60 | */ |
||
61 | protected $productRepository; |
||
62 | |||
63 | /** |
||
64 | * @var BaseInfo |
||
65 | */ |
||
66 | protected $BaseInfo; |
||
67 | |||
68 | /** |
||
69 | * @var AuthenticationUtils |
||
70 | */ |
||
71 | protected $helper; |
||
72 | |||
73 | /** |
||
74 | * @var ProductListMaxRepository |
||
75 | */ |
||
76 | protected $productListMaxRepository; |
||
77 | |||
78 | private $title = ''; |
||
79 | |||
80 | /** |
||
81 | * ProductController constructor. |
||
82 | * |
||
83 | * @param PurchaseFlow $cartPurchaseFlow |
||
84 | 46 | * @param CustomerFavoriteProductRepository $customerFavoriteProductRepository |
|
85 | * @param CartService $cartService |
||
86 | * @param ProductRepository $productRepository |
||
87 | * @param BaseInfoRepository $baseInfoRepository |
||
88 | * @param AuthenticationUtils $helper |
||
89 | * @param ProductListMaxRepository $productListMaxRepository |
||
90 | */ |
||
91 | public function __construct( |
||
92 | 46 | PurchaseFlow $cartPurchaseFlow, |
|
93 | 46 | CustomerFavoriteProductRepository $customerFavoriteProductRepository, |
|
94 | 46 | CartService $cartService, |
|
95 | 46 | ProductRepository $productRepository, |
|
96 | 46 | BaseInfoRepository $baseInfoRepository, |
|
97 | 46 | AuthenticationUtils $helper, |
|
98 | ProductListMaxRepository $productListMaxRepository |
||
99 | ) { |
||
100 | $this->purchaseFlow = $cartPurchaseFlow; |
||
101 | $this->customerFavoriteProductRepository = $customerFavoriteProductRepository; |
||
102 | $this->cartService = $cartService; |
||
103 | $this->productRepository = $productRepository; |
||
104 | $this->BaseInfo = $baseInfoRepository->get(); |
||
105 | $this->helper = $helper; |
||
106 | 3 | $this->productListMaxRepository = $productListMaxRepository; |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * 商品一覧画面. |
||
111 | * |
||
112 | * @Route("/products/list", name="product_list") |
||
113 | * @Template("Product/list.twig") |
||
114 | 3 | */ |
|
115 | 3 | public function index(Request $request, Paginator $paginator) |
|
116 | { |
||
117 | // Doctrine SQLFilter |
||
118 | if ($this->BaseInfo->isOptionNostockHidden()) { |
||
119 | $this->entityManager->getFilters()->enable('option_nostock_hidden'); |
||
120 | 3 | } |
|
121 | 3 | ||
122 | 3 | // handleRequestは空のqueryの場合は無視するため |
|
123 | 3 | if ($request->getMethod() === 'GET') { |
|
124 | 3 | $request->query->set('pageno', $request->query->get('pageno', '')); |
|
125 | } |
||
126 | |||
127 | 3 | // searchForm |
|
128 | /* @var $builder \Symfony\Component\Form\FormBuilderInterface */ |
||
129 | 3 | $builder = $this->formFactory->createNamedBuilder('', SearchProductType::class); |
|
130 | |||
131 | 3 | if ($request->getMethod() === 'GET') { |
|
132 | $builder->setMethod('GET'); |
||
133 | 3 | } |
|
134 | |||
135 | $event = new EventArgs( |
||
136 | 3 | [ |
|
137 | 'builder' => $builder, |
||
138 | 3 | ], |
|
139 | $request |
||
140 | ); |
||
141 | 3 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event); |
|
142 | 3 | ||
143 | /* @var $searchForm \Symfony\Component\Form\FormInterface */ |
||
144 | 3 | $searchForm = $builder->getForm(); |
|
145 | |||
146 | 3 | $searchForm->handleRequest($request); |
|
147 | 3 | ||
148 | // paginator |
||
149 | 3 | $searchData = $searchForm->getData(); |
|
150 | $qb = $this->productRepository->getQueryBuilderBySearchData($searchData); |
||
151 | 3 | ||
152 | 3 | $event = new EventArgs( |
|
153 | [ |
||
154 | 3 | 'searchData' => $searchData, |
|
155 | 3 | 'qb' => $qb, |
|
156 | 3 | ], |
|
157 | 3 | $request |
|
158 | ); |
||
159 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event); |
||
160 | $searchData = $event->getArgument('searchData'); |
||
161 | 3 | ||
162 | 3 | $query = $qb->getQuery() |
|
163 | ->useResultCache(true, $this->eccubeConfig['eccube_result_cache_lifetime_short']); |
||
164 | 3 | ||
165 | 3 | /** @var SlidingPagination $pagination */ |
|
166 | 3 | $pagination = $paginator->paginate( |
|
167 | 3 | $query, |
|
168 | !empty($searchData['pageno']) ? $searchData['pageno'] : 1, |
||
169 | 3 | !empty($searchData['disp_number']) ? $searchData['disp_number']->getId() : $this->productListMaxRepository->findOneBy([], ['sort_no' => 'ASC'])->getId() |
|
170 | ); |
||
171 | |||
172 | $ids = []; |
||
173 | 3 | foreach ($pagination as $Product) { |
|
174 | $ids[] = $Product->getId(); |
||
175 | 3 | } |
|
176 | $ProductsAndClassCategories = $this->productRepository->findProductsWithSortedClassCategories($ids, 'p.id'); |
||
177 | |||
178 | // addCart form |
||
179 | 3 | $forms = []; |
|
180 | 3 | View Code Duplication | foreach ($pagination as $Product) { |
181 | 3 | /* @var $builder \Symfony\Component\Form\FormBuilderInterface */ |
|
182 | 3 | $builder = $this->formFactory->createNamedBuilder( |
|
183 | '', |
||
184 | 3 | AddCartType::class, |
|
185 | 3 | null, |
|
186 | [ |
||
187 | 'product' => $ProductsAndClassCategories[$Product->getId()], |
||
188 | 'allow_extra_fields' => true, |
||
189 | 3 | ] |
|
190 | 3 | ); |
|
191 | $addCartForm = $builder->getForm(); |
||
192 | |||
193 | 3 | $forms[$Product->getId()] = $addCartForm->createView(); |
|
194 | } |
||
195 | 3 | ||
196 | // 表示件数 |
||
197 | 3 | $builder = $this->formFactory->createNamedBuilder( |
|
198 | 'disp_number', |
||
199 | 3 | ProductListMaxType::class, |
|
200 | null, |
||
201 | 3 | [ |
|
202 | 'required' => false, |
||
203 | 3 | 'allow_extra_fields' => true, |
|
204 | ] |
||
205 | ); |
||
206 | 3 | if ($request->getMethod() === 'GET') { |
|
207 | 3 | $builder->setMethod('GET'); |
|
208 | 3 | } |
|
209 | 3 | ||
210 | $event = new EventArgs( |
||
211 | 3 | [ |
|
212 | 3 | 'builder' => $builder, |
|
213 | ], |
||
214 | $request |
||
215 | ); |
||
216 | 3 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event); |
|
217 | 3 | ||
218 | $dispNumberForm = $builder->getForm(); |
||
219 | |||
220 | 3 | $dispNumberForm->handleRequest($request); |
|
221 | |||
222 | 3 | // ソート順 |
|
223 | $builder = $this->formFactory->createNamedBuilder( |
||
224 | 3 | 'orderby', |
|
225 | ProductListOrderByType::class, |
||
226 | 3 | null, |
|
227 | [ |
||
228 | 3 | 'required' => false, |
|
229 | 'allow_extra_fields' => true, |
||
230 | 3 | ] |
|
231 | ); |
||
232 | 3 | if ($request->getMethod() === 'GET') { |
|
233 | $builder->setMethod('GET'); |
||
234 | } |
||
235 | 3 | ||
236 | 3 | $event = new EventArgs( |
|
237 | 3 | [ |
|
238 | 3 | 'builder' => $builder, |
|
239 | 3 | ], |
|
240 | 3 | $request |
|
241 | 3 | ); |
|
242 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event); |
||
243 | |||
244 | $orderByForm = $builder->getForm(); |
||
245 | |||
246 | $orderByForm->handleRequest($request); |
||
247 | |||
248 | $Category = $searchForm->get('category_id')->getData(); |
||
249 | |||
250 | return [ |
||
251 | 'subtitle' => $this->getPageTitle($searchData), |
||
252 | 'pagination' => $pagination, |
||
253 | 'search_form' => $searchForm->createView(), |
||
254 | 'disp_number_form' => $dispNumberForm->createView(), |
||
255 | 'order_by_form' => $orderByForm->createView(), |
||
256 | 'forms' => $forms, |
||
257 | 'Category' => $Category, |
||
258 | 11 | ]; |
|
259 | } |
||
260 | 11 | ||
261 | /** |
||
262 | * 商品詳細画面. |
||
263 | * |
||
264 | 11 | * @Route("/products/detail/{id}", name="product_detail", methods={"GET"}, requirements={"id" = "\d+"}) |
|
265 | 11 | * @Template("Product/detail.twig") |
|
266 | 11 | * @ParamConverter("Product", options={"repository_method" = "findWithSortedClassCategories"}) |
|
267 | 11 | * |
|
268 | * @param Request $request |
||
269 | 11 | * @param Product $Product |
|
270 | * |
||
271 | * @return array |
||
272 | */ |
||
273 | public function detail(Request $request, Product $Product) |
||
274 | 11 | { |
|
275 | if (!$this->checkVisibility($Product)) { |
||
276 | 11 | throw new NotFoundHttpException(); |
|
277 | 11 | } |
|
278 | |||
279 | 11 | $builder = $this->formFactory->createNamedBuilder( |
|
280 | '', |
||
281 | 11 | AddCartType::class, |
|
282 | null, |
||
283 | 11 | [ |
|
284 | 11 | 'product' => $Product, |
|
285 | 2 | 'id_add_product_id' => false, |
|
286 | 2 | ] |
|
287 | ); |
||
288 | |||
289 | $event = new EventArgs( |
||
290 | 11 | [ |
|
291 | 11 | 'builder' => $builder, |
|
292 | 11 | 'Product' => $Product, |
|
293 | 11 | ], |
|
294 | 11 | $request |
|
295 | ); |
||
296 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event); |
||
297 | |||
298 | $is_favorite = false; |
||
299 | if ($this->isGranted('ROLE_USER')) { |
||
300 | $Customer = $this->getUser(); |
||
301 | $is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product); |
||
302 | } |
||
303 | 3 | ||
304 | return [ |
||
305 | 3 | 'title' => $this->title, |
|
306 | 'subtitle' => $Product->getName(), |
||
307 | 3 | 'form' => $builder->getForm()->createView(), |
|
308 | 'Product' => $Product, |
||
309 | 3 | 'is_favorite' => $is_favorite, |
|
310 | ]; |
||
311 | 3 | } |
|
312 | |||
313 | 3 | /** |
|
314 | * お気に入り追加. |
||
315 | 3 | * |
|
316 | 2 | * @Route("/products/add_favorite/{id}", name="product_add_favorite", requirements={"id" = "\d+"}) |
|
317 | 2 | */ |
|
318 | 2 | public function addFavorite(Request $request, Product $Product) |
|
319 | { |
||
320 | 2 | $this->checkVisibility($Product); |
|
321 | |||
322 | 2 | $event = new EventArgs( |
|
323 | [ |
||
324 | 2 | 'Product' => $Product, |
|
325 | ], |
||
326 | 2 | $request |
|
327 | ); |
||
328 | 2 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_INITIALIZE, $event); |
|
329 | |||
330 | if ($this->isGranted('ROLE_USER')) { |
||
331 | $Customer = $this->getUser(); |
||
332 | 1 | $this->customerFavoriteProductRepository->addFavorite($Customer, $Product); |
|
333 | 1 | $this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId()); |
|
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('product_detail', ['id' => $Product->getId()]); |
|
344 | } else { |
||
345 | // 非会員の場合、ログイン画面を表示 |
||
346 | // ログイン後の画面遷移先を設定 |
||
347 | $this->setLoginTargetPath($this->generateUrl('product_add_favorite', ['id' => $Product->getId()])); |
||
348 | $this->session->getFlashBag()->set('eccube.add.favorite', true); |
||
349 | |||
350 | $event = new EventArgs( |
||
351 | [ |
||
352 | 'Product' => $Product, |
||
353 | 37 | ], |
|
354 | $request |
||
355 | ); |
||
356 | 37 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event); |
|
357 | 37 | ||
358 | 1 | return $this->redirectToRoute('mypage_login'); |
|
359 | } |
||
360 | } |
||
361 | 36 | ||
362 | 36 | /** |
|
363 | 36 | * カートに追加. |
|
364 | 36 | * |
|
365 | * @Route("/products/add_cart/{id}", name="product_add_cart", methods={"POST"}, requirements={"id" = "\d+"}) |
||
366 | 36 | */ |
|
367 | public function addCart(Request $request, Product $Product) |
||
368 | { |
||
369 | // エラーメッセージの配列 |
||
370 | $errorMessages = []; |
||
371 | 36 | if (!$this->checkVisibility($Product)) { |
|
372 | throw new NotFoundHttpException(); |
||
373 | 36 | } |
|
374 | 36 | ||
375 | $builder = $this->formFactory->createNamedBuilder( |
||
376 | 36 | '', |
|
377 | AddCartType::class, |
||
378 | 36 | null, |
|
379 | [ |
||
380 | 'product' => $Product, |
||
381 | 36 | 'id_add_product_id' => false, |
|
382 | 36 | ] |
|
383 | ); |
||
384 | 36 | ||
385 | 1 | $event = new EventArgs( |
|
386 | [ |
||
387 | 'builder' => $builder, |
||
388 | 35 | 'Product' => $Product, |
|
389 | ], |
||
390 | 35 | $request |
|
391 | 35 | ); |
|
392 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event); |
||
393 | 35 | ||
394 | 35 | /* @var $form \Symfony\Component\Form\FormInterface */ |
|
395 | 35 | $form = $builder->getForm(); |
|
396 | $form->handleRequest($request); |
||
397 | |||
398 | if (!$form->isValid()) { |
||
399 | throw new NotFoundHttpException(); |
||
400 | 35 | } |
|
401 | |||
402 | $addCartData = $form->getData(); |
||
403 | 35 | ||
404 | 35 | log_info( |
|
405 | 35 | 'カート追加処理開始', |
|
406 | [ |
||
407 | 35 | 'product_id' => $Product->getId(), |
|
408 | 'product_class_id' => $addCartData['product_class_id'], |
||
409 | 'quantity' => $addCartData['quantity'], |
||
410 | ] |
||
411 | ); |
||
412 | |||
413 | 35 | // カートへ追加 |
|
414 | 35 | $this->cartService->addProduct($addCartData['product_class_id'], $addCartData['quantity']); |
|
415 | |||
416 | // 明細の正規化 |
||
417 | $Carts = $this->cartService->getCarts(); |
||
418 | 35 | View Code Duplication | foreach ($Carts as $Cart) { |
419 | $result = $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart, $this->getUser())); |
||
420 | 35 | // 復旧不可のエラーが発生した場合は追加した明細を削除. |
|
421 | 35 | if ($result->hasError()) { |
|
422 | $this->cartService->removeProduct($addCartData['product_class_id']); |
||
423 | 35 | foreach ($result->getErrors() as $error) { |
|
424 | 35 | $errorMessages[] = $error->getMessage(); |
|
425 | 35 | } |
|
426 | } |
||
427 | foreach ($result->getWarning() as $warning) { |
||
428 | $errorMessages[] = $warning->getMessage(); |
||
429 | 35 | } |
|
430 | } |
||
431 | 35 | ||
432 | 35 | $this->cartService->save(); |
|
433 | |||
434 | 35 | log_info( |
|
435 | 'カート追加処理完了', |
||
436 | 35 | [ |
|
437 | 'product_id' => $Product->getId(), |
||
438 | 35 | 'product_class_id' => $addCartData['product_class_id'], |
|
439 | 'quantity' => $addCartData['quantity'], |
||
440 | ] |
||
441 | ); |
||
442 | 35 | ||
443 | $event = new EventArgs( |
||
444 | [ |
||
445 | 'form' => $form, |
||
446 | 'Product' => $Product, |
||
447 | ], |
||
448 | $request |
||
449 | ); |
||
450 | $this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event); |
||
451 | |||
452 | if ($event->getResponse() !== null) { |
||
453 | return $event->getResponse(); |
||
454 | } |
||
455 | |||
456 | if ($request->isXmlHttpRequest()) { |
||
457 | // ajaxでのリクエストの場合は結果をjson形式で返す。 |
||
458 | |||
459 | // 初期化 |
||
460 | $done = null; |
||
0 ignored issues
–
show
|
|||
461 | $messages = []; |
||
462 | 35 | ||
463 | 5 | if (empty($errorMessages)) { |
|
464 | // エラーが発生していない場合 |
||
465 | $done = true; |
||
466 | 35 | array_push($messages, trans('front.product.add_cart_complete')); |
|
467 | } else { |
||
468 | // エラーが発生している場合 |
||
469 | $done = false; |
||
470 | $messages = $errorMessages; |
||
471 | } |
||
472 | |||
473 | return $this->json(['done' => $done, 'messages' => $messages]); |
||
474 | } else { |
||
475 | // ajax以外でのリクエストの場合はカート画面へリダイレクト |
||
476 | foreach ($errorMessages as $errorMessage) { |
||
477 | 3 | $this->addRequestError($errorMessage); |
|
478 | } |
||
479 | 3 | ||
480 | return $this->redirectToRoute('cart'); |
||
481 | 3 | } |
|
482 | 1 | } |
|
483 | |||
484 | 2 | /** |
|
485 | * ページタイトルの設定 |
||
486 | * |
||
487 | * @param null|array $searchData |
||
488 | * |
||
489 | * @return str |
||
490 | */ |
||
491 | private function getPageTitle($searchData) |
||
492 | { |
||
493 | if (isset($searchData['name']) && !empty($searchData['name'])) { |
||
494 | return trans('front.product.search_result'); |
||
495 | 43 | } elseif (isset($searchData['category_id']) && $searchData['category_id']) { |
|
496 | return $searchData['category_id']->getName(); |
||
497 | 43 | } else { |
|
498 | return trans('front.product.all_products'); |
||
499 | } |
||
500 | 43 | } |
|
501 | |||
502 | /** |
||
503 | * 閲覧可能な商品かどうかを判定 |
||
504 | * |
||
505 | * @param Product $Product |
||
506 | * |
||
507 | * @return boolean 閲覧可能な場合はtrue |
||
508 | 43 | */ |
|
509 | 1 | private function checkVisibility(Product $Product) |
|
510 | { |
||
511 | $is_admin = $this->session->has('_security_admin'); |
||
512 | |||
513 | 43 | // 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能. |
|
514 | if (!$is_admin) { |
||
515 | // 在庫なし商品の非表示オプションが有効な場合. |
||
516 | // if ($this->BaseInfo->isOptionNostockHidden()) { |
||
517 | // if (!$Product->getStockFind()) { |
||
518 | // return false; |
||
519 | // } |
||
520 | // } |
||
521 | // 公開ステータスでない商品は表示しない. |
||
522 | if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) { |
||
523 | return false; |
||
524 | } |
||
525 | } |
||
526 | |||
527 | return true; |
||
528 | } |
||
529 | } |
||
530 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
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.