BoneUserController   F
last analyzed

Complexity

Total Complexity 69

Size/Duplication

Total Lines 647
Duplicated Lines 0 %

Test Coverage

Coverage 98.39%

Importance

Changes 12
Bugs 2 Features 0
Metric Value
eloc 360
c 12
b 2
f 0
dl 0
loc 647
ccs 366
cts 372
cp 0.9839
rs 2.88
wmc 69

18 Methods

Rating   Name   Duplication   Size   Complexity  
A resetEmailAction() 0 22 2
A editProfileAction() 0 29 3
A registerAction() 0 48 4
A indexAction() 0 13 2
A setCookie() 0 22 3
B changeEmailAction() 0 65 6
A __construct() 0 10 1
A logoutAction() 0 6 1
A activateAction() 0 43 5
A initForm() 0 3 2
A resendActivationEmailAction() 0 46 4
A loginAction() 0 7 1
A getLogo() 0 7 2
A homePageAction() 0 21 4
B resetPasswordAction() 0 52 8
A changePasswordAction() 0 40 4
F loginFormAction() 0 61 13
A forgotPasswordAction() 0 36 4

How to fix   Complexity   

Complex Class

Complex classes like BoneUserController 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.

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 BoneUserController, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Bone\User\Controller;
4
5
use Bone\Http\Response\HtmlResponse;
6
use Bone\Http\Response\LayoutResponse;
7
use Bone\I18n\Form;
8
use Bone\Controller\Controller;
9
use Bone\Paseto\PasetoService;
10
use Bone\Server\SiteConfigAwareInterface;
11
use Bone\Server\Traits\HasSiteConfigTrait;
12
use Bone\View\ViewEngine;
13
use Bone\Server\SessionAwareInterface;
14
use Bone\Server\Traits\HasSessionTrait;
15
use Bone\Mail\EmailMessage;
16
use Bone\Mail\Service\MailService;
17
use Bone\User\Form\LoginForm;
18
use Bone\User\Form\PersonForm;
19
use Bone\User\Form\RegistrationForm;
20
use Bone\User\Form\ResetPasswordForm;
21
use DateTime;
22
use DateTimeZone;
23
use Del\Entity\User;
24
use Del\Exception\EmailLinkException;
25
use Del\Exception\UserException;
26
use Del\Factory\CountryFactory;
27
use Del\Form\Field\Text\EmailAddress;
28
use Del\Icon;
29
use Del\Service\UserService;
30
use Del\SessionManager;
31
use Del\Value\User\State;
32
use Exception;
33
use Laminas\Diactoros\Response\RedirectResponse;
34
use Laminas\Diactoros\Uri;
35
use Psr\Http\Message\ResponseInterface;
36
use Psr\Http\Message\ServerRequestInterface;
37
38
class BoneUserController extends Controller implements SessionAwareInterface
39
{
40
    use HasSessionTrait;
41
    use HasSiteConfigTrait;
42
43
    private string $logo = '';
44
45 41
    public function __construct(
46
        private UserService $userService,
47
        private MailService $mailService,
48
        private string $loginRedirectRoute,
49
        private string $adminLayout,
50
        private PasetoService $pasetoService,
51
        private bool $registrationEnabled = true,
52
        private $profileRequired = false,
53
        private bool $rememberMeCookie = true
54
    ) {
55 41
    }
56
57
    /**
58
     * @return string
59
     */
60 29
    public function getLogo(): string
61
    {
62 29
        if ($this->logo === '') {
63 29
            $this->logo = $this->getSiteConfig()->getLogo();
64
        }
65
66 29
        return $this->logo;
67
    }
68
69
    /**
70
     * @param ServerRequestInterface $request
71
     * @return ResponseInterface $response
72
     * @throws \Exception
73
     */
74 1
    public function indexAction(ServerRequestInterface $request): ResponseInterface
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

74
    public function indexAction(/** @scrutinizer ignore-unused */ ServerRequestInterface $request): ResponseInterface

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...
75
    {
76 1
        if ($this->getSession()->get('user')) {
77 1
            return new RedirectResponse('/user/home');
78
        }
79
80 1
        $body = $this->getView()->render('boneuser::index', [
81 1
            'logo' => $this->getLogo(),
82 1
            'canRegister' => $this->registrationEnabled
83 1
        ]
84 1
    );
85
86 1
        return new HtmlResponse($body);
87
    }
88
89
    /**
90
     * @param ServerRequestInterface $request
91
     * @return ResponseInterface
92
     * @throws UserException
93
     */
94 4
    public function registerAction(ServerRequestInterface $request): ResponseInterface
95
    {
96 4
        $form = new RegistrationForm('register', $this->getTranslator());
97 4
        $message = null;
98
99 4
        if ($request->getMethod() === 'POST') {
100
101 3
            $formData = $request->getParsedBody();
102 3
            $form->populate($formData);
0 ignored issues
show
Bug introduced by
It seems like $formData can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

102
            $form->populate(/** @scrutinizer ignore-type */ $formData);
Loading history...
103
104 3
            if ($form->isValid()) {
105 2
                $data = $form->getValues();
106
107
                try {
108 2
                    $user = $this->userService->registerUser($data);
109 1
                    $link = $this->userService->generateEmailLink($user);
110 1
                    $mail = $this->mailService;
111
112 1
                    $env = $mail->getSiteConfig()->getEnvironment();
113 1
                    $email = $user->getEmail();
114 1
                    $token = $link->getToken();
115
116 1
                    $mail = new EmailMessage();
117 1
                    $mail->setTo($user->getEmail());
118 1
                    $mail->setSubject($this->getTranslator()->translate('email.user.register.thankswith', 'user') . ' ' . $this->mailService->getSiteConfig()->getTitle());
119 1
                    $mail->setTemplate('email.user::user_registration/user_registration');
120 1
                    $mail->setViewData([
121 1
                        'siteUrl' => $env->getSiteURL(),
122 1
                        'logo' => $this->getSiteConfig()->getEmailLogo(),
123 1
                        'address' => $this->getSiteConfig()->getAddress(),
124 1
                        'activationLink' => '/user/activate/' . $email . '/' . $token,
125 1
                    ]);
126 1
                    $this->mailService->sendEmail($mail);
127 1
                    $body = $this->getView()->render('boneuser::thanks-for-registering', ['logo' => $this->getLogo()]);
128
129 1
                    return new HtmlResponse($body);
130
131 1
                } catch (UserException $e) {
132 1
                    $message = [$e->getMessage(), 'danger'];
133
                }
134
            } else {
135 1
                $message = [Icon::WARNING . ' There was a problem with your form.', 'danger'];
136
            }
137
        }
138
139 3
        $body = $this->getView()->render('boneuser::register', ['form' => $form, 'message' => $message, 'logo' => $this->getLogo()]);
140
141 3
        return new HtmlResponse($body);
142
    }
143
144
    /**
145
     * @param ServerRequestInterface $request
146
     * @return ResponseInterface
147
     * @throws \Doctrine\ORM\ORMException
148
     * @throws \Doctrine\ORM\OptimisticLockException
149
     */
150 3
    public function activateAction(ServerRequestInterface $request): ResponseInterface
151
    {
152 3
        $email = $request->getAttribute('email');
153 3
        $token = $request->getAttribute('token');
154 3
        $translator = $this->getTranslator();
155 3
        $userService = $this->userService;
156 3
        $loginRedirect = $this->loginRedirectRoute;
157 3
        $message = null;
158
159
        try {
160 3
            $link = $userService->findEmailLink($email, $token);
161 1
            $user = $link->getUser();
162 1
            $user->setState(new State(State::STATE_ACTIVATED));
163 1
            $user->setLastLogin(new DateTime());
164 1
            $userService->saveUser($user);
165 1
            $userService->deleteEmailLink($link);
166 1
            $this->getSession()->set('user', $user->getId());
167
168 1
            if ($this->profileRequired && !$this->userService->hasProfile($user)) {
169 1
                $this->loginRedirectRoute = '/user/edit-profile';
170
171 1
                return new RedirectResponse($this->loginRedirectRoute);
172
            }
173 2
        } catch (EmailLinkException $e) {
174 2
            switch ($e->getMessage()) {
175 2
                case EmailLinkException::LINK_EXPIRED:
176 1
                    $message = [$translator->translate('login.activation.expired', 'user')
177 1
                        . ' <a href="/user/resend-activation-mail/' . $email . '">'
178 1
                        . $translator->translate('login.activation.expired2', 'user') . '</a>', 'danger'];
179 1
                    break;
180
                default:
181 1
                    $message = [$e->getMessage(), 'danger'];
182 1
                    break;
183
            }
184
        }
185
186 2
        $body = $this->getView()->render('boneuser::activate-user-account', [
187 2
            'loginRedirect' => $loginRedirect,
188 2
            'message' => $message,
189 2
            'logo' => $this->getLogo(),
190 2
        ]);
191
192 2
        return new HtmlResponse($body);
193
    }
194
195 6
    private function initForm(LoginForm $form)
196
    {
197 6
        $this->rememberMeCookie === false ? $form->getFields()->removeByName('remember') : null;
198
    }
199
200
201
    /**
202
     * @param ServerRequestInterface $request
203
     * @return ResponseInterface
204
     */
205 1
    public function loginAction(ServerRequestInterface $request): ResponseInterface
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

205
    public function loginAction(/** @scrutinizer ignore-unused */ ServerRequestInterface $request): ResponseInterface

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...
206
    {
207 1
        $form = new LoginForm('userlogin', $this->getTranslator());
208 1
        $this->initForm($form);
209 1
        $body = $this->getView()->render('boneuser::login', ['form' => $form, 'logo' => $this->getLogo()]);
210
211 1
        return new HtmlResponse($body);
212
    }
213
214
215
    /**
216
     * @param ServerRequestInterface $request
217
     * @return ResponseInterface
218
     */
219 5
    public function loginFormAction(ServerRequestInterface $request): ResponseInterface
220
    {
221 5
        $translator = $this->getTranslator();
222 5
        $form = new LoginForm('userlogin', $translator);
223 5
        $this->initForm($form);
224 5
        $post = $request->getParsedBody();
225 5
        $form->populate($post);
0 ignored issues
show
Bug introduced by
It seems like $post can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

225
        $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
226 5
        $params = ['form' => $form];
227
228
        try {
229 5
            if ($form->isValid()) {
230 5
                $data = $form->getValues();
231 5
                $email = $data['email'];
232 5
                $pass = $data['password'];
233 5
                $userId = $this->userService->authenticate($email, $pass);
234 5
                $locale = $translator->getLocale();
235 5
                $session = $this->getSession();
236 5
                $session->set('user', $userId);
237 5
                $session->set('locale', $locale);
238 5
                $this->rememberMeCookie && isset($data['remember']) ? $this->setCookie((int)$data['remember'], $userId) : null;
239
240 5
                if ($route = $session->get('loginRedirectRoute')) {
241 5
                    $this->loginRedirectRoute = $route;
242 5
                    $session->unset('loginRedirectRoute');
243
                }
244
245 5
                $user = $this->userService->findUserById($userId);
246 1
                $user->setLastLogin(new DateTime());
247 1
                $this->userService->saveUser($user);
0 ignored issues
show
Bug introduced by
It seems like $user can also be of type null; however, parameter $user of Del\Service\UserService::saveUser() does only seem to accept Del\Entity\UserInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

247
                $this->userService->saveUser(/** @scrutinizer ignore-type */ $user);
Loading history...
248
249 1
                if ($this->profileRequired && !$this->userService->hasProfile($user)) {
0 ignored issues
show
Bug introduced by
It seems like $user can also be of type null; however, parameter $user of Del\Service\UserService::hasProfile() does only seem to accept Del\Entity\UserInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

249
                if ($this->profileRequired && !$this->userService->hasProfile(/** @scrutinizer ignore-type */ $user)) {
Loading history...
250 1
                    $this->loginRedirectRoute = '/user/edit-profile';
251
                }
252
253 1
                return new RedirectResponse('/' . $locale . $this->loginRedirectRoute);
254
            }
255 4
        } catch (UserException $e) {
256 4
            switch ($e->getMessage()) {
257 4
                case UserException::USER_NOT_FOUND:
258 4
                case UserException::WRONG_PASSWORD:
259 1
                    $message = [Icon::WARNING . ' ' . $translator->translate('login.error.password', 'user') . '<a href="/user/lost-password/' . $email . '">' . $translator->translate('login.error.password2', 'user') . '</a>', 'danger'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $email does not seem to be defined for all execution paths leading up to this point.
Loading history...
260 1
                    break;
261 3
                case UserException::USER_UNACTIVATED:
262 1
                    $message = [Icon::WARNING . ' ' . $translator->translate('login.unactivated', 'user') . '<a href="/user/resend-activation-mail/' . $email . '">' . $translator->translate('login.unactivated2', 'user') . '</a>', 'danger'];
263 1
                    break;
264 2
                case UserException::USER_DISABLED:
265 2
                case UserException::USER_BANNED:
266 1
                    $message = [Icon::REMOVE . ' ' . $translator->translate('login.activation.banned', 'user'), 'danger'];
267 1
                    break;
268
                default:
269 1
                    $message = $e->getMessage();
270 1
                    break;
271
            }
272
273 4
            $params['message'] = $message;
274
        }
275
276 4
        $params['logo'] = $this->getLogo();
277 4
        $body = $this->getView()->render('boneuser::login', $params);
278
279 4
        return new HtmlResponse($body);
280
281
    }
282
283
    /**
284
     * @param int $length
285
     * @param int $userId
286
     * @throws \ParagonIE\Paseto\Exception\InvalidKeyException
287
     * @throws \ParagonIE\Paseto\Exception\InvalidPurposeException
288
     * @throws \ParagonIE\Paseto\Exception\PasetoException
289
     */
290 1
    private function setCookie(int $length, int $userId): void
291
    {
292 1
        $times = [
293 1
            1 => 60 * 60 * 24 * 7,
294 1
            2 => 60 * 60 * 24 * 30,
295 1
            3 => 60 * 60 * 24 * 365,
296 1
        ];
297
298 1
        $intervals = [
299 1
            1 => 'P07D',
300 1
            2 => 'P30D',
301 1
            3 => 'P365D',
302 1
        ];
303
304 1
        $time = array_key_exists($length, $times) ? $times[$length] : 0;
305 1
        $time += \time();
306 1
        $expiry = \time() + $time;
307 1
        $interval = array_key_exists($length, $intervals) ? $intervals[$length] : 'P0D';
308 1
        $token = $this->pasetoService->encryptToken([
309 1
            'user' => $userId,
310 1
        ], $interval);
311 1
        \setcookie('resu', $token, $expiry, '/');
312
    }
313
314
    /**
315
     * @param ServerRequestInterface $request
316
     * @return ResponseInterface
317
     */
318 2
    public function homePageAction(ServerRequestInterface $request): ResponseInterface
319
    {
320 2
        if ($this->loginRedirectRoute !== '/user/home') {
321 1
            return new RedirectResponse($this->loginRedirectRoute);
322
        }
323
324 1
        $user = $request->getAttribute('user');
325
326 1
        if ($this->profileRequired && !$this->userService->hasProfile($user)) {
327 1
            $this->loginRedirectRoute = '/user/edit-profile';
328
329 1
            return new RedirectResponse($this->loginRedirectRoute);
330
        }
331
332
        $body = $this->getView()->render('boneuser::home', [
333
            'message' => [$this->getTranslator()->translate('home.loggedin', 'user'), 'success'],
334
            'user' => $user,
335
            'logo' => $this->getSiteConfig()->getLogo(),
336
        ]);
337
338
        return new LayoutResponse($body, $this->adminLayout);
339
    }
340
341
    /**
342
     * @param ServerRequestInterface $request
343
     * @return ResponseInterface
344
     */
345 1
    public function logoutAction(ServerRequestInterface $request): ResponseInterface
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

345
    public function logoutAction(/** @scrutinizer ignore-unused */ ServerRequestInterface $request): ResponseInterface

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...
346
    {
347 1
        SessionManager::destroySession();
348 1
        \setcookie('resu', '', 1, '/');
349
350 1
        return new RedirectResponse(new Uri('/'));
351
    }
352
353
    /**
354
     * @param ServerRequestInterface $request
355
     * @return ResponseInterface
356
     */
357 4
    public function resendActivationEmailAction(ServerRequestInterface $request): ResponseInterface
358
    {
359 4
        $email = $request->getAttribute('email');
360 4
        $user = $this->userService->findUserByEmail($email);
361 4
        $message = null;
362 4
        $translator = $this->getTranslator();
363
364 4
        if (!$user) {
365 1
            throw new Exception(UserException::USER_NOT_FOUND, 404);
366
        }
367
368 3
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
369 1
            $message = [UserException::USER_ACTIVATED, 'danger'];
370
        } else {
371
            try {
372 2
                $link = $this->userService->generateEmailLink($user);
373 1
                $mail = $this->mailService;
374
375 1
                $env = $mail->getSiteConfig()->getEnvironment();
376 1
                $email = $user->getEmail();
377 1
                $token = $link->getToken();
378
379 1
                $mail = new EmailMessage();
380 1
                $mail->setTo($user->getEmail());
381 1
                $mail->setSubject($translator->translate('email.user.register.thankswith', 'user') . ' ' . $this->mailService->getSiteConfig()->getTitle());
382 1
                $mail->setTemplate('email.user::user_registration/user_registration');
383 1
                $mail->setViewData([
384 1
                    'siteUrl' => $env->getSiteURL(),
385 1
                    'logo' => $this->getSiteConfig()->getEmailLogo(),
386 1
                    'address' => $this->getSiteConfig()->getAddress(),
387 1
                    'activationLink' => '/user/activate/' . $email . '/' . $token,
388 1
                ]);
389 1
                $this->mailService->sendEmail($mail);
390
391 1
            } catch (Exception $e) {
392 1
                $message = [$translator->translate('login.resendactivation.error', 'user')
393 1
                    . $this->getSiteConfig()->getContactEmail() . '', 'danger'];
394
            }
395
        }
396
397 3
        $body = $this->getView()->render('boneuser::resend-activation', [
398 3
            'message' => $message,
399 3
            'logo' => $this->getLogo(),
400 3
        ]);
401
402 3
        return new HtmlResponse($body);
403
    }
404
405
406
    /**
407
     * @param ServerRequestInterface $request
408
     * @return ResponseInterface
409
     */
410 4
    public function forgotPasswordAction(ServerRequestInterface $request): ResponseInterface
411
    {
412 4
        $email = $request->getAttribute('email');
413 4
        $user = $this->userService->findUserByEmail($email);
414
415 4
        if (!$user) {
416 1
            throw new Exception(UserException::USER_NOT_FOUND, 404);
417
        }
418
419 3
        if ($user->getState()->getValue() == State::STATE_UNACTIVATED) {
420 1
            return new RedirectResponse('/user/resend-activation-mail/' . $email);
421
        }
422
423
        try {
424 2
            $link = $this->userService->generateEmailLink($user);
425 1
            $email = $user->getEmail();
426 1
            $token = $link->getToken();
427 1
            $env = $this->getSiteConfig()->getEnvironment();
428 1
            $mail = new EmailMessage();
429 1
            $mail->setTo($email);
430 1
            $mail->setSubject($this->getTranslator()->translate('email.forgotpass.subject', 'user') . $this->mailService->getSiteConfig()->getTitle() . '.');
431 1
            $mail->setTemplate('email.user::user_registration/reset_password');
432 1
            $mail->setViewData([
433 1
                'siteUrl' => $env->getSiteURL(),
434 1
                'logo' => $this->getSiteConfig()->getEmailLogo(),
435 1
                'address' => $this->getSiteConfig()->getAddress(),
436 1
                'resetLink' => '/user/reset-password/' . $email . '/' . $token,
437 1
            ]);
438 1
            $this->mailService->sendEmail($mail);
439 1
        } catch (Exception $e) {
440 1
            $this->view->message = [$e->getMessage(), 'danger'];
0 ignored issues
show
Bug introduced by
Accessing message on the interface Bone\View\ViewEngineInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
441
        }
442
443 2
        $body = $this->getView()->render('boneuser::forgot-password', ['logo' => $this->getLogo()]);
444
445 2
        return new HtmlResponse($body);
446
    }
447
448
449
    /**
450
     * @param ServerRequestInterface $request
451
     * @return ResponseInterface
452
     */
453 5
    public function resetPasswordAction(ServerRequestInterface $request): ResponseInterface
454
    {
455 5
        $email = $request->getAttribute('email');
456 5
        $token = $request->getAttribute('token');
457 5
        $form = new ResetPasswordForm('resetpass');
458 5
        $translator = $this->getTranslator();
459 5
        $params = [];
460 5
        $success = false;
461 5
        $user = $this->userService->findUserByEmail($email);
462
463 5
        if (!$user) {
464 1
            throw new Exception(UserException::USER_NOT_FOUND, 404);
465
        }
466
467
        try {
468 4
            $link = $this->userService->findEmailLink($email, $token);
469
470 2
            if ($request->getMethod() === 'POST') {
471 2
                $data = $request->getParsedBody();
472 2
                $form->populate($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

472
                $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
473
474 2
                if ($form->isValid()) {
475 2
                    $data = $form->getValues();
476
477 2
                    if ($data['password'] === $data['confirm']) {
478 1
                        $this->userService->changePassword($user, $data['password']);
479 1
                        $this->userService->deleteEmailLink($link);
480 1
                        $message = [$translator->translate('email.resetpass.success', 'user'), 'success'];
481 1
                        $success = true;
482 1
                        $this->getSession()->set('user', $user->getId());
483
                    } else {
484 1
                        $message = [$translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
485 2
                        $form = new ResetPasswordForm('resetpass');
486
                    }
487
                }
488
            }
489 2
        } catch (EmailLinkException $e) {
490 1
            $message = [$e->getMessage(), 'danger'];
491 1
        } catch (Exception $e) {
492 1
            throw $e;
493
        }
494
495 3
        if (isset($message)) {
496 3
            $params['message'] = $message;
497
        }
498
499 3
        $params['success'] = $success;
500 3
        $params['form'] = $form;
501 3
        $params['logo'] = $this->getLogo();
502 3
        $body = $this->getView()->render('boneuser::reset-pass', $params);
503
504 3
        return new HtmlResponse($body);
505
    }
506
507
    /**
508
     * @param ServerRequestInterface $request
509
     * @return ResponseInterface
510
     */
511 3
    public function changePasswordAction(ServerRequestInterface $request): ResponseInterface
512
    {
513 3
        $user = $request->getAttribute('user');
514 3
        $form = new ResetPasswordForm('resetpass');
515 3
        $translator = $this->getTranslator();
516 3
        $message = null;
517 3
        $success = false;
518
519 3
        if ($request->getMethod() === 'POST') {
520 3
            $data = $request->getParsedBody();
521 3
            $form->populate($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

521
            $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
522
523 3
            if ($form->isValid()) {
524 2
                $data = $form->getValues();
525
526 2
                if ($data['password'] === $data['confirm']) {
527 1
                    $this->userService->changePassword($user, $data['password']);
528 1
                    $message = [Icon::CHECK_CIRCLE . ' ' . $translator->translate('email.resetpass.success', 'user'), 'success'];
529 1
                    $success = true;
530
                } else {
531 1
                    $message = [Icon::WARNING . ' ' . $translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
532 1
                    $form = new ResetPasswordForm('resetpass');
533
                }
534
            } else {
535 1
                $message = [Icon::WARNING . ' There was a problem with your form.', 'danger'];
536
            }
537
        }
538
539 3
        $params['success'] = $success;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
540 3
        $params['form'] = $form;
541 3
        $params['logo'] = $this->getLogo();
542
543 3
        $body = $this->getView()->render('boneuser::change-pass', [
544 3
            'success' => $success,
545 3
            'form' => $form,
546 3
            'logo' => $this->getLogo(),
547 3
            'message' => $message
548 3
        ]);
549
550 3
        return new HtmlResponse($body);
551
    }
552
553
    /**
554
     * @param ServerRequestInterface $request
555
     * @return ResponseInterface
556
     */
557 4
    public function changeEmailAction(ServerRequestInterface $request): ResponseInterface
558
    {
559 4
        $user = $request->getAttribute('user');
560 4
        $form = new LoginForm('changeemail', $this->getTranslator());
561 4
        $form->getFields()->removeByName('remember');
562 4
        $form->getField('email')->setLabel('New email');
563 4
        $form->getField('submit')->setValue('Submit');
564 4
        $translator = $this->getTranslator();
565 4
        $params = [
566 4
            'form' => $form
567 4
        ];
568
569 4
        if ($request->getMethod() === 'POST') {
570 4
            $data = $request->getParsedBody();
571 4
            $form->populate($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

571
            $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
572 4
            $message = null;
573
574 4
            if ($form->isValid()) {
575
576 4
                $newEmail = $form->getField('email')->getValue();
577 4
                $password = $form->getField('password')->getValue();
578 4
                $existing = $this->userService->findUserByEmail($newEmail);
579
580 4
                if ($existing) {
581 1
                    $message = [$translator->translate('email.changeemail.registered', 'user') . $this->getSiteConfig()->getTitle() . '.', 'danger'];
582
                } else {
583 3
                    if ($this->userService->checkPassword($user, $password)) {
584
585
                        try {
586
587 2
                            $link = $this->userService->generateEmailLink($user);
588 1
                            $email = $user->getEmail();
589 1
                            $token = $link->getToken();
590 1
                            $env = $this->getSiteConfig()->getEnvironment();
591 1
                            $mail = new EmailMessage();
592 1
                            $mail->setTo($email);
593 1
                            $mail->setSubject($translator->translate('email.changeemail.subject', 'user') . $this->mailService->getSiteConfig()->getTitle() . '.');
594 1
                            $mail->setTemplate('email.user::user_registration/change_email');
595 1
                            $mail->setViewData([
596 1
                                'siteUrl' => $env->getSiteURL(),
597 1
                                'logo' => $this->getSiteConfig()->getEmailLogo(),
598 1
                                'address' => $this->getSiteConfig()->getAddress(),
599 1
                                'resetLink' => '/user/reset-email/' . $email . '/' . $newEmail . '/' . $token,
600 1
                            ]);
601 1
                            $this->mailService->sendEmail($mail);
602 1
                            $message = [$translator->translate('email.changeemail.sent', 'user'), 'info'];
603 1
                            unset ($params['form']);
604
605 1
                        } catch (Exception $e) {
606 1
                            $message = [$translator->translate('email.changeemail.notsent', 'user') . $this->getSiteConfig()->getContactEmail() . '.', 'danger'];
607
                        }
608
609
                    } else {
610 1
                        $message = [$translator->translate('email.changeemail.wrongpass', 'user'), 'danger'];
611
                    }
612
                }
613
            }
614
615 4
            $params['message'] = $message;
616
        }
617
618 4
        $params['logo'] = $this->getLogo();
619 4
        $body = $this->getView()->render('boneuser::change-email', $params);
620
621 4
        return new LayoutResponse($body, 'layouts::admin');
622
    }
623
624
    /**
625
     * @param ServerRequestInterface $request
626
     * @return ResponseInterface
627
     */
628 1
    public function editProfileAction(ServerRequestInterface $request): ResponseInterface
629
    {
630 1
        $user = $request->getAttribute('user');
631 1
        $person = $user->getPerson();
632 1
        $image = $person->getImage();
633 1
        $form = new PersonForm('profile', $this->getTranslator());
634 1
        $array = $this->userService->getPersonService()->toArray($person);
635 1
        $form->populate($array);
636
637 1
        if ($request->getMethod() === 'POST') {
638 1
            $post = $request->getParsedBody();
639 1
            $form->populate($post);
0 ignored issues
show
Bug introduced by
It seems like $post can also be of type null and object; however, parameter $values of Del\Form\AbstractForm::populate() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

639
            $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
640
641 1
            if ($form->isValid()) {
642 1
                $data = $form->getValues();
643 1
                $data['image'] = $image;
644 1
                $data['dob'] = new DateTime($data['dob'], new DateTimeZone('UTC'));
645 1
                $data['country'] = CountryFactory::generate($data['country']);
646 1
                $this->userService->getPersonService()->populateFromArray($person, $data);
647 1
                $this->userService->saveUser($user);
648
            }
649
        }
650
651 1
        $body = $this->getView()->render('boneuser::edit-profile', [
652 1
            'person' => $person,
653 1
            'form' => $form->render(),
654 1
        ]);
655
656 1
        return new LayoutResponse($body, $this->adminLayout);
657
    }
658
659
    /**
660
     * @param ServerRequestInterface $requestApiController
661
     * @return ResponseInterface
662
     */
663 2
    public function resetEmailAction(ServerRequestInterface $request): ResponseInterface
664
    {
665 2
        $email = $request->getAttribute('email');
666 2
        $newEmail = $request->getAttribute('new-email');
667 2
        $token = $request->getAttribute('token');
668 2
        $translator = $this->getTranslator();
669
670
        try {
671 2
            $link = $this->userService->findEmailLink($email, $token);
672 1
            $user = $link->getUser();
673 1
            $user->setEmail($newEmail);
674 1
            $this->userService->saveUser($user);
675 1
            $this->userService->deleteEmailLink($link);
676 1
            $message = [$translator->translate('email.changeemail.success', 'user') . $newEmail . $translator->translate('email.changeemail.success2', 'user'), 'success'];
677 1
            SessionManager::getInstance()->set('user', $user->getId());
678 1
        } catch (EmailLinkException $e) {
679 1
            $message = [$e->getMessage(), 'danger'];
680
        }
681
682 2
        $body = $this->getView()->render('boneuser::reset-email', ['message' => $message, 'logo' => $this->getLogo()]);
683
684 2
        return new HtmlResponse($body);
685
    }
686
}
687