Completed
Push — symfony3 ( 9e4aea...666329 )
by Kamil
18:10
created

UserController   F

Complexity

Total Complexity 50

Size/Duplication

Total Lines 394
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 23

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 50
lcom 1
cbo 23
dl 0
loc 394
rs 3.2012
c 2
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
B changePasswordAction() 0 28 6
A requestPasswordResetTokenAction() 0 7 1
A requestPasswordResetPinAction() 0 7 1
C resetPasswordAction() 0 36 7
B verifyAction() 0 41 6
B requestVerificationTokenAction() 0 34 5
D prepareResetPasswordRequest() 0 45 10
A addFlash() 0 5 1
A createResourceForm() 0 8 2
A handleExpiredToken() 0 17 2
A handleResetPasswordRequest() 0 13 1
A handleResetPassword() 0 23 3
A handleChangePassword() 0 21 3
A generateRequestPasswordResetUrl() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like UserController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use UserController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Bundle\UserBundle\Controller;
13
14
use FOS\RestBundle\View\View;
15
use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
16
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
17
use Sylius\Bundle\UserBundle\Form\Model\ChangePassword;
18
use Sylius\Bundle\UserBundle\Form\Model\PasswordReset;
19
use Sylius\Bundle\UserBundle\Form\Model\PasswordResetRequest;
20
use Sylius\Bundle\UserBundle\UserEvents;
21
use Sylius\Component\User\Model\UserInterface;
22
use Sylius\Component\User\Security\Generator\GeneratorInterface;
23
use Symfony\Component\EventDispatcher\GenericEvent;
24
use Symfony\Component\Form\FormInterface;
25
use Symfony\Component\HttpFoundation\RedirectResponse;
26
use Symfony\Component\HttpFoundation\Request;
27
use Symfony\Component\HttpFoundation\Response;
28
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
29
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
30
31
/**
32
 * @author Łukasz Chruściel <[email protected]>
33
 * @author Jan Góralski <[email protected]>
34
 */
35
class UserController extends ResourceController
36
{
37
    /**
38
     * @param Request $request
39
     *
40
     * @return Response
41
     */
42
    public function changePasswordAction(Request $request)
43
    {
44
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
45
46
        if (!$this->container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
47
            throw new AccessDeniedException('You have to be registered user to access this section.');
48
        }
49
50
        $user = $this->container->get('security.token_storage')->getToken()->getUser();
51
52
        $changePassword = new ChangePassword();
53
        $syliusConfiguration = $request->attributes->get('_sylius');
54
        $formType = isset($syliusConfiguration['form']) ? $syliusConfiguration['form'] : 'sylius_user_change_password';
55
        $form = $this->createResourceForm($configuration, $formType, $changePassword);
56
57
        if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH']) && $form->submit($request->request->get($form->getName()), !$request->isMethod('PATCH'))->isValid()) {
58
            return $this->handleChangePassword($request, $configuration, $user, $changePassword->getNewPassword());
59
        }
60
61
        if (!$configuration->isHtmlRequest()) {
62
            return $this->viewHandler->handle($configuration, View::create($form, Response::HTTP_BAD_REQUEST));
63
        }
64
65
        return $this->container->get('templating')->renderResponse(
66
            $configuration->getTemplate('changePassword.html'),
67
            ['form' => $form->createView()]
68
        );
69
    }
70
71
    /**
72
     * @param Request $request
73
     *
74
     * @return Response
75
     */
76
    public function requestPasswordResetTokenAction(Request $request)
77
    {
78
        /** @var GeneratorInterface $generator */
79
        $generator = $this->container->get(sprintf('sylius.%s.token_generator.password_reset', $this->metadata->getName()));
80
81
        return $this->prepareResetPasswordRequest($request, $generator, UserEvents::REQUEST_RESET_PASSWORD_TOKEN);
82
    }
83
84
    /**
85
     * @param Request $request
86
     *
87
     * @return Response
88
     */
89
    public function requestPasswordResetPinAction(Request $request)
90
    {
91
        /** @var GeneratorInterface $generator */
92
        $generator = $this->container->get(sprintf('sylius.%s.pin_generator.password_reset', $this->metadata->getName()));
93
94
        return $this->prepareResetPasswordRequest($request, $generator, UserEvents::REQUEST_RESET_PASSWORD_PIN);
95
    }
96
97
    /**
98
     * @param Request $request
99
     * @param string $token
100
     *
101
     * @return Response
102
     */
103
    public function resetPasswordAction(Request $request, $token)
104
    {
105
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
106
        /** @var UserInterface $user */
107
        $user = $this->repository->findOneBy(['passwordResetToken' => $token]);
108
        if (null === $user) {
109
            throw new NotFoundHttpException('Token not found.');
110
        }
111
112
        $resetting = $this->metadata->getParameter('resetting');
113
        $lifetime = new \DateInterval($resetting['token']['ttl']);
114
        if (!$user->isPasswordRequestNonExpired($lifetime)) {
115
            return $this->handleExpiredToken($configuration, $token, $user);
116
        }
117
118
        $passwordReset = new PasswordReset();
119
        $syliusConfiguration = $request->attributes->get('_sylius');
120
        $formType = isset($syliusConfiguration['form']) ? $syliusConfiguration['form'] : 'sylius_user_reset_password';
121
        $form = $this->createResourceForm($configuration, $formType, $passwordReset);
122
123
        if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH']) && $form->submit($request->request->get($form->getName()), !$request->isMethod('PATCH'))->isValid()) {
124
            return $this->handleResetPassword($request, $configuration, $user, $passwordReset->getPassword());
125
        }
126
127
        if (!$configuration->isHtmlRequest()) {
128
            return $this->viewHandler->handle($configuration, View::create($form, Response::HTTP_BAD_REQUEST));
129
        }
130
131
        return $this->container->get('templating')->renderResponse(
132
            $configuration->getTemplate('resetPassword.html'),
133
            [
134
                'form' => $form->createView(),
135
                'user' => $user,
136
            ]
137
        );
138
    }
139
140
    /**
141
     * @param Request $request
142
     * @param string $token
143
     *
144
     * @return Response
145
     */
146
    public function verifyAction(Request $request, $token)
147
    {
148
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
149
        $syliusConfiguration = $request->attributes->get('_sylius');
150
        $redirectRoute = isset($syliusConfiguration['redirect']) ? $syliusConfiguration['redirect'] : null;
151
152
        $response = $this->redirectToRoute($redirectRoute);
153
154
        /** @var UserInterface $user */
155
        $user = $this->repository->findOneBy(['emailVerificationToken' => $token]);
156
        if (null === $user) {
157
            if (!$configuration->isHtmlRequest()) {
158
                return $this->viewHandler->handle($configuration, View::create($configuration, Response::HTTP_BAD_REQUEST));
159
            }
160
161
            $this->addFlash('error', 'sylius.user.verification.error');
162
163
            return $this->redirectToRoute($redirectRoute);
164
        }
165
166
        $eventDispatcher = $this->container->get('event_dispatcher');
167
        $eventDispatcher->dispatch(UserEvents::PRE_EMAIL_VERIFICATION, new GenericEvent($user));
168
169
        $user->setVerifiedAt(new \DateTime());
170
        $user->setEmailVerificationToken(null);
171
172
        $this->manager->flush();
173
174
        $eventDispatcher->dispatch(UserEvents::POST_EMAIL_VERIFICATION, new GenericEvent($user));
175
176
        if (!$configuration->isHtmlRequest()) {
177
            return $this->viewHandler->handle($configuration, View::create($user));
178
        }
179
180
        $this->addFlash(
181
            'success',
182
            isset($syliusConfiguration['flash']) ? $syliusConfiguration['flash'] : 'sylius.user.verification.success'
183
        );
184
185
        return $response;
186
    }
187
188
    /**
189
     * @param Request $request
190
     *
191
     * @return Response
192
     */
193
    public function requestVerificationTokenAction(Request $request)
194
    {
195
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
196
        $syliusConfiguration = $request->attributes->get('_sylius');
197
        $redirectRoute = isset($syliusConfiguration['redirect']) ? $syliusConfiguration['redirect'] : 'referer';
198
199
        /** @var UserInterface $user */
200
        $user = $this->container->get('sylius.context.customer')->getCustomer()->getUser();
201
        if (null !== $user->getVerifiedAt()) {
202
            if (!$configuration->isHtmlRequest()) {
203
                return $this->viewHandler->handle($configuration, View::create($configuration, Response::HTTP_BAD_REQUEST));
204
            }
205
206
            $this->addFlash('notice', 'sylius.user.verification.notice.verified');
207
208
            return $this->redirectHandler->redirectToRoute($configuration, $redirectRoute);
209
        }
210
211
        $tokenGenerator = $this->container->get(sprintf('sylius.%s.token_generator.email_verification', $this->metadata->getName()));
212
        $user->setEmailVerificationToken($tokenGenerator->generate());
213
214
        $this->manager->flush();
215
216
        $eventDispatcher = $this->container->get('event_dispatcher');
217
        $eventDispatcher->dispatch(UserEvents::REQUEST_VERIFICATION_TOKEN, new GenericEvent($user));
218
219
        if (!$configuration->isHtmlRequest()) {
220
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
221
        }
222
223
        $this->addFlash('success', 'sylius.user.verification.request.success');
224
225
        return $this->redirectHandler->redirectToRoute($configuration, $redirectRoute);
226
    }
227
228
    /**
229
     * @param Request $request
230
     * @param GeneratorInterface $generator
231
     * @param string $senderEvent
232
     *
233
     * @return Response
234
     */
235
    protected function prepareResetPasswordRequest(Request $request, GeneratorInterface $generator, $senderEvent)
236
    {
237
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
238
239
        $passwordReset = new PasswordResetRequest();
240
        $syliusConfiguration = $request->attributes->get('_sylius');
241
        $template = isset($syliusConfiguration['template']) ? $syliusConfiguration['template'] : 'SyliusUserBundle:User:requestPasswordReset.html.twig';
242
        $formType = isset($syliusConfiguration['form']) ? $syliusConfiguration['form'] : 'sylius_user_request_password_reset';
243
        $form = $this->createResourceForm($configuration, $formType, $passwordReset);
244
245
        if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH']) && $form->submit($request->request->get($form->getName()), !$request->isMethod('PATCH'))->isValid()) {
246
            $user = $this->repository->findOneByEmail($passwordReset->getEmail());
0 ignored issues
show
Bug introduced by
The method findOneByEmail() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
247
            if (null !== $user) {
248
                $this->handleResetPasswordRequest($generator, $user, $senderEvent);
249
            }
250
251
            if (!$configuration->isHtmlRequest()) {
252
                return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
253
            }
254
255
            $this->addFlash('success', 'sylius.user.password.reset.requested');
256
            $redirectRoute = isset($syliusConfiguration['redirect']) ? $syliusConfiguration['redirect'] : 'sylius_user_security_login';
257
258
            if (is_array($redirectRoute)) {
259
                return $this->redirectHandler->redirectToRoute(
260
                    $configuration,
261
                    $configuration->getParameters()->get('redirect')['route'],
262
                    $configuration->getParameters()->get('redirect')['parameters']
263
                );
264
            }
265
266
            return $this->redirectHandler->redirectToRoute($configuration, $redirectRoute);
267
        }
268
269
        if (!$configuration->isHtmlRequest()) {
270
            return $this->viewHandler->handle($configuration, View::create($form, Response::HTTP_BAD_REQUEST));
271
        }
272
273
        return $this->container->get('templating')->renderResponse(
274
            $template,
275
            [
276
                'form' => $form->createView(),
277
            ]
278
        );
279
    }
280
281
    /**
282
     * @param string $type
283
     * @param string $message
284
     */
285
    protected function addFlash($type, $message)
286
    {
287
        $translator = $this->container->get('translator');
288
        $this->container->get('session')->getFlashBag()->add($type, $translator->trans($message, [], 'flashes'));
289
    }
290
291
    /**
292
     * @param RequestConfiguration $configuration
293
     * @param string $type
294
     * @param mixed $resource
295
     *
296
     * @return FormInterface
297
     */
298
    protected function createResourceForm(RequestConfiguration $configuration, $type, $resource)
299
    {
300
        if (!$configuration->isHtmlRequest()) {
301
            return $this->container->get('form.factory')->createNamed('', $type, $resource, ['csrf_protection' => false]);
302
        }
303
304
        return $this->container->get('form.factory')->create($type, $resource);
305
    }
306
307
    /**
308
     * @param RequestConfiguration $configuration
309
     * @param string $token
310
     * @param UserInterface $user
311
     *
312
     * @return RedirectResponse
313
     */
314
    protected function handleExpiredToken(RequestConfiguration $configuration, $token, UserInterface $user)
315
    {
316
        $user->setPasswordResetToken(null);
317
        $user->setPasswordRequestedAt(null);
318
319
        $this->manager->flush();
320
321
        if (!$configuration->isHtmlRequest()) {
322
            return $this->viewHandler->handle($configuration, View::create($user, Response::HTTP_BAD_REQUEST));
323
        }
324
325
        $this->addFlash('error', 'sylius.user.password.reset.token_expired');
326
327
        $url = $this->generateRequestPasswordResetUrl($token);
328
329
        return new RedirectResponse($url);
330
    }
331
332
    /**
333
     * @param GeneratorInterface $generator
334
     * @param UserInterface $user
335
     * @param string $senderEvent
336
     */
337
    protected function handleResetPasswordRequest(GeneratorInterface $generator, UserInterface $user, $senderEvent)
338
    {
339
        $user->setPasswordResetToken($generator->generate());
340
        $user->setPasswordRequestedAt(new \DateTime());
341
342
        /* I have to use doctrine manager directly, because domain manager functions add a flash messages. I can't get rid of them.*/
343
        $manager = $this->container->get('doctrine.orm.default_entity_manager');
344
        $manager->persist($user);
345
        $manager->flush();
346
347
        $dispatcher = $this->container->get('event_dispatcher');
348
        $dispatcher->dispatch($senderEvent, new GenericEvent($user));
349
    }
350
351
    /**
352
     * @param Request $request
353
     * @param RequestConfiguration $configuration
354
     * @param UserInterface $user
355
     * @param string $newPassword
356
     *
357
     * @return Response
358
     */
359
    protected function handleResetPassword(Request $request, RequestConfiguration $configuration, UserInterface $user, $newPassword)
360
    {
361
        $user->setPlainPassword($newPassword);
362
        $user->setPasswordResetToken(null);
363
        $user->setPasswordRequestedAt(null);
364
365
        $dispatcher = $this->container->get('event_dispatcher');
366
        $dispatcher->dispatch(UserEvents::PRE_PASSWORD_RESET, new GenericEvent($user));
367
368
        $this->manager->flush();
369
        $this->addFlash('success', 'sylius.user.password.reset.success');
370
371
        $dispatcher->dispatch(UserEvents::POST_PASSWORD_RESET, new GenericEvent($user));
372
373
        if (!$configuration->isHtmlRequest()) {
374
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
375
        }
376
377
        $syliusConfiguration = $request->attributes->get('_sylius');
378
        $redirectRoute = isset($syliusConfiguration['redirect']) ? $syliusConfiguration['redirect'] : 'sylius_user_security_login';
379
380
        return new RedirectResponse($this->container->get('router')->generate($redirectRoute));
381
    }
382
383
    /**
384
     * @param Request $request
385
     * @param RequestConfiguration $configuration
386
     * @param UserInterface $user
387
     * @param string $newPassword
388
     *
389
     * @return Response
390
     */
391
    protected function handleChangePassword(Request $request, RequestConfiguration $configuration, UserInterface $user, $newPassword)
392
    {
393
        $user->setPlainPassword($newPassword);
394
395
        $dispatcher = $this->container->get('event_dispatcher');
396
        $dispatcher->dispatch(UserEvents::PRE_PASSWORD_CHANGE, new GenericEvent($user));
397
398
        $this->manager->flush();
399
        $this->addFlash('success', 'sylius.user.password.change.success');
400
401
        $dispatcher->dispatch(UserEvents::POST_PASSWORD_CHANGE, new GenericEvent($user));
402
403
        if (!$configuration->isHtmlRequest()) {
404
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
405
        }
406
407
        $syliusConfiguration = $request->attributes->get('_sylius');
408
        $redirectRoute = isset($syliusConfiguration['redirect']) ? $syliusConfiguration['redirect'] : 'sylius_account_profile_show';
409
410
        return new RedirectResponse($this->container->get('router')->generate($redirectRoute));
411
    }
412
413
    /**
414
     * @param string $token
415
     *
416
     * @return string
417
     */
418
    protected function generateRequestPasswordResetUrl($token)
419
    {
420
        $router = $this->container->get('router');
421
422
        if (is_numeric($token)) {
423
            return $router->generate('sylius_user_request_password_reset_pin');
424
        }
425
426
        return $router->generate('sylius_user_request_password_reset_token');
427
    }
428
}
429