Passed
Push — trunk ( 1e1758...8e4416 )
by Christian
12:44 queued 14s
created

AuthController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 8
dl 0
loc 10
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
namespace Shopware\Storefront\Controller;
4
5
use Shopware\Core\Checkout\Customer\Exception\BadCredentialsException;
6
use Shopware\Core\Checkout\Customer\Exception\CustomerAuthThrottledException;
7
use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundByHashException;
8
use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundException;
9
use Shopware\Core\Checkout\Customer\Exception\CustomerOptinNotCompletedException;
10
use Shopware\Core\Checkout\Customer\Exception\CustomerRecoveryHashExpiredException;
11
use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLoginRoute;
12
use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLogoutRoute;
13
use Shopware\Core\Checkout\Customer\SalesChannel\AbstractResetPasswordRoute;
14
use Shopware\Core\Checkout\Customer\SalesChannel\AbstractSendPasswordRecoveryMailRoute;
15
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
16
use Shopware\Core\Framework\Log\Package;
17
use Shopware\Core\Framework\RateLimiter\Exception\RateLimitExceededException;
18
use Shopware\Core\Framework\Routing\RoutingException;
19
use Shopware\Core\Framework\Validation\DataBag\DataBag;
20
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
21
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
22
use Shopware\Core\PlatformRequest;
23
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceInterface;
24
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
25
use Shopware\Core\System\SalesChannel\SalesChannelContext;
26
use Shopware\Storefront\Checkout\Cart\SalesChannel\StorefrontCartFacade;
27
use Shopware\Storefront\Framework\Routing\RequestTransformer;
28
use Shopware\Storefront\Page\Account\Login\AccountGuestLoginPageLoadedHook;
29
use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedHook;
30
use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoader;
31
use Shopware\Storefront\Page\Account\RecoverPassword\AccountRecoverPasswordPageLoadedHook;
32
use Shopware\Storefront\Page\Account\RecoverPassword\AccountRecoverPasswordPageLoader;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\HttpFoundation\Response;
35
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
36
use Symfony\Component\Routing\Annotation\Route;
37
38
/**
39
 * @internal
40
 * Do not use direct or indirect repository calls in a controller. Always use a store-api route to get or put data
41
 */
42
#[Route(defaults: ['_routeScope' => ['storefront']])]
43
#[Package('storefront')]
44
class AuthController extends StorefrontController
45
{
46
    /**
47
     * @internal
48
     */
49
    public function __construct(
50
        private readonly AccountLoginPageLoader $loginPageLoader,
51
        private readonly AbstractSendPasswordRecoveryMailRoute $sendPasswordRecoveryMailRoute,
52
        private readonly AbstractResetPasswordRoute $resetPasswordRoute,
53
        private readonly AbstractLoginRoute $loginRoute,
54
        private readonly AbstractLogoutRoute $logoutRoute,
55
        private readonly StorefrontCartFacade $cartFacade,
56
        private readonly AccountRecoverPasswordPageLoader $recoverPasswordPageLoader,
57
        private readonly SalesChannelContextServiceInterface $salesChannelContextService
58
    ) {
59
    }
60
61
    #[Route(path: '/account/login', name: 'frontend.account.login.page', defaults: ['_noStore' => true], methods: ['GET'])]
62
    public function loginPage(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
63
    {
64
        /** @var string $redirect */
65
        $redirect = $request->get('redirectTo', 'frontend.account.home.page');
66
67
        $customer = $context->getCustomer();
68
69
        if ($customer !== null && $customer->getGuest() === false) {
70
            $request->request->set('redirectTo', $redirect);
71
72
            return $this->createActionResponse($request);
73
        }
74
75
        $page = $this->loginPageLoader->load($request, $context);
76
77
        $this->hook(new AccountLoginPageLoadedHook($page, $context));
78
79
        return $this->renderStorefront('@Storefront/storefront/page/account/register/index.html.twig', [
80
            'redirectTo' => $redirect,
81
            'redirectParameters' => $request->get('redirectParameters', json_encode([])),
82
            'errorRoute' => $request->attributes->get('_route'),
83
            'page' => $page,
84
            'loginError' => (bool) $request->get('loginError'),
85
            'waitTime' => $request->get('waitTime'),
86
            'errorSnippet' => $request->get('errorSnippet'),
87
            'data' => $data,
88
        ]);
89
    }
90
91
    #[Route(path: '/account/guest/login', name: 'frontend.account.guest.login.page', defaults: ['_noStore' => true], methods: ['GET'])]
92
    public function guestLoginPage(Request $request, SalesChannelContext $context): Response
93
    {
94
        /** @var string $redirect */
95
        $redirect = $request->get('redirectTo', 'frontend.account.home.page');
96
97
        $customer = $context->getCustomer();
98
99
        if ($customer !== null) {
100
            $request->request->set('redirectTo', $redirect);
101
102
            return $this->createActionResponse($request);
103
        }
104
105
        $waitTime = (int) $request->get('waitTime');
106
        if ($waitTime) {
107
            $this->addFlash(self::INFO, $this->trans('account.loginThrottled', ['%seconds%' => $waitTime]));
108
        }
109
110
        if ((bool) $request->get('loginError')) {
111
            $this->addFlash(self::DANGER, $this->trans('account.orderGuestLoginWrongCredentials'));
112
        }
113
114
        $page = $this->loginPageLoader->load($request, $context);
115
116
        $this->hook(new AccountGuestLoginPageLoadedHook($page, $context));
117
118
        return $this->renderStorefront('@Storefront/storefront/page/account/guest-auth.html.twig', [
119
            'redirectTo' => $redirect,
120
            'redirectParameters' => $request->get('redirectParameters', json_encode([])),
121
            'page' => $page,
122
        ]);
123
    }
124
125
    #[Route(path: '/account/logout', name: 'frontend.account.logout.page', methods: ['GET'])]
126
    public function logout(Request $request, SalesChannelContext $context, RequestDataBag $dataBag): Response
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

126
    public function logout(/** @scrutinizer ignore-unused */ Request $request, SalesChannelContext $context, RequestDataBag $dataBag): Response

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
127
    {
128
        if ($context->getCustomer() === null) {
129
            return $this->redirectToRoute('frontend.account.login.page');
130
        }
131
132
        try {
133
            $this->logoutRoute->logout($context, $dataBag);
134
            $this->addFlash(self::SUCCESS, $this->trans('account.logoutSucceeded'));
135
136
            $parameters = [];
137
        } catch (ConstraintViolationException $formViolations) {
138
            $parameters = ['formViolations' => $formViolations];
139
        }
140
141
        return $this->redirectToRoute('frontend.account.login.page', $parameters);
142
    }
143
144
    #[Route(path: '/account/login', name: 'frontend.account.login', defaults: ['XmlHttpRequest' => true], methods: ['POST'])]
145
    public function login(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
146
    {
147
        $customer = $context->getCustomer();
148
149
        if ($customer !== null && $customer->getGuest() === false) {
150
            return $this->createActionResponse($request);
151
        }
152
153
        try {
154
            $token = $this->loginRoute->login($data, $context)->getToken();
155
            $cartBeforeNewContext = $this->cartFacade->get($token, $context);
156
157
            $newContext = $this->salesChannelContextService->get(
158
                new SalesChannelContextServiceParameters(
159
                    $context->getSalesChannelId(),
160
                    $token,
161
                    $context->getLanguageIdChain()[0],
162
                    $context->getCurrencyId(),
163
                    $context->getDomainId(),
164
                    $context->getContext()
165
                )
166
            );
167
168
            // Update the sales channel context for CacheResponseSubscriber
169
            $request->attributes->set(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT, $newContext);
170
171
            if (!empty($token)) {
172
                $this->addCartErrors($cartBeforeNewContext);
173
174
                return $this->createActionResponse($request);
175
            }
176
        } catch (BadCredentialsException|UnauthorizedHttpException|CustomerOptinNotCompletedException|CustomerAuthThrottledException $e) {
177
            if ($e instanceof CustomerOptinNotCompletedException) {
178
                $errorSnippet = $e->getSnippetKey();
179
            }
180
181
            if ($e instanceof CustomerAuthThrottledException) {
182
                $waitTime = $e->getWaitTime();
183
            }
184
        }
185
186
        $data->set('password', null);
187
188
        return $this->forwardToRoute(
189
            'frontend.account.login.page',
190
            [
191
                'loginError' => true,
192
                'errorSnippet' => $errorSnippet ?? null,
193
                'waitTime' => $waitTime ?? null,
194
            ]
195
        );
196
    }
197
198
    #[Route(path: '/account/recover', name: 'frontend.account.recover.page', methods: ['GET'])]
199
    public function recoverAccountForm(Request $request, SalesChannelContext $context): Response
200
    {
201
        $page = $this->loginPageLoader->load($request, $context);
202
203
        return $this->renderStorefront('@Storefront/storefront/page/account/profile/recover-password.html.twig', [
204
            'page' => $page,
205
        ]);
206
    }
207
208
    #[Route(path: '/account/recover', name: 'frontend.account.recover.request', methods: ['POST'])]
209
    public function generateAccountRecovery(Request $request, RequestDataBag $data, SalesChannelContext $context): Response
210
    {
211
        try {
212
            $mailData = $data->get('email');
213
            if (!$mailData instanceof DataBag) {
214
                throw RoutingException::invalidRequestParameter('email');
215
            }
216
            $mailData->set('storefrontUrl', $request->attributes->get(RequestTransformer::STOREFRONT_URL));
217
218
            $this->sendPasswordRecoveryMailRoute->sendRecoveryMail(
219
                $mailData->toRequestDataBag(),
220
                $context,
221
                false
222
            );
223
224
            $this->addFlash(self::SUCCESS, $this->trans('account.recoveryMailSend'));
225
        } catch (CustomerNotFoundException $e) {
226
            $this->addFlash(self::SUCCESS, $this->trans('account.recoveryMailSend'));
227
        } catch (InconsistentCriteriaIdsException $e) {
228
            $this->addFlash(self::DANGER, $this->trans('error.message-default'));
229
        } catch (RateLimitExceededException $e) {
230
            $this->addFlash(self::INFO, $this->trans('error.rateLimitExceeded', ['%seconds%' => $e->getWaitTime()]));
231
        }
232
233
        return $this->redirectToRoute('frontend.account.recover.page');
234
    }
235
236
    #[Route(path: '/account/recover/password', name: 'frontend.account.recover.password.page', methods: ['GET'])]
237
    public function resetPasswordForm(Request $request, SalesChannelContext $context): Response
238
    {
239
        /** @var ?string $hash */
240
        $hash = $request->get('hash');
241
242
        if (!$hash || !\is_string($hash)) {
243
            $this->addFlash(self::DANGER, $this->trans('account.passwordHashNotFound'));
244
245
            return $this->redirectToRoute('frontend.account.recover.request');
246
        }
247
248
        try {
249
            $page = $this->recoverPasswordPageLoader->load($request, $context, $hash);
250
        } catch (ConstraintViolationException) {
251
            $this->addFlash(self::DANGER, $this->trans('account.passwordHashNotFound'));
252
253
            return $this->redirectToRoute('frontend.account.recover.request');
254
        }
255
256
        $this->hook(new AccountRecoverPasswordPageLoadedHook($page, $context));
257
258
        if ($page->getHash() === null || $page->isHashExpired()) {
259
            $this->addFlash(self::DANGER, $this->trans('account.passwordHashNotFound'));
260
261
            return $this->redirectToRoute('frontend.account.recover.request');
262
        }
263
264
        return $this->renderStorefront('@Storefront/storefront/page/account/profile/reset-password.html.twig', [
265
            'page' => $page,
266
            'formViolations' => $request->get('formViolations'),
267
        ]);
268
    }
269
270
    #[Route(path: '/account/recover/password', name: 'frontend.account.recover.password.reset', methods: ['POST'])]
271
    public function resetPassword(RequestDataBag $data, SalesChannelContext $context): Response
272
    {
273
        $passwordData = $data->get('password');
274
        if (!$passwordData instanceof DataBag) {
275
            throw RoutingException::invalidRequestParameter('password');
276
        }
277
        $hash = $passwordData->get('hash');
278
279
        try {
280
            $this->resetPasswordRoute->resetPassword($passwordData->toRequestDataBag(), $context);
281
282
            $this->addFlash(self::SUCCESS, $this->trans('account.passwordChangeSuccess'));
283
        } catch (ConstraintViolationException $formViolations) {
284
            $this->addFlash(self::DANGER, $this->trans('account.passwordChangeNoSuccess'));
285
286
            if ($formViolations->getViolations('newPassword')->count() === 1) {
287
                $this->addFlash(self::DANGER, $this->trans('account.passwordNotIdentical'));
288
            }
289
290
            return $this->forwardToRoute(
291
                'frontend.account.recover.password.page',
292
                ['hash' => $hash, 'formViolations' => $formViolations, 'passwordFormViolation' => true]
293
            );
294
        } catch (CustomerNotFoundByHashException) {
295
            $this->addFlash(self::DANGER, $this->trans('account.passwordChangeNoSuccess'));
296
297
            return $this->forwardToRoute('frontend.account.recover.request');
298
        } catch (CustomerRecoveryHashExpiredException) {
299
            $this->addFlash(self::DANGER, $this->trans('account.passwordHashExpired'));
300
301
            return $this->forwardToRoute('frontend.account.recover.request');
302
        }
303
304
        return $this->redirectToRoute('frontend.account.profile.page');
305
    }
306
}
307