Failed Conditions
Pull Request — 4.0 (#3650)
by chihiro
06:14
created

ShoppingController::shipping()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 64

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 48.2971

Importance

Changes 0
Metric Value
cc 8
nc 6
nop 2
dl 0
loc 64
ccs 4
cts 28
cp 0.1429
crap 48.2971
rs 7.541
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\CustomerAddress;
17
use Eccube\Entity\Order;
18
use Eccube\Entity\Shipping;
19
use Eccube\Event\EccubeEvents;
20
use Eccube\Event\EventArgs;
21
use Eccube\Exception\ShoppingException;
22
use Eccube\Form\Type\Front\CustomerLoginType;
23
use Eccube\Form\Type\Front\ShoppingShippingType;
24
use Eccube\Form\Type\Shopping\CustomerAddressType;
25
use Eccube\Form\Type\Shopping\OrderType;
26
use Eccube\Repository\OrderRepository;
27
use Eccube\Service\CartService;
28
use Eccube\Service\MailService;
29
use Eccube\Service\OrderHelper;
30
use Eccube\Service\Payment\PaymentDispatcher;
31
use Eccube\Service\Payment\PaymentMethodInterface;
32
use Eccube\Service\PurchaseFlow\PurchaseContext;
33
use Eccube\Service\PurchaseFlow\PurchaseFlow;
34
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
35
use Symfony\Component\Form\FormInterface;
36
use Symfony\Component\HttpFoundation\Request;
37
use Symfony\Component\Routing\Annotation\Route;
38
use Symfony\Component\Routing\RouterInterface;
39
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
40
41
class ShoppingController extends AbstractShoppingController
42
{
43
    /**
44
     * @var CartService
45
     */
46
    protected $cartService;
47
48
    /**
49
     * @var MailService
50
     */
51
    protected $mailService;
52
53
    /**
54
     * @var OrderHelper
55
     */
56
    protected $orderHelper;
57
58
    /**
59
     * @var OrderRepository
60
     */
61
    protected $orderRepository;
62
63
    public function __construct(
64
        CartService $cartService,
65
        MailService $mailService,
66
        OrderRepository $orderRepository,
67
        OrderHelper $orderHelper
68
    ) {
69
        $this->cartService = $cartService;
70
        $this->mailService = $mailService;
71
        $this->orderRepository = $orderRepository;
72
        $this->orderHelper = $orderHelper;
73
    }
74
75
    /**
76
     * 注文手続き画面を表示する
77
     *
78
     * 未ログインまたはRememberMeログインの場合はログイン画面に遷移させる.
79
     * ただし、非会員でお客様情報を入力済の場合は遷移させない.
80
     *
81
     * カート情報から受注データを生成し, `pre_order_id`でカートと受注の紐付けを行う.
82
     * 既に受注が生成されている場合(pre_order_idで取得できる場合)は, 受注の生成を行わずに画面を表示する.
83
     *
84
     * purchaseFlowの集計処理実行後, warning/errorがあればカートに戻す.
85
     *
86
     * @Route("/shopping", name="shopping")
87
     * @Template("Shopping/index.twig")
88
     */
89
    public function index()
90
    {
91 59
        // ログイン状態のチェック.
92
        if ($this->orderHelper->isLoginRequired()) {
93
            log_info('[注文手続] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
94
95
            return $this->redirectToRoute('shopping_login');
96
        }
97
98
        // カートチェック.
99
        $Cart = $this->cartService->getCart();
100 59
        if (!$this->orderHelper->verifyCart($Cart)) {
101 59
            log_info('[注文手続] カートが購入フローへ遷移できない状態のため, カート画面に遷移します.');
102 59
103 59
            return $this->redirectToRoute('cart');
104 59
        }
105 59
106 59
        // 受注の初期化.
107
        log_info('[注文手続] 受注の初期化処理を開始します.');
108
        $Customer = $this->getUser() ? $this->getUser() : $this->orderHelper->getNonMember();
109
        $Order = $this->orderHelper->initializeOrder($Cart, $Customer);
0 ignored issues
show
Bug introduced by
It seems like $Cart defined by $this->cartService->getCart() on line 99 can be null; however, Eccube\Service\OrderHelper::initializeOrder() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
110
111
        // 集計処理.
112
        log_info('[注文手続] 集計処理を開始します.', [$Order->getId()]);
113
        $flowResult = $this->validatePurchaseFlow($Order);
114
        $this->entityManager->flush();
115 51
116 View Code Duplication
        if ($flowResult->hasWarning() || $flowResult->hasError()) {
117
            log_info('[注文手続] WarningもしくはErrorが発生したためカート画面へ遷移します.',
118 51
                [$flowResult->getWarning(), $flowResult->getErrors()]);
119 51
120 1
            return $this->redirectToRoute('cart');
121
        }
122
123
        $form = $this->createForm(OrderType::class, $Order);
124 50
125 50
        return [
126
            'form' => $form->createView(),
127
            'Order' => $Order,
128
        ];
129
    }
130 50
131
    /**
132
     * 他画面への遷移を行う.
133 50
     *
134
     * お届け先編集画面など, 他画面へ遷移する際に, フォームの値をDBに保存してからリダイレクトさせる.
135
     * フォームの`redirect_to`パラメータの値にリダイレクトを行う.
136 50
     * `redirect_to`パラメータはpath('遷移先のルーティング')が渡される必要がある.
137
     *
138
     * 外部のURLやPathを渡された場合($router->matchで展開出来ない場合)は, 購入エラーとする.
139 50
     *
140
     * プラグインやカスタマイズでこの機能を使う場合は, twig側で以下のように記述してください.
141 50
     *
142 10
     * <button class="redirect-onclick" data-path="path('ルーティング')">更新する</button>
143
     *
144
     * redirect-*は, 以下を使用できます.
145 45
     *
146
     * - redirect-onclick
147
     * - redirect-onchange
148 45
     * - redirect-onblur
149 45
     *
150
     * data-pathは任意のパラメータです. デフォルトでは注文手続き画面へリダイレクトします.
151
     *
152
     * @Route("/shopping/redirect_to", name="shopping_redirect_to", methods={"POST"})
153
     * @Template("Shopping/index.twig")
154
     */
155
    public function redirectTo(Request $request, RouterInterface $router)
156
    {
157
        // ログイン状態のチェック.
158
        if ($this->orderHelper->isLoginRequired()) {
159
            log_info('[リダイレクト] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
160 20
161
            return $this->redirectToRoute('shopping_login');
162
        }
163 20
164 20
        // 受注の存在チェック.
165
        $preOrderId = $this->cartService->getPreOrderId();
166
        $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
167
        if (!$Order) {
168
            log_info('[リダイレクト] 購入処理中の受注が存在しません.');
169 20
170 20
            return $this->redirectToRoute('shopping_error');
171
        }
172
173
        $form = $this->createForm(OrderType::class, $Order);
174
        $form->handleRequest($request);
175 20
176 20
        if ($form->isSubmitted() && $form->isValid()) {
177 20
            log_info('[リダイレクト] 集計処理を開始します.', [$Order->getId()]);
178
            $flowResult = $this->validatePurchaseFlow($Order);
179
            $this->entityManager->flush();
180 20
181 20 View Code Duplication
            if ($flowResult->hasWarning() || $flowResult->hasError()) {
182 8
                log_info('[リダイレクト] WarningもしくはErrorが発生したためカート画面へ遷移します.',
183
                    [$flowResult->getWarning(), $flowResult->getErrors()]);
184 12
185 12
                return $this->redirectToRoute('shopping_error');
186
            }
187
188 12
            $redirectTo = $form['redirect_to']->getData();
189 12
            if (empty($redirectTo)) {
190
                log_info('[リダイレクト] リダイレクト先未指定のため注文手続き画面へ遷移します.');
191
192
                return $this->redirectToRoute('shopping');
193
            }
194
195
            try {
196
                // リダイレクト先のチェック.
197
                $result = $router->match($redirectTo);
198
                // パラメータのみ抽出
199
                $params = array_filter($result, function ($key) {
200 5
                    return 0 !== \strpos($key, '_');
201
                }, ARRAY_FILTER_USE_KEY);
202
203 5
                log_info('[リダイレクト] リダイレクトを実行します.', [$result['_route'], $params]);
204 5
205
                // pathからurlを再構築してリダイレクト.
206
                return $this->redirectToRoute($result['_route'], $params);
207
            } catch (\Exception $e) {
208
                log_info('[リダイレクト] URLの形式が不正です', [$redirectTo, $e->getMessage()]);
209 5
210 5
                return $this->redirectToRoute('shopping_error');
211
            }
212
        }
213
214
        log_info('[リダイレクト] フォームエラーのため, 注文手続き画面を表示します.', [$Order->getId()]);
215 5
216 5
        return [
217 5
            'form' => $form->createView(),
218
            'Order' => $Order,
219 5
        ];
220 5
    }
221
222 5
    /**
223 5
     * 注文確認画面を表示する.
224
     *
225
     * ここではPaymentMethod::verifyがコールされます.
226
     * PaymentMethod::verifyではクレジットカードの有効性チェック等, 注文手続きを進められるかどうかのチェック処理を行う事を想定しています.
227 5
     * PaymentMethod::verifyでエラーが発生した場合は, 注文手続き画面へリダイレクトします.
228
     *
229 5
     * @Route("/shopping/confirm", name="shopping_confirm", methods={"POST"})
230
     * @Template("Shopping/confirm.twig")
231 5
     */
232
    public function confirm(Request $request)
233
    {
234
        // ログイン状態のチェック.
235
        if ($this->orderHelper->isLoginRequired()) {
236
            log_info('[注文確認] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
237
238
            return $this->redirectToRoute('shopping_login');
239
        }
240
241
        // 受注の存在チェック
242
        $preOrderId = $this->cartService->getPreOrderId();
243
        $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
244
        if (!$Order) {
245 5
            log_info('[注文確認] 購入処理中の受注が存在しません.', [$preOrderId]);
246
247
            return $this->redirectToRoute('shopping_error');
248 5
        }
249 5
250
        $form = $this->createForm(OrderType::class, $Order);
251
        $form->handleRequest($request);
252
253
        if ($form->isSubmitted() && $form->isValid()) {
254
            log_info('[注文確認] 集計処理を開始します.', [$Order->getId()]);
255
            $flowResult = $this->validatePurchaseFlow($Order);
256
            $this->entityManager->flush();
257
258 View Code Duplication
            if ($flowResult->hasWarning() || $flowResult->hasError()) {
259
                log_info('[注文確認] WarningもしくはErrorが発生したためカート画面へ遷移します.',
260 6
                    [$flowResult->getWarning(), $flowResult->getErrors()]);
261
262
                return $this->redirectToRoute('shopping_error');
263 6
            }
264 6
265
            log_info('[注文確認] PaymentMethod::verifyを実行します.', [$Order->getPayment()->getMethodClass()]);
266
            $paymentMethod = $this->createPaymentMethod($Order, $form);
267
            $PaymentResult = $paymentMethod->verify();
268
269 6
            if ($PaymentResult) {
270 6 View Code Duplication
                if (!$PaymentResult->isSuccess()) {
271
                    $this->entityManager->rollback();
272
                    foreach ($PaymentResult->getErrors() as $error) {
273
                        $this->addError($error);
274
                    }
275
276 6
                    log_info('[注文確認] PaymentMethod::verifyのエラーのため, 注文手続き画面へ遷移します.', [$PaymentResult->getErrors()]);
277
278 6
                    return $this->redirectToRoute('shopping');
279 6
                }
280 6
281
                $response = $PaymentResult->getResponse();
282 6
                if ($response && ($response->isRedirection() || $response->getContent())) {
283 6
                    $this->entityManager->flush();
284
285
                    log_info('[注文確認] PaymentMethod::verifyが指定したレスポンスを表示します.');
286 6
287 6
                    return $response;
288 6
                }
289
            }
290
291
            $this->entityManager->flush();
292
293
            log_info('[注文確認] 注文確認画面を表示します.');
294
295
            return [
296
                'form' => $form->createView(),
297
                'Order' => $Order,
298
            ];
299
        }
300
301
        log_info('[注文確認] フォームエラーのため, 注文手続画面を表示します.', [$Order->getId()]);
302
303
        // FIXME @Templateの差し替え.
304
        $request->attributes->set('_template', new Template(['template' => 'shopping/index.twig']));
305
306
        return [
307
            'form' => $form->createView(),
308
            'Order' => $Order,
309
        ];
310
    }
311
312
    /**
313
     * 注文処理を行う.
314
     *
315
     * 決済プラグインによる決済処理および注文の確定処理を行います.
316
     *
317
     * @Route("/shopping/checkout", name="shopping_checkout", methods={"POST"})
318
     * @Template("Shopping/confirm.twig")
319
     */
320
    public function checkout(Request $request)
321
    {
322
        // ログイン状態のチェック.
323
        if ($this->orderHelper->isLoginRequired()) {
324
            log_info('[注文処理] 未ログインもしくはRememberMeログインのため, ログイン画面に遷移します.');
325
326
            return $this->redirectToRoute('shopping_login');
327
        }
328
329
        // 受注の存在チェック
330
        $preOrderId = $this->cartService->getPreOrderId();
331
        $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
332
        if (!$Order) {
333
            log_info('[注文処理] 購入処理中の受注が存在しません.', [$preOrderId]);
334 1
335
            return $this->redirectToRoute('shopping_error');
336
        }
337 1
338
        // フォームの生成.
339 1
        $form = $this->createForm(OrderType::class, $Order);
340
        $form->handleRequest($request);
341
342
        if ($form->isSubmitted() && $form->isValid()) {
343 1
            log_info('[注文処理] 注文処理を開始します.', [$Order->getId()]);
344
345 1
            try {
346
                /*
347 1
                 * 集計処理
348
                 */
349 1
                log_info('[注文処理] 集計処理を開始します.', [$Order->getId()]);
350
                $flowResult = $this->validatePurchaseFlow($Order);
351 1
                $this->entityManager->flush();
352
353 1 View Code Duplication
                if ($flowResult->hasWarning() || $flowResult->hasError()) {
354
                    log_info('[注文処理] WarningもしくはErrorが発生したためカート画面へ遷移します.', [$flowResult->getWarning(), $flowResult->getErrors()]);
355
356
                    return $this->redirectToRoute('shopping_error');
357
                }
358 1
359 1
                /*
360 1
                 * 決済実行(前処理)
361
                 */
362 1
                log_info('[注文処理] PaymentMethod::applyを実行します.', [$Order->getPayment()->getMethodClass()]);
363
                $paymentMethod = $this->createPaymentMethod($Order, $form);
364 1
                $dispatcher = $paymentMethod->apply(); // 決済処理中.
365
366
                // リンク式決済のように他のサイトへ遷移する場合などは, dispatcherに処理を移譲する.
367 1
                if ($dispatcher instanceof PaymentDispatcher) {
368 1
                    $response = $dispatcher->getResponse();
369
                    $this->entityManager->flush();
370
371
                    // dispatcherがresponseを保持している場合はresponseを返す
372
                    if ($response && ($response->isRedirection() || $response->getContent())) {
373
                        log_info('[注文処理] PaymentMethod::applyが指定したレスポンスを表示します.');
374
375
                        return $response;
376
                    }
377
378
                    // forwardすることも可能.
379
                    if ($dispatcher->isForward()) {
380
                        log_info('[注文処理] PaymentMethod::applyによりForwardします.', [$dispatcher->getRoute(), $dispatcher->getPathParameters(), $dispatcher->getQueryParameters(),]);
381
382
                        return $this->forwardToRoute($dispatcher->getRoute(), $dispatcher->getPathParameters(), $dispatcher->getQueryParameters());
383
                    } else {
384
                        log_info('[注文処理] PaymentMethod::applyによりリダイレクトします.', [$dispatcher->getRoute(), $dispatcher->getPathParameters(), $dispatcher->getQueryParameters(),]);
385
386
                        return $this->redirectToRoute($dispatcher->getRoute(), array_merge($dispatcher->getPathParameters(), $dispatcher->getQueryParameters()));
387
                    }
388
                }
389
390
                /*
391
                 * 決済実行
392
                 *
393
                 * PaymentMethod::checkoutでは決済処理が行われ, 正常に処理出来た場合はPurchaseFlow::commitがコールされます.
394
                 */
395
                log_info('[注文処理] PaymentMethod::checkoutを実行します.', [$Order->getPayment()->getMethodClass()]);
396
                $PaymentResult = $paymentMethod->checkout();
397
                $response = $PaymentResult->getResponse();
398
                // PaymentResultがresponseを保持している場合はresponseを返す
399
                if ($response && ($response->isRedirection() || $response->getContent())) {
400
                    log_info('[注文処理] PaymentMethod::checkoutが指定したレスポンスを表示します.');
401
402
                    return $response;
403
                }
404
405
                // エラー時はロールバックして購入エラーとする.
406 View Code Duplication
                if (!$PaymentResult->isSuccess()) {
407
                    $this->entityManager->rollback();
408
                    foreach ($PaymentResult->getErrors() as $error) {
409
                        $this->addError($error);
410
                    }
411
412
                    log_info('[注文処理] PaymentMethod::checkoutのエラーのため, 購入エラー画面へ遷移します.', [$PaymentResult->getErrors()]);
413
414
                    return $this->redirectToRoute('shopping_error');
415
                }
416
417
                $this->entityManager->flush();
418
419
                log_info('[注文処理] 注文処理が完了しました.', [$Order->getId()]);
420
            } catch (ShoppingException $e) {
421
                log_error('[注文処理] 購入エラーが発生しました.', [$e->getMessage()]);
422
423
                $this->entityManager->rollback();
424
425
                $this->addError($e->getMessage());
426
427
                return $this->redirectToRoute('shopping_error');
428
            } catch (\Exception $e) {
429
                log_error('[注文確認] 予期しないエラーが発生しました.', [$e->getMessage()]);
430
431
                $this->entityManager->rollback();
432
433
                $this->addError('front.shopping.system_error');
434
435
                return $this->redirectToRoute('shopping_error');
436
            }
437
438
            // カート削除
439
            log_info('[注文処理] カートをクリアします.', [$Order->getId()]);
440
            $this->cartService->clear();
441
442
            // 受注IDをセッションにセット
443
            $this->session->set(OrderHelper::SESSION_ORDER_ID, $Order->getId());
444
445
            // メール送信
446
            log_info('[注文処理] 注文メールの送信を行います.', [$Order->getId()]);
447
            $this->mailService->sendOrderMail($Order);
448
449
            log_info('[注文処理] 注文処理が完了しました. 購入完了画面へ遷移します.', [$Order->getId()]);
450
451
            return $this->redirectToRoute('shopping_complete');
452
        }
453
454
        log_info('[注文処理] フォームエラーのため, 購入エラー画面へ遷移します.', [$Order->getId()]);
455
456
        return $this->redirectToRoute('shopping_error');
457
    }
458
459
    /**
460
     * 購入完了画面を表示する.
461
     *
462
     * @Route("/shopping/complete", name="shopping_complete")
463
     * @Template("Shopping/complete.twig")
464
     */
465
    public function complete(Request $request)
466
    {
467
        log_info('[注文完了] 注文完了画面を表示します.');
468
469
        // 受注IDを取得
470
        $orderId = $this->session->get(OrderHelper::SESSION_ORDER_ID);
471
472
        if (empty($orderId)) {
473
            log_info('[注文完了] 受注IDを取得できないため, トップページへ遷移します.');
474
475
            return $this->redirectToRoute('homepage');
476
        }
477
478
        $Order = $this->orderRepository->find($orderId);
479
480
        $event = new EventArgs(
481
            [
482
                'Order' => $Order,
483
            ],
484
            $request
485
        );
486
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_COMPLETE_INITIALIZE, $event);
487
488
        if ($event->getResponse() !== null) {
489
            return $event->getResponse();
490
        }
491
492
        log_info('[注文完了] 購入フローのセッションをクリアします. ');
493
        $this->orderHelper->removeSession();
494
495
        $hasNextCart = !empty($this->cartService->getCarts());
496
497
        log_info('[注文完了] 注文完了画面を表示しました. ', [$hasNextCart]);
498
499
        return [
500
            'Order' => $Order,
501
            'hasNextCart' => $hasNextCart,
502
        ];
503
    }
504
505
    /**
506
     * お届け先選択画面.
507
     *
508
     * 会員ログイン時, お届け先を選択する画面を表示する
509
     * 非会員の場合はこの画面は使用しない。
510
     *
511
     * @Route("/shopping/shipping/{id}", name="shopping_shipping", requirements={"id" = "\d+"})
512
     * @Template("Shopping/shipping.twig")
513
     */
514
    public function shipping(Request $request, Shipping $Shipping)
515
    {
516
        // ログイン状態のチェック.
517
        if ($this->orderHelper->isLoginRequired()) {
518
            return $this->redirectToRoute('shopping_login');
519
        }
520
521
        // 受注の存在チェック
522
        $preOrderId = $this->cartService->getPreOrderId();
523
        $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
524
        if (!$Order) {
525
            return $this->redirectToRoute('shopping_error');
526
        }
527
528
        // 受注に紐づくShippingかどうかのチェック.
529
        if (!$Order->findShipping($Shipping->getId())) {
530
            return $this->redirectToRoute('shopping_error');
531
        }
532
533
        $builder = $this->formFactory->createBuilder(CustomerAddressType::class, null, [
534
            'customer' => $this->getUser(),
535
            'shipping' => $Shipping,
536
        ]);
537
538
        $form = $builder->getForm();
539
        $form->handleRequest($request);
540
541
        if ($form->isSubmitted() && $form->isValid()) {
542
            log_info('お届先情報更新開始', [$Shipping->getId()]);
543
544
            /** @var CustomerAddress $CustomerAddress */
545
            $CustomerAddress = $form['addresses']->getData();
546
547
            // お届け先情報を更新
548
            $Shipping->setFromCustomerAddress($CustomerAddress);
549
550
            // 合計金額の再計算
551
            $flowResult = $this->validatePurchaseFlow($Order);
552
            $this->entityManager->flush();
553
554
            if ($flowResult->hasWarning() || $flowResult->hasError()) {
555
                return $this->redirectToRoute('shopping_error');
556
            }
557
558
            $event = new EventArgs(
559
                [
560
                    'Order' => $Order,
561
                    'Shipping' => $Shipping,
562
                ],
563
                $request
564
            );
565
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_SHIPPING_COMPLETE, $event);
566
567
            log_info('お届先情報更新完了', [$Shipping->getId()]);
568 2
569
            return $this->redirectToRoute('shopping');
570 2
        }
571
572
        return [
573
            'form' => $form->createView(),
574
            'Customer' => $this->getUser(),
575 2
            'shippingId' => $Shipping->getId(),
576
        ];
577 2
    }
578
579
    /**
580
     * お届け先の新規作成または編集画面.
581
     *
582
     * 会員時は新しいお届け先を作成する.
583
     * 非会員時は選択されたお届け先の編集を行う.
584 2
     *
585
     * @Route("/shopping/shipping_edit/{id}", name="shopping_shipping_edit", requirements={"id" = "\d+"})
586 2
     * @Template("Shopping/shipping_edit.twig")
587
     */
588 2
    public function shippingEdit(Request $request, Shipping $Shipping)
589
    {
590 2
        // ログイン状態のチェック.
591
        if ($this->orderHelper->isLoginRequired()) {
592 2
            return $this->redirectToRoute('shopping_login');
593
        }
594
595 2
        // 受注の存在チェック
596 2
        $preOrderId = $this->cartService->getPreOrderId();
597
        $Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
598
        if (!$Order) {
599
            return $this->redirectToRoute('shopping_error');
600
        }
601
602
        // 受注に紐づくShippingかどうかのチェック.
603
        if (!$Order->findShipping($Shipping->getId())) {
604
            return $this->redirectToRoute('shopping_error');
605
        }
606 1
607
        $CustomerAddress = new CustomerAddress();
608 1
        if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
609 1
            // ログイン時は会員と紐付け
610 1
            $CustomerAddress->setCustomer($this->getUser());
611
        } else {
612 1
            // 非会員時はお届け先をセット
613
            $CustomerAddress->setFromShipping($Shipping);
614 1
        }
615
        $builder = $this->formFactory->createBuilder(ShoppingShippingType::class, $CustomerAddress);
616
617
        $event = new EventArgs(
618 1
            [
619
                'builder' => $builder,
620
                'Order' => $Order,
621
                'Shipping' => $Shipping,
622
                'CustomerAddress' => $CustomerAddress,
623
            ],
624
            $request
625
        );
626
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_SHIPPING_EDIT_INITIALIZE, $event);
627 55
628
        $form = $builder->getForm();
629 55
        $form->handleRequest($request);
630 55
631 53
        if ($form->isSubmitted() && $form->isValid()) {
632 53
            log_info('お届け先追加処理開始', ['order_id' => $Order->getId(), 'shipping_id' => $Shipping->getId()]);
633
634
            $Shipping->setFromCustomerAddress($CustomerAddress);
635
636
            if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
637
                $this->entityManager->persist($CustomerAddress);
638 53
            }
639
640 2
            // 合計金額の再計算
641
            $flowResult = $this->validatePurchaseFlow($Order);
642
            $this->entityManager->flush();
643 2
            if ($flowResult->hasWarning() || $flowResult->hasError()) {
644
                return $this->redirectToRoute('shopping_error');
645
            }
646
647
            $event = new EventArgs(
648
                [
649
                    'form' => $form,
650
                    'Shipping' => $Shipping,
651
                    'CustomerAddress' => $CustomerAddress,
652 50
                ],
653
                $request
654
            );
655 50
            $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_SHIPPING_EDIT_COMPLETE, $event);
656
657
            log_info('お届け先追加処理完了', ['order_id' => $Order->getId(), 'shipping_id' => $Shipping->getId()]);
658 50
659
            return $this->redirectToRoute('shopping');
660 34
        }
661
662
        return [
663
            'form' => $form->createView(),
664
            'shippingId' => $Shipping->getId(),
665
        ];
666
    }
667
668
    /**
669
     * ログイン画面.
670 34
     *
671
     * @Route("/shopping/login", name="shopping_login")
672
     * @Template("Shopping/login.twig")
673
     */
674
    public function login(Request $request, AuthenticationUtils $authenticationUtils)
675
    {
676 34
        if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
677 34
            return $this->redirectToRoute('shopping');
678 34
        }
679
680 34
        /* @var $form \Symfony\Component\Form\FormInterface */
681 34
        $builder = $this->formFactory->createNamedBuilder('', CustomerLoginType::class);
682
683
        if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
684
            $Customer = $this->getUser();
685
            if ($Customer) {
686
                $builder->get('login_email')->setData($Customer->getEmail());
687
            }
688
        }
689
690 34
        $event = new EventArgs(
691
            [
692
                'builder' => $builder,
693
            ],
694 50
            $request
695
        );
696 50
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_LOGIN_INITIALIZE, $event);
697
698 50
        $form = $builder->getForm();
699
700
        return [
701
            'error' => $authenticationUtils->getLastAuthenticationError(),
702
            'form' => $form->createView(),
703
        ];
704
    }
705
706
    /**
707 50
     * 購入エラー画面.
708
     *
709 50
     * @Route("/shopping/error", name="shopping_error")
710
     * @Template("Shopping/shopping_error.twig")
711 50
     */
712
    public function error(Request $request, PurchaseFlow $cartPurchaseFlow)
713 50
    {
714
        // 受注とカートのずれを合わせるため, カートのPurchaseFlowをコールする.
715 50
        $Cart = $this->cartService->getCart();
716 50
        if (null !== $Cart) {
717
            $cartPurchaseFlow->validate($Cart, new PurchaseContext());
718 50
            $this->cartService->save();
719
        }
720 50
721
        $event = new EventArgs(
722 50
            [],
723
            $request
724 50
        );
725
        $this->eventDispatcher->dispatch(EccubeEvents::FRONT_SHOPPING_SHIPPING_ERROR_COMPLETE, $event);
726 50
727
        if ($event->getResponse() !== null) {
728
            return $event->getResponse();
729
        }
730
731
        return [];
732
    }
733
734
    /**
735 20
     * PaymentMethodをコンテナから取得する.
736
     *
737 20
     * @param Order $Order
738
     * @param FormInterface $form
739
     *
740
     * @return PaymentMethodInterface
741
     */
742
    private function createPaymentMethod(Order $Order, FormInterface $form)
743 20
    {
744
        $PaymentMethod = $this->container->get($Order->getPayment()->getMethodClass());
745 8
        $PaymentMethod->setOrder($Order);
746
        $PaymentMethod->setFormType($form);
747 8
748 8
        return $PaymentMethod;
749 7
    }
750
}
751