Passed
Push — master ( 7bd6be...071490 )
by Christian
11:46 queued 10s
created

CheckoutController::confirmPage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 2
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Storefront\Controller;
4
5
use Shopware\Core\Checkout\Cart\Error\Error;
6
use Shopware\Core\Checkout\Cart\Exception\CartTokenNotFoundException;
7
use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
8
use Shopware\Core\Checkout\Cart\Exception\OrderNotFoundException;
9
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
10
use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
11
use Shopware\Core\Checkout\Payment\Exception\InvalidOrderException;
12
use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException;
13
use Shopware\Core\Checkout\Payment\Exception\UnknownPaymentMethodException;
14
use Shopware\Core\Checkout\Payment\PaymentService;
15
use Shopware\Core\Framework\Feature;
16
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
17
use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
18
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
19
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
20
use Shopware\Core\System\SalesChannel\SalesChannelContext;
21
use Shopware\Storefront\Framework\AffiliateTracking\AffiliateTrackingListener;
22
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoader;
23
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoader;
24
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoader;
25
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoader;
26
use Symfony\Component\HttpFoundation\RedirectResponse;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\HttpFoundation\Session\SessionInterface;
30
use Symfony\Component\Routing\Annotation\Route;
31
32
/**
33
 * @RouteScope(scopes={"storefront"})
34
 */
35
class CheckoutController extends StorefrontController
36
{
37
    /**
38
     * @var CartService
39
     */
40
    private $cartService;
41
42
    /**
43
     * @var CheckoutCartPageLoader
44
     */
45
    private $cartPageLoader;
46
47
    /**
48
     * @var CheckoutConfirmPageLoader
49
     */
50
    private $confirmPageLoader;
51
52
    /**
53
     * @var CheckoutFinishPageLoader
54
     */
55
    private $finishPageLoader;
56
57
    /**
58
     * @var OrderService
59
     */
60
    private $orderService;
61
62
    /**
63
     * @var PaymentService
64
     */
65
    private $paymentService;
66
67
    /**
68
     * @var OffcanvasCartPageLoader
69
     */
70
    private $offcanvasCartPageLoader;
71
72
    public function __construct(
73
        CartService $cartService,
74
        CheckoutCartPageLoader $cartPageLoader,
75
        CheckoutConfirmPageLoader $confirmPageLoader,
76
        CheckoutFinishPageLoader $finishPageLoader,
77
        OrderService $orderService,
78
        PaymentService $paymentService,
79
        OffcanvasCartPageLoader $offcanvasCartPageLoader
80
    ) {
81
        $this->cartService = $cartService;
82
        $this->cartPageLoader = $cartPageLoader;
83
        $this->confirmPageLoader = $confirmPageLoader;
84
        $this->finishPageLoader = $finishPageLoader;
85
        $this->orderService = $orderService;
86
        $this->paymentService = $paymentService;
87
        $this->offcanvasCartPageLoader = $offcanvasCartPageLoader;
88
    }
89
90
    /**
91
     * @Route("/checkout/cart", name="frontend.checkout.cart.page", options={"seo"="false"}, methods={"GET"})
92
     */
93
    public function cartPage(Request $request, SalesChannelContext $context): Response
94
    {
95
        $page = $this->cartPageLoader->load($request, $context);
96
97
        return $this->renderStorefront('@Storefront/storefront/page/checkout/cart/index.html.twig', ['page' => $page]);
98
    }
99
100
    /**
101
     * @Route("/checkout/confirm", name="frontend.checkout.confirm.page", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
102
     */
103
    public function confirmPage(Request $request, SalesChannelContext $context): Response
104
    {
105
        if (!$context->getCustomer()) {
106
            return $this->redirectToRoute('frontend.checkout.register.page');
107
        }
108
109
        if ($this->cartService->getCart($context->getToken(), $context)->getLineItems()->count() === 0) {
110
            return $this->redirectToRoute('frontend.checkout.cart.page');
111
        }
112
113
        $page = $this->confirmPageLoader->load($request, $context);
114
115
        return $this->renderStorefront('@Storefront/storefront/page/checkout/confirm/index.html.twig', ['page' => $page]);
116
    }
117
118
    /**
119
     * @Route("/checkout/finish", name="frontend.checkout.finish.page", options={"seo"="false"}, methods={"GET"})
120
     *
121
     * @throws CustomerNotLoggedInException
122
     * @throws MissingRequestParameterException
123
     * @throws OrderNotFoundException
124
     */
125
    public function finishPage(Request $request, SalesChannelContext $context): Response
126
    {
127
        if (!$context->getCustomer()) {
128
            return $this->redirectToRoute('frontend.checkout.register.page');
129
        }
130
131
        $page = $this->finishPageLoader->load($request, $context);
132
133
        if ($page->isPaymentFailed() === true) {
134
            $this->addFlash(
135
                'danger',
136
                $this->trans(
137
                    'checkout.finishPaymentFailed',
138
                    [
139
                        '%editOrderUrl%' => $this->generateUrl('frontend.account.edit-order.page', ['orderId' => $request->get('orderId')]),
140
                    ]
141
                )
142
            );
143
        }
144
145
        return $this->renderStorefront('@Storefront/storefront/page/checkout/finish/index.html.twig', ['page' => $page]);
146
    }
147
148
    /**
149
     * @Route("/checkout/order", name="frontend.checkout.finish.order", options={"seo"="false"}, methods={"POST"})
150
     */
151
    public function order(RequestDataBag $data, SalesChannelContext $context, Request $request): Response
152
    {
153
        if (!$context->getCustomer()) {
154
            return $this->redirectToRoute('frontend.checkout.register.page');
155
        }
156
157
        $formViolations = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $formViolations is dead and can be removed.
Loading history...
158
159
        $orderId = null;
160
161
        try {
162
            $this->addAffiliateTracking($data, $request->getSession());
163
            $orderId = $this->orderService->createOrder($data, $context);
164
            $finishUrl = $this->generateUrl('frontend.checkout.finish.page', ['orderId' => $orderId]);
165
            $errorUrl = $this->generateUrl('frontend.checkout.finish.page', [
166
                'orderId' => $orderId,
167
                'changedPayment' => false,
168
                'paymentFailed' => true,
169
            ]);
170
171
            $response = $this->paymentService->handlePaymentByOrder($orderId, $data, $context, $finishUrl, $errorUrl);
172
173
            return $response ?? new RedirectResponse($finishUrl);
174
        } catch (ConstraintViolationException $formViolations) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
175
        } catch (Error $blockedError) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
176
        } catch (PaymentProcessException | InvalidOrderException | UnknownPaymentMethodException $e) {
177
            return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $orderId, 'changedPayment' => false, 'paymentFailed' => true]);
178
        }
179
180
        return $this->forwardToRoute('frontend.checkout.confirm.page', ['formViolations' => $formViolations]);
181
    }
182
183
    /**
184
     * @Route("/widgets/checkout/info", name="frontend.checkout.info", methods={"GET"}, defaults={"XmlHttpRequest"=true})
185
     *
186
     * @throws CartTokenNotFoundException
187
     */
188
    public function info(Request $request, SalesChannelContext $context): Response
189
    {
190
        $page = $this->offcanvasCartPageLoader->load($request, $context);
191
192
        return $this->renderStorefront('@Storefront/storefront/layout/header/actions/cart-widget.html.twig', ['page' => $page]);
193
    }
194
195
    /**
196
     * @Route("/checkout/offcanvas", name="frontend.cart.offcanvas", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
197
     *
198
     * @throws CartTokenNotFoundException
199
     */
200
    public function offcanvas(Request $request, SalesChannelContext $context): Response
201
    {
202
        $page = $this->offcanvasCartPageLoader->load($request, $context);
203
        if (Feature::isActive('FEATURE_NEXT_10058')) {
204
            if ($request->cookies->get('sf_redirect') === null) {
205
                $cart = $page->getCart();
206
                if ($cart->getErrors()->count() > 0) {
207
                    $this->addCartErrorsToFlashBag($cart->getErrors()->getNotices(), 'info');
208
                    $this->addCartErrorsToFlashBag($cart->getErrors()->getWarnings(), 'warning');
209
                    $this->addCartErrorsToFlashBag($cart->getErrors()->getErrors(), 'danger');
210
                }
211
                $cart->getErrors()->clear();
212
            }
213
        }
214
215
        return $this->renderStorefront('@Storefront/storefront/component/checkout/offcanvas-cart.html.twig', ['page' => $page]);
216
    }
217
218
    private function addAffiliateTracking(RequestDataBag $dataBag, SessionInterface $session): void
219
    {
220
        $affiliateCode = $session->get(AffiliateTrackingListener::AFFILIATE_CODE_KEY);
221
        $campaignCode = $session->get(AffiliateTrackingListener::CAMPAIGN_CODE_KEY);
222
        if ($affiliateCode !== null && $campaignCode !== null) {
223
            $dataBag->set(AffiliateTrackingListener::AFFILIATE_CODE_KEY, $affiliateCode);
224
            $dataBag->set(AffiliateTrackingListener::CAMPAIGN_CODE_KEY, $campaignCode);
225
        }
226
    }
227
228
    /**
229
     * @param Error[] $errors
230
     */
231
    private function addCartErrorsToFlashBag(array $errors, string $type): void
232
    {
233
        foreach ($errors as $error) {
234
            $parameters = [];
235
            foreach ($error->getParameters() as $key => $value) {
236
                $parameters['%' . $key . '%'] = $value;
237
            }
238
239
            $message = $this->trans('checkout.' . $error->getMessageKey(), $parameters);
240
241
            $this->addFlash($type, $message);
242
        }
243
    }
244
}
245