Completed
Push — 4.0 ( b48f64...137622 )
by chihiro
20:21 queued 10s
created

src/Eccube/Controller/CartController.php (1 issue)

Upgrade to new PHP Analysis Engine

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\ProductClass;
18
use Eccube\Event\EccubeEvents;
19
use Eccube\Event\EventArgs;
20
use Eccube\Repository\BaseInfoRepository;
21
use Eccube\Repository\ProductClassRepository;
22
use Eccube\Service\CartService;
23
use Eccube\Service\PurchaseFlow\PurchaseContext;
24
use Eccube\Service\PurchaseFlow\PurchaseFlow;
25
use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
26
use Eccube\Service\OrderHelper;
27
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
28
use Symfony\Component\HttpFoundation\Request;
29
use Symfony\Component\Routing\Annotation\Route;
30
31
class CartController extends AbstractController
32
{
33
    /**
34
     * @var ProductClassRepository
35
     */
36
    protected $productClassRepository;
37
38
    /**
39
     * @var CartService
40
     */
41
    protected $cartService;
42
43
    /**
44
     * @var PurchaseFlow
45
     */
46
    protected $purchaseFlow;
47
48
    /**
49
     * @var BaseInfo
50
     */
51
    protected $baseInfo;
52
53
    /**
54
     * CartController constructor.
55
     *
56
     * @param ProductClassRepository $productClassRepository
57
     * @param CartService $cartService
58
     * @param PurchaseFlow $cartPurchaseFlow
59
     * @param BaseInfoRepository $baseInfoRepository
60
     */
61 View Code Duplication
    public function __construct(
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
62 77
        ProductClassRepository $productClassRepository,
63
        CartService $cartService,
64
        PurchaseFlow $cartPurchaseFlow,
65
        BaseInfoRepository $baseInfoRepository
66
    ) {
67
        $this->productClassRepository = $productClassRepository;
68 77
        $this->cartService = $cartService;
69 77
        $this->purchaseFlow = $cartPurchaseFlow;
70 77
        $this->baseInfo = $baseInfoRepository->get();
71 77
    }
72
73
    /**
74
     * カート画面.
75
     *
76
     * @Route("/cart", name="cart")
77
     * @Template("Cart/index.twig")
78
     */
79
    public function index(Request $request)
80 36
    {
81
        // カートを取得して明細の正規化を実行
82
        $Carts = $this->cartService->getCarts();
83 36
        $this->execPurchaseFlow($Carts);
84 36
85
        // TODO itemHolderから取得できるように
86
        $least = [];
87 36
        $quantity = [];
88 36
        $isDeliveryFree = [];
89 36
        $totalPrice = 0;
90 36
        $totalQuantity = 0;
91 36
92
        foreach ($Carts as $Cart) {
93 36
            $quantity[$Cart->getCartKey()] = 0;
94 35
            $isDeliveryFree[$Cart->getCartKey()] = false;
95 35
96
            if ($this->baseInfo->getDeliveryFreeQuantity()) {
97 35
                if ($this->baseInfo->getDeliveryFreeQuantity() > $Cart->getQuantity()) {
98
                    $quantity[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeQuantity() - $Cart->getQuantity();
99
                } else {
100
                    $isDeliveryFree[$Cart->getCartKey()] = true;
101
                }
102
            }
103
104
            if ($this->baseInfo->getDeliveryFreeAmount()) {
105 35
                if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $Cart->getTotalPrice()) {
106
                    $isDeliveryFree[$Cart->getCartKey()] = true;
107
                } else {
108
                    $least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $Cart->getTotalPrice();
109
                }
110
            }
111
112
            $totalPrice += $Cart->getTotalPrice();
113 35
            $totalQuantity += $Cart->getQuantity();
114 35
        }
115
116
        // カートが分割された時のセッション情報を削除
117
        $request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
118 36
119
        return [
120
            'totalPrice' => $totalPrice,
121 36
            'totalQuantity' => $totalQuantity,
122 36
            // 空のカートを削除し取得し直す
123 36
            'Carts' => $this->cartService->getCarts(true),
124 36
            'least' => $least,
125 36
            'quantity' => $quantity,
126 36
            'is_delivery_free' => $isDeliveryFree,
127
        ];
128
    }
129
130
    /**
131
     * @param $Carts
132
     *
133
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
134
     */
135
    protected function execPurchaseFlow($Carts)
136
    {
137
        /** @var PurchaseFlowResult[] $flowResults */
138 77
        $flowResults = array_map(function ($Cart) {
139 75
            $purchaseContext = new PurchaseContext($Cart, $this->getUser());
140
141 75
            return $this->purchaseFlow->validate($Cart, $purchaseContext);
142 77
        }, $Carts);
143
144
        // 復旧不可のエラーが発生した場合はカートをクリアして再描画
145 77
        $hasError = false;
146 77
        foreach ($flowResults as $result) {
147 75
            if ($result->hasError()) {
148 1
                $hasError = true;
149 1
                foreach ($result->getErrors() as $error) {
150 75
                    $this->addRequestError($error->getMessage());
151
                }
152
            }
153
        }
154 77
        if ($hasError) {
155 1
            $this->cartService->clear();
156
157 1
            return $this->redirectToRoute('cart');
158
        }
159
160 76
        $this->cartService->save();
161
162 76
        foreach ($flowResults as $index => $result) {
163 74
            foreach ($result->getWarning() as $warning) {
164 74
                if ($Carts[$index]->getItems()->count() > 0) {
165
                    $cart_key = $Carts[$index]->getCartKey();
166
                    $this->addRequestError($warning->getMessage(), "front.cart.${cart_key}");
167
                } else {
168
                    // キーが存在しない場合はグローバルにエラーを表示する
169
                    $this->addRequestError($warning->getMessage());
170
                }
171
            }
172
        }
173
    }
174
175
    /**
176
     * カート明細の加算/減算/削除を行う.
177
     *
178
     * - 加算
179
     *      - 明細の個数を1増やす
180
     * - 減算
181
     *      - 明細の個数を1減らす
182
     *      - 個数が0になる場合は、明細を削除する
183
     * - 削除
184
     *      - 明細を削除する
185
     *
186
     * @Route(
187
     *     path="/cart/{operation}/{productClassId}",
188
     *     name="cart_handle_item",
189
     *     methods={"PUT"},
190
     *     requirements={
191
     *          "operation": "up|down|remove",
192 51
     *          "productClassId": "\d+"
193
     *     }
194 51
     * )
195
     */
196
    public function handleCartItem($operation, $productClassId)
197 51
    {
198
        log_info('カート明細操作開始', ['operation' => $operation, 'product_class_id' => $productClassId]);
199 51
200
        $this->isTokenValid();
201
202
        /** @var ProductClass $ProductClass */
203
        $ProductClass = $this->productClassRepository->find($productClassId);
204
205
        if (is_null($ProductClass)) {
206 51
            log_info('商品が存在しないため、カート画面へredirect', ['operation' => $operation, 'product_class_id' => $productClassId]);
207
208 44
            return $this->redirectToRoute('cart');
209 44
        }
210
211 6
        // 明細の増減・削除
212 6
        switch ($operation) {
213
            case 'up':
214 1
                $this->cartService->addProduct($ProductClass, 1);
215 1
                break;
216
            case 'down':
217
                $this->cartService->addProduct($ProductClass, -1);
218
                break;
219 51
            case 'remove':
220 51
                $this->cartService->removeProduct($ProductClass);
221
                break;
222 51
        }
223
224 51
        // カートを取得して明細の正規化を実行
225
        $Carts = $this->cartService->getCarts();
226
        $this->execPurchaseFlow($Carts);
227
228
        log_info('カート演算処理終了', ['operation' => $operation, 'product_class_id' => $productClassId]);
229
230
        return $this->redirectToRoute('cart');
231
    }
232
233
    /**
234 53
     * カートをロック状態に設定し、購入確認画面へ遷移する.
235 53
     *
236
     * @Route("/cart/buystep/{cart_key}", name="cart_buystep", requirements={"cart_key" = "[a-zA-Z0-9]+[_][\x20-\x7E]+"})
237
     */
238
    public function buystep(Request $request, $cart_key)
239 53
    {
240 53
        $Carts = $this->cartService->getCart();
241 53
        if (!is_object($Carts)) {
242
            return $this->redirectToRoute('cart');
243 53
        }
244
        // FRONT_CART_BUYSTEP_INITIALIZE
245 53
        $event = new EventArgs(
246 53
            [],
247
            $request
248
        );
249 53
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE, $event);
250 53
251 53
        $this->cartService->setPrimary($cart_key);
252
        $this->cartService->save();
253 53
254
        // FRONT_CART_BUYSTEP_COMPLETE
255 53
        $event = new EventArgs(
256
            [],
257
            $request
258
        );
259 53
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_CART_BUYSTEP_COMPLETE, $event);
260
261
        if ($event->hasResponse()) {
262
            return $event->getResponse();
263
        }
264
265
        return $this->redirectToRoute('shopping');
266
    }
267
}
268