BoneUserController   F
last analyzed

Complexity

Total Complexity 69

Size/Duplication

Total Lines 648
Duplicated Lines 0 %

Test Coverage

Coverage 98.39%

Importance

Changes 11
Bugs 2 Features 0
Metric Value
wmc 69
eloc 361
c 11
b 2
f 0
dl 0
loc 648
ccs 367
cts 373
cp 0.9839
rs 2.88

18 Methods

Rating   Name   Duplication   Size   Complexity  
A indexAction() 0 13 2
A registerAction() 0 48 4
A setCookie() 0 22 3
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
A editProfileAction() 0 30 3
B changeEmailAction() 0 65 6
A resetEmailAction() 0 22 2

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 Del\Entity\User;
23
use Del\Exception\EmailLinkException;
24
use Del\Exception\UserException;
25
use Del\Factory\CountryFactory;
26
use Del\Form\Field\Text\EmailAddress;
27
use Del\Icon;
28
use Del\Service\UserService;
29
use Del\SessionManager;
30
use Del\Value\User\State;
31
use Exception;
32
use Laminas\Diactoros\Response\RedirectResponse;
33
use Laminas\Diactoros\Uri;
34
use Psr\Http\Message\ResponseInterface;
35
use Psr\Http\Message\ServerRequestInterface;
36
37
class BoneUserController extends Controller implements SessionAwareInterface
38
{
39
    use HasSessionTrait;
40
    use HasSiteConfigTrait;
41
42
    private string $logo = '';
43
44 41
    public function __construct(
45
        private UserService $userService,
46
        private MailService $mailService,
47
        private string $loginRedirectRoute,
48
        private string $adminLayout,
49
        private PasetoService $pasetoService,
50
        private bool $registrationEnabled = true,
51
        private $profileRequired = false,
52
        private bool $rememberMeCookie = true
53
    ) {
54 41
    }
55
56
    /**
57
     * @return string
58
     */
59 29
    public function getLogo(): string
60
    {
61 29
        if ($this->logo === '') {
62 29
            $this->logo = $this->getSiteConfig()->getLogo();
63
        }
64
65 29
        return $this->logo;
66
    }
67
68
    /**
69
     * @param ServerRequestInterface $request
70
     * @return ResponseInterface $response
71
     * @throws \Exception
72
     */
73 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

73
    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...
74
    {
75 1
        if ($this->getSession()->get('user')) {
76 1
            return new RedirectResponse('/user/home');
77
        }
78
79 1
        $body = $this->getView()->render('boneuser::index', [
80 1
            'logo' => $this->getLogo(),
81 1
            'canRegister' => $this->registrationEnabled
82 1
        ]
83 1
    );
84
85 1
        return new HtmlResponse($body);
86
    }
87
88
    /**
89
     * @param ServerRequestInterface $request
90
     * @return ResponseInterface
91
     * @throws UserException
92
     */
93 4
    public function registerAction(ServerRequestInterface $request): ResponseInterface
94
    {
95 4
        $form = new RegistrationForm('register', $this->getTranslator());
96 4
        $message = null;
97
98 4
        if ($request->getMethod() === 'POST') {
99
100 3
            $formData = $request->getParsedBody();
101 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 $data 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

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

204
    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...
205
    {
206 1
        $form = new LoginForm('userlogin', $this->getTranslator());
207 1
        $this->initForm($form);
208 1
        $body = $this->getView()->render('boneuser::login', ['form' => $form, 'logo' => $this->getLogo()]);
209
210 1
        return new HtmlResponse($body);
211
    }
212
213
214
    /**
215
     * @param ServerRequestInterface $request
216
     * @return ResponseInterface
217
     */
218 5
    public function loginFormAction(ServerRequestInterface $request): ResponseInterface
219
    {
220 5
        $translator = $this->getTranslator();
221 5
        $form = new LoginForm('userlogin', $translator);
222 5
        $this->initForm($form);
223 5
        $post = $request->getParsedBody();
224 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 $data 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

224
        $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
225 5
        $params = ['form' => $form];
226
227
        try {
228 5
            if ($form->isValid()) {
229 5
                $data = $form->getValues();
230 5
                $email = $data['email'];
231 5
                $pass = $data['password'];
232 5
                $userId = $this->userService->authenticate($email, $pass);
233 5
                $locale = $translator->getLocale();
234 5
                $session = $this->getSession();
235 5
                $session->set('user', $userId);
236 5
                $session->set('locale', $locale);
237 5
                $this->rememberMeCookie && isset($data['remember']) ? $this->setCookie((int)$data['remember'], $userId) : null;
238
239 5
                if ($route = $session->get('loginRedirectRoute')) {
240 5
                    $this->loginRedirectRoute = $route;
241 5
                    $session->unset('loginRedirectRoute');
242
                }
243
244 5
                $user = $this->userService->findUserById($userId);
245 1
                $user->setLastLogin(new DateTime());
246 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

246
                $this->userService->saveUser(/** @scrutinizer ignore-type */ $user);
Loading history...
247
248 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

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

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

471
                $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
472
473 2
                if ($form->isValid()) {
474 2
                    $data = $form->getValues();
475
476 2
                    if ($data['password'] === $data['confirm']) {
477 1
                        $this->userService->changePassword($user, $data['password']);
478 1
                        $this->userService->deleteEmailLink($link);
479 1
                        $message = [$translator->translate('email.resetpass.success', 'user'), 'success'];
480 1
                        $success = true;
481 1
                        $this->getSession()->set('user', $user->getId());
482
                    } else {
483 1
                        $message = [$translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
484 2
                        $form = new ResetPasswordForm('resetpass');
485
                    }
486
                }
487
            }
488 2
        } catch (EmailLinkException $e) {
489 1
            $message = [$e->getMessage(), 'danger'];
490 1
        } catch (Exception $e) {
491 1
            throw $e;
492
        }
493
494 3
        if (isset($message)) {
495 3
            $params['message'] = $message;
496
        }
497
498 3
        $params['success'] = $success;
499 3
        $params['form'] = $form;
500 3
        $params['logo'] = $this->getLogo();
501 3
        $body = $this->getView()->render('boneuser::reset-pass', $params);
502
503 3
        return new HtmlResponse($body);
504
    }
505
506
    /**
507
     * @param ServerRequestInterface $request
508
     * @return ResponseInterface
509
     */
510 3
    public function changePasswordAction(ServerRequestInterface $request): ResponseInterface
511
    {
512 3
        $user = $request->getAttribute('user');
513 3
        $form = new ResetPasswordForm('resetpass');
514 3
        $translator = $this->getTranslator();
515 3
        $message = null;
516 3
        $success = false;
517
518 3
        if ($request->getMethod() === 'POST') {
519 3
            $data = $request->getParsedBody();
520 3
            $form->populate($data);
521
522 3
            if ($form->isValid()) {
523 2
                $data = $form->getValues();
524
525 2
                if ($data['password'] === $data['confirm']) {
526 1
                    $this->userService->changePassword($user, $data['password']);
527 1
                    $message = [Icon::CHECK_CIRCLE . ' ' . $translator->translate('email.resetpass.success', 'user'), 'success'];
528 1
                    $success = true;
529
                } else {
530 1
                    $message = [Icon::WARNING . ' ' . $translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
531 1
                    $form = new ResetPasswordForm('resetpass');
532
                }
533
            } else {
534 1
                $message = [Icon::WARNING . ' There was a problem with your form.', 'danger'];
535
            }
536
        }
537
538 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...
539 3
        $params['form'] = $form;
540 3
        $params['logo'] = $this->getLogo();
541
542 3
        $body = $this->getView()->render('boneuser::change-pass', [
543 3
            'success' => $success,
544 3
            'form' => $form,
545 3
            'logo' => $this->getLogo(),
546 3
            'message' => $message
547 3
        ]);
548
549 3
        return new HtmlResponse($body);
550
    }
551
552
    /**
553
     * @param ServerRequestInterface $request
554
     * @return ResponseInterface
555
     */
556 4
    public function changeEmailAction(ServerRequestInterface $request): ResponseInterface
557
    {
558 4
        $user = $request->getAttribute('user');
559 4
        $form = new LoginForm('changeemail', $this->getTranslator());
560 4
        $form->getFields()->removeByName('remember');
561 4
        $form->getField('email')->setLabel('New email');
562 4
        $form->getField('submit')->setValue('Submit');
563 4
        $translator = $this->getTranslator();
564 4
        $params = [
565 4
            'form' => $form
566 4
        ];
567
568 4
        if ($request->getMethod() === 'POST') {
569 4
            $data = $request->getParsedBody();
570 4
            $form->populate($data);
571 4
            $message = null;
572
573 4
            if ($form->isValid()) {
574
575 4
                $newEmail = $form->getField('email')->getValue();
576 4
                $password = $form->getField('password')->getValue();
577 4
                $existing = $this->userService->findUserByEmail($newEmail);
578
579 4
                if ($existing) {
580 1
                    $message = [$translator->translate('email.changeemail.registered', 'user') . $this->getSiteConfig()->getTitle() . '.', 'danger'];
581
                } else {
582 3
                    if ($this->userService->checkPassword($user, $password)) {
583
584
                        try {
585
586 2
                            $link = $this->userService->generateEmailLink($user);
587 1
                            $email = $user->getEmail();
588 1
                            $token = $link->getToken();
589 1
                            $env = $this->getSiteConfig()->getEnvironment();
590 1
                            $mail = new EmailMessage();
591 1
                            $mail->setTo($email);
592 1
                            $mail->setSubject($translator->translate('email.changeemail.subject', 'user') . $this->mailService->getSiteConfig()->getTitle() . '.');
593 1
                            $mail->setTemplate('email.user::user_registration/change_email');
594 1
                            $mail->setViewData([
595 1
                                'siteUrl' => $env->getSiteURL(),
596 1
                                'logo' => $this->getSiteConfig()->getEmailLogo(),
597 1
                                'address' => $this->getSiteConfig()->getAddress(),
598 1
                                'resetLink' => '/user/reset-email/' . $email . '/' . $newEmail . '/' . $token,
599 1
                            ]);
600 1
                            $this->mailService->sendEmail($mail);
601 1
                            $message = [$translator->translate('email.changeemail.sent', 'user'), 'info'];
602 1
                            unset ($params['form']);
603
604 1
                        } catch (Exception $e) {
605 1
                            $message = [$translator->translate('email.changeemail.notsent', 'user') . $this->getSiteConfig()->getContactEmail() . '.', 'danger'];
606
                        }
607
608
                    } else {
609 1
                        $message = [$translator->translate('email.changeemail.wrongpass', 'user'), 'danger'];
610
                    }
611
                }
612
            }
613
614 4
            $params['message'] = $message;
615
        }
616
617 4
        $params['logo'] = $this->getLogo();
618 4
        $body = $this->getView()->render('boneuser::change-email', $params);
619
620 4
        return new LayoutResponse($body, 'layouts::admin');
621
    }
622
623
    /**
624
     * @param ServerRequestInterface $request
625
     * @return ResponseInterface
626
     */
627 1
    public function editProfileAction(ServerRequestInterface $request): ResponseInterface
628
    {
629 1
        $user = $request->getAttribute('user');
630 1
        $person = $user->getPerson();
631 1
        $image = $person->getImage();
632 1
        $form = new PersonForm('profile', $this->getTranslator());
633 1
        $array = $this->userService->getPersonSvc()->toArray($person);
0 ignored issues
show
Deprecated Code introduced by
The function Del\Service\UserService::getPersonSvc() has been deprecated: use getPersonService() instead ( Ignorable by Annotation )

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

633
        $array = /** @scrutinizer ignore-deprecated */ $this->userService->getPersonSvc()->toArray($person);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
634 1
        $form->populate($array);
635
636 1
        if ($request->getMethod() === 'POST') {
637 1
            $post = $request->getParsedBody();
638 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 $data 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

638
            $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
639
640 1
            if ($form->isValid()) {
641 1
                $data = $form->getValues();
642 1
                $data['image'] = $image;
643 1
                $dateFormat = $this->getSiteConfig()->getAttribute('i18n')['date_format'];
644 1
                $data['dob'] = DateTime::createFromFormat($dateFormat, $data['dob']);
645 1
                $data['country'] = CountryFactory::generate($data['country']);
646 1
                $this->userService->getPersonSvc()->populateFromArray($person, $data);
0 ignored issues
show
Deprecated Code introduced by
The function Del\Service\UserService::getPersonSvc() has been deprecated: use getPersonService() instead ( Ignorable by Annotation )

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

646
                /** @scrutinizer ignore-deprecated */ $this->userService->getPersonSvc()->populateFromArray($person, $data);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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