Passed
Push — master ( 9bed10...cf9f86 )
by Derek Stephen
02:25
created

BoneUserController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.9666
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
namespace 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 Psr\Http\Message\ResponseInterface;
33
use Psr\Http\Message\ServerRequestInterface;
34
use Laminas\Diactoros\Response\RedirectResponse;
35
use Laminas\Diactoros\Uri;
36
37
class BoneUserController extends Controller implements SessionAwareInterface, SiteConfigAwareInterface
38
{
39
    use HasSessionTrait;
40
    use HasSiteConfigTrait;
41
42
    /** @var UserService $userService */
43
    private $userService;
44
45
    /** @var MailService $mailService */
46
    private $mailService;
47
48
    /** @var string $loginRedirectRoute */
49
    private $loginRedirectRoute;
50
51
    /** @var string $logo */
52
    private $logo;
53
54
    /** @var string $adminLayout */
55
    private $adminLayout;
56
57
    /** @var bool $registrationEnabled */
58
    private $registrationEnabled;
59
60
    /** @var bool $profileRequired */
61
    private $profileRequired;
62
63
    /** @var bool $rememberMeCookie */
64
    private $rememberMeCookie;
65
66
    /** @var PasetoService $pasetoService */
67
    private $pasetoService = null;
68
69
    /**
70
     * BoneUserController constructor.
71
     * @param UserService $userService
72
     * @param MailService $mailService
73
     */
74 27
    public function __construct(UserService $userService, MailService $mailService, string $loginRedirectRoute = '/user/home',
75
                                string $adminLayout, PasetoService $pasetoService, bool $registrationEnabled = true, $profileRequired = false,
76
                                bool $rememberMeCookie = true)
77
    {
78 27
        $this->userService = $userService;
79 27
        $this->mailService = $mailService;
80 27
        $this->loginRedirectRoute = $loginRedirectRoute;
81 27
        $this->adminLayout = $adminLayout;
82 27
        $this->registrationEnabled = $registrationEnabled;
83 27
        $this->profileRequired = $profileRequired;
84 27
        $this->rememberMeCookie = $rememberMeCookie;
85 27
        $this->profileRequired = $profileRequired;
86 27
        $this->pasetoService = $pasetoService;
87 27
    }
88
89
    /**
90
     * @return string
91
     */
92 19
    public function getLogo(): string
93
    {
94 19
        if (!$this->logo) {
95 19
            $this->logo = $this->getSiteConfig()->getLogo();
96
        }
97
98 19
        return $this->logo;
99
    }
100
101
    /**
102
     * @param ServerRequestInterface $request
103
     * @return ResponseInterface $response
104
     * @throws \Exception
105
     */
106 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

106
    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...
107
    {
108 1
        if ($this->getSession()->get('user')) {
109 1
            return new RedirectResponse('/user/home');
110
        }
111
112 1
        $body = $this->getView()->render('boneuser::index', ['logo' => $this->getLogo()]);
113
114 1
        return new HtmlResponse($body);
115
    }
116
117
    /**
118
     * @param ServerRequestInterface $request
119
     * @return ResponseInterface
120
     * @throws UserException
121
     */
122 4
    public function registerAction(ServerRequestInterface $request): ResponseInterface
123
    {
124 4
        $form = new RegistrationForm('register', $this->getTranslator());
125 4
        $message = null;
126
127 4
        if ($request->getMethod() == 'POST') {
128
129 3
            $formData = $request->getParsedBody();
130 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

130
            $form->populate(/** @scrutinizer ignore-type */ $formData);
Loading history...
131
132 3
            if ($form->isValid()) {
133 2
                $data = $form->getValues();
134
                try {
135 2
                    $user = $this->userService->registerUser($data);
136 1
                    $link = $this->userService->generateEmailLink($user);
137 1
                    $mail = $this->mailService;
138
139 1
                    $env = $mail->getSiteConfig()->getEnvironment();
140 1
                    $email = $user->getEmail();
141 1
                    $token = $link->getToken();
142
143 1
                    $mail = new EmailMessage();
144 1
                    $mail->setTo($user->getEmail());
145 1
                    $mail->setSubject($this->getTranslator()->translate('email.user.register.thankswith', 'user') . ' ' . $this->mailService->getSiteConfig()->getTitle());
146 1
                    $mail->setTemplate('email.user::user_registration/user_registration');
147 1
                    $mail->setViewData([
148 1
                        'siteUrl' => $env->getSiteURL(),
149 1
                        'logo' => $this->getSiteConfig()->getEmailLogo(),
150 1
                        'address' => $this->getSiteConfig()->getAddress(),
151 1
                        'activationLink' => '/user/activate/' . $email . '/' . $token,
152
                    ]);
153 1
                    $this->mailService->sendEmail($mail);
154 1
                    $body = $this->getView()->render('boneuser::thanks-for-registering', ['logo' => $this->getLogo()]);
155
156 1
                    return new HtmlResponse($body);
157
158 1
                } catch (UserException $e) {
159 1
                    $message = [$e->getMessage(), 'danger'];
160
                }
161
            } else {
162 1
                $message = [Icon::WARNING . ' There was a problem with your form.', 'danger'];
163
            }
164
        }
165
166 3
        $body = $this->getView()->render('boneuser::register', ['form' => $form, 'message' => $message, 'logo' => $this->getLogo()]);
167
168 3
        return new HtmlResponse($body);
169
    }
170
171
    /**
172
     * @param ServerRequestInterface $request
173
     * @return ResponseInterface
174
     * @throws \Doctrine\ORM\ORMException
175
     * @throws \Doctrine\ORM\OptimisticLockException
176
     */
177 3
    public function activateAction(ServerRequestInterface $request): ResponseInterface
178
    {
179 3
        $email = $request->getAttribute('email');
180 3
        $token = $request->getAttribute('token');
181 3
        $translator = $this->getTranslator();
182 3
        $userService = $this->userService;
183 3
        $loginRedirect = $this->loginRedirectRoute;
184 3
        $message = null;
185
186
        try {
187
188 3
            $link = $userService->findEmailLink($email, $token);
189 1
            $user = $link->getUser();
190 1
            $user->setState(new State(State::STATE_ACTIVATED));
191 1
            $user->setLastLogin(new DateTime());
192 1
            $userService->saveUser($user);
193 1
            $userService->deleteEmailLink($link);
194 1
            $this->getSession()->set('user', $user->getId());
195
196 2
        } catch (EmailLinkException $e) {
197 2
            switch ($e->getMessage()) {
198 2
                case EmailLinkException::LINK_EXPIRED:
199 1
                    $message = [$translator->translate('login.activation.expired', 'user')
200 1
                        . ' <a href="/user/resend-activation-mail/' . $email . '">'
201 1
                        . $translator->translate('login.activation.expired2', 'user') . '</a>', 'danger'];
202 1
                    break;
203
                default:
204 1
                    $message = [$e->getMessage(), 'danger'];
205 1
                    break;
206
            }
207
        }
208
209 3
        $body = $this->getView()->render('boneuser::activate-user-account', [
210 3
            'loginRedirect' => $loginRedirect,
211 3
            'message' => $message,
212 3
            'logo' => $this->getLogo(),
213
        ]);
214
215 3
        return new HtmlResponse($body);
216
    }
217
218 7
    private function initForm(LoginForm $form)
219
    {
220 7
        if ($this->rememberMeCookie === false) {
221 7
            $form->getFields()->removeByName('remember');
222
        }
223 7
    }
224
225
226
    /**
227
     * @param ServerRequestInterface $request
228
     * @return ResponseInterface
229
     */
230 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

230
    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...
231
    {
232 1
        $form = new LoginForm('userlogin', $this->getTranslator());
233 1
        $this->initForm($form);
234 1
        $body = $this->getView()->render('boneuser::login', ['form' => $form, 'logo' => $this->getLogo()]);
235
236 1
        return new HtmlResponse($body);
237
    }
238
239
240
    /**
241
     * @param ServerRequestInterface $request
242
     * @return ResponseInterface
243
     */
244 6
    public function loginFormAction(ServerRequestInterface $request): ResponseInterface
245
    {
246 6
        $translator = $this->getTranslator();
247 6
        $form = new LoginForm('userlogin', $translator);
248 6
        $this->initForm($form);
249 6
        $post = $request->getParsedBody() ?: [];
250 6
        $form->populate($post);
1 ignored issue
show
Bug introduced by
It seems like $post can also be of type 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

250
        $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
251 6
        $params = ['form' => $form];
252
253
        try {
254
255 6
            if ($form->isValid()) {
256 5
                $data = $form->getValues();
257 5
                $email = $data['email'];
258 5
                $pass = $data['password'];
259 5
                $userId = $this->userService->authenticate($email, $pass);
260 5
                $locale = $translator->getLocale();
261 5
                $session = $this->getSession();
262 5
                $session->set('user', $userId);
263 5
                $session->set('locale', $locale);
264 5
                $this->rememberMeCookie && isset($data['remember']) ? $this->setCookie((int)$data['remember'], $userId) : null;
265
266 5
                if ($route = $session->get('loginRedirectRoute')) {
267 5
                    $this->loginRedirectRoute = $route;
268 5
                    $session->unset('loginRedirectRoute');
269
                }
270
271 5
                $user = $this->userService->findUserById($userId);
272 1
                $user->setLastLogin(new DateTime());
273 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

273
                $this->userService->saveUser(/** @scrutinizer ignore-type */ $user);
Loading history...
274
275 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\User, 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

275
                if ($this->profileRequired && !$this->userService->hasProfile(/** @scrutinizer ignore-type */ $user)) {
Loading history...
276 1
                    $this->loginRedirectRoute = '/user/edit-profile';
277
                }
278
279 2
                return new RedirectResponse('/' . $locale . $this->loginRedirectRoute);
280
            }
281 4
        } catch (UserException $e) {
282 4
            switch ($e->getMessage()) {
283 4
                case UserException::USER_NOT_FOUND:
284 4
                case UserException::WRONG_PASSWORD:
285 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...
286 1
                    break;
287 3
                case UserException::USER_UNACTIVATED:
288 1
                    $message = [Icon::WARNING . ' ' . $translator->translate('login.unactivated', 'user') . '<a href="/user/resend-activation-mail/' . $email . '">' . $translator->translate('login.unactivated2', 'user') . '</a>', 'danger'];
289 1
                    break;
290 2
                case UserException::USER_DISABLED:
291 2
                case UserException::USER_BANNED:
292 1
                    $message = [Icon::REMOVE . ' ' . $translator->translate('login.activation.banned', 'user'), 'danger'];
293 1
                    break;
294
                default:
295 1
                    $message = $e->getMessage();
296 1
                    break;
297
            }
298
299 4
            $params['message'] = $message;
300
        }
301
302 5
        $params['logo'] = $this->getLogo();
303 5
        $body = $this->getView()->render('boneuser::login', $params);
304
305 5
        return new HtmlResponse($body);
306
307
    }
308
309
    /**
310
     * @param int $length
311
     * @param int $userId
312
     * @throws \ParagonIE\Paseto\Exception\InvalidKeyException
313
     * @throws \ParagonIE\Paseto\Exception\InvalidPurposeException
314
     * @throws \ParagonIE\Paseto\Exception\PasetoException
315
     */
316
    private function setCookie(int $length, int $userId): void
317
    {
318
        switch ($length) {
319
            case 1:
320
                $time = 60 * 60 * 24 * 7;
321
                break;
322
            case 1:
323
                $time = 60 * 60 * 24 * 30;
324
                break;
325
            case 1:
326
                $time = 60 * 60 * 24 * 365;
327
                break;
328
            default:
329
                $time = 0;
330
                break;
331
        }
332
        $time = time() + $time;
0 ignored issues
show
Unused Code introduced by
The assignment to $time is dead and can be removed.
Loading history...
333
        $token = $this->pasetoService->encryptToken([
334
            'user' => $userId,
335
        ]);
336
        \setcookie('resu', $token, \time() * 2, '/');
337
    }
338
339
    /**
340
     * @param ServerRequestInterface $request
341
     * @return ResponseInterface
342
     */
343 2
    public function homePageAction(ServerRequestInterface $request): ResponseInterface
344
    {
345 2
        if ($this->loginRedirectRoute !== '/user/home') {
346 1
            return new RedirectResponse($this->loginRedirectRoute);
347
        }
348
349 1
        $user = $request->getAttribute('user');
350 1
        $body = $this->getView()->render('boneuser::home', [
351 1
            'message' => [$this->getTranslator()->translate('home.loggedin', 'user'), 'success'],
352 1
            'user' => $user,
353 1
            'logo' => $this->getSiteConfig()->getLogo(),
354
        ]);
355
356 1
        return new LayoutResponse($body, $this->adminLayout);
357
    }
358
359
    /**
360
     * @param ServerRequestInterface $request
361
     * @return ResponseInterface
362
     */
363 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

363
    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...
364
    {
365 1
        SessionManager::destroySession();
366 1
        \setcookie('resu', '', 1, '/');
367
368 1
        return new RedirectResponse(new Uri('/'));
369
    }
370
371
    /**
372
     * @param ServerRequestInterface $request
373
     * @return ResponseInterface
374
     */
375 4
    public function resendActivationEmailAction(ServerRequestInterface $request): ResponseInterface
376
    {
377 4
        $success = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $success is dead and can be removed.
Loading history...
378 4
        $email = $request->getAttribute('email');
379 4
        $user = $this->userService->findUserByEmail($email);
380 4
        $message = [];
381 4
        $translator = $this->getTranslator();
382
383 4
        if (!$user) {
384 1
            throw new Exception(UserException::USER_NOT_FOUND, 404);
385
        }
386
387 3
        if ($user->getState()->getValue() == State::STATE_ACTIVATED) {
388 1
            $message = [UserException::USER_ACTIVATED, 'danger'];
0 ignored issues
show
Unused Code introduced by
The assignment to $message is dead and can be removed.
Loading history...
389
        } else {
390
            try {
391 2
                $link = $this->userService->generateEmailLink($user);
392 1
                $mail = $this->mailService;
393
394 1
                $env = $mail->getSiteConfig()->getEnvironment();
395 1
                $email = $user->getEmail();
396 1
                $token = $link->getToken();
397
398 1
                $mail = new EmailMessage();
399 1
                $mail->setTo($user->getEmail());
400 1
                $mail->setSubject($translator->translate('email.user.register.thankswith', 'user') . ' ' . $this->mailService->getSiteConfig()->getTitle());
401 1
                $mail->setTemplate('email.user::user_registration/user_registration');
402 1
                $mail->setViewData([
403 1
                    'siteUrl' => $env->getSiteURL(),
404 1
                    'logo' => $this->getSiteConfig()->getEmailLogo(),
405 1
                    'address' => $this->getSiteConfig()->getAddress(),
406 1
                    'activationLink' => '/user/activate/' . $email . '/' . $token,
407
                ]);
408 1
                $this->mailService->sendEmail($mail);
409
410 1
            } catch (Exception $e) {
411 1
                $message = [$translator->translate('login.resendactivation.error', 'user')
412 1
                    . $this->getSiteConfig()->getContactEmail() . '', 'danger'];
413
            }
414
        }
415
416 3
        $body = $this->getView()->render('boneuser::resend-activation', [
417 3
            'message' => null,
418 3
            'logo' => $this->getLogo(),
419
        ]);
420
421 3
        return new HtmlResponse($body);
422
    }
423
424
425
    /**
426
     * @param ServerRequestInterface $request
427
     * @return ResponseInterface
428
     */
429 4
    public function forgotPasswordAction(ServerRequestInterface $request): ResponseInterface
430
    {
431 4
        $email = $request->getAttribute('email');
432 4
        $user = $this->userService->findUserByEmail($email);
433
434 4
        if (!$user) {
435 1
            throw new Exception(UserException::USER_NOT_FOUND, 404);
436
        }
437
438 3
        if ($user->getState()->getValue() == State::STATE_UNACTIVATED) {
439 1
            return new RedirectResponse('/user/resend-activation-mail/' . $email);
440
        }
441
442
        try {
443
444 2
            $link = $this->userService->generateEmailLink($user);
445 1
            $email = $user->getEmail();
446 1
            $token = $link->getToken();
447 1
            $env = $this->getSiteConfig()->getEnvironment();
448 1
            $mail = new EmailMessage();
449 1
            $mail->setTo($email);
450 1
            $mail->setSubject($this->getTranslator()->translate('email.forgotpass.subject', 'user') . $this->mailService->getSiteConfig()->getTitle() . '.');
451 1
            $mail->setTemplate('email.user::user_registration/reset_password');
452 1
            $mail->setViewData([
453 1
                'siteUrl' => $env->getSiteURL(),
454 1
                'logo' => $this->getSiteConfig()->getEmailLogo(),
455 1
                'address' => $this->getSiteConfig()->getAddress(),
456 1
                'resetLink' => '/user/reset-password/' . $email . '/' . $token,
457
            ]);
458 1
            $this->mailService->sendEmail($mail);
459
460
461 1
        } catch (Exception $e) {
462 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...
463
        }
464
465 2
        $body = $this->getView()->render('boneuser::forgot-password', ['logo' => $this->getLogo()]);
466
467 2
        return new HtmlResponse($body);
468
    }
469
470
471
    /**
472
     * @param ServerRequestInterface $request
473
     * @return ResponseInterface
474
     */
475
    public function resetPasswordAction(ServerRequestInterface $request): ResponseInterface
476
    {
477
        $email = $request->getAttribute('email');
478
        $token = $request->getAttribute('token');
479
        $form = new ResetPasswordForm('resetpass');
480
        $translator = $this->getTranslator();
481
        $params = [];
482
        $success = false;
483
        $user = $this->userService->findUserByEmail($email);
484
485
        if (!$user) {
486
            throw new Exception(UserException::USER_NOT_FOUND, 404);
487
        }
488
489
        try {
490
            $link = $this->userService->findEmailLink($email, $token);
491
492
            if ($request->getMethod() === 'POST') {
493
494
                $data = $request->getParsedBody();
495
                $form->populate($data);
1 ignored issue
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

495
                $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
496
497
                if ($form->isValid()) {
498
                    $data = $form->getValues();
499
500
                    if ($data['password'] === $data['confirm']) {
501
                        $this->userService->changePassword($user, $data['password']);
502
                        $this->userService->deleteEmailLink($link);
503
                        $message = [$translator->translate('email.resetpass.success', 'user'), 'success'];
504
                        $success = true;
505
                        SessionManager::set('user', $user->getId());
0 ignored issues
show
Bug Best Practice introduced by
The method Del\SessionManager::set() is not static, but was called statically. ( Ignorable by Annotation )

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

505
                        SessionManager::/** @scrutinizer ignore-call */ 
506
                                        set('user', $user->getId());
Loading history...
506
                    } else {
507
                        $message = [$translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
508
                        $form = new ResetPasswordForm('resetpass');
509
                    }
510
                }
511
            }
512
        } catch (EmailLinkException $e) {
513
            $message = [$e->getMessage(), 'danger'];
514
        } catch (Exception $e) {
515
            throw $e;
516
        }
517
518
        if (isset($message)) {
519
            $params['message'] = $message;
520
        }
521
        
522
        $params['success'] = $success;
523
        $params['form'] = $form;
524
        $params['logo'] = $this->getLogo();
525
        $body = $this->getView()->render('boneuser::reset-pass', $params);
526
527
        return new HtmlResponse($body);
528
    }
529
530
    /**
531
     * @param ServerRequestInterface $request
532
     * @return ResponseInterface
533
     */
534
    public function changePasswordAction(ServerRequestInterface $request): ResponseInterface
535
    {
536
        $user = $request->getAttribute('user');
537
        $form = new ResetPasswordForm('resetpass');
538
        $translator = $this->getTranslator();
539
        $message = null;
540
        $success = false;
541
542
        if ($request->getMethod() === 'POST') {
543
544
            $data = $request->getParsedBody();
545
            $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

545
            $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
546
547
            if ($form->isValid()) {
548
                $data = $form->getValues();
549
                if ($data['password'] === $data['confirm']) {
550
                    $this->userService->changePassword($user, $data['password']);
551
                    $message = [Icon::CHECK_CIRCLE . ' ' . $translator->translate('email.resetpass.success', 'user'), 'success'];
552
                    $success = true;
553
                } else {
554
                    $message = [Icon::WARNING . ' ' . $translator->translate('email.resetpass.nomatch', 'user'), 'danger'];
555
                    $form = new ResetPasswordForm('resetpass');
556
                }
557
            } else {
558
                $message = [Icon::WARNING . ' There was a problem with your form.', 'danger'];
559
            }
560
        }
561
562
        $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...
563
        $params['form'] = $form;
564
        $params['logo'] = $this->getLogo();
565
566
        $body = $this->getView()->render('boneuser::change-pass', [
567
            'success' => $success,
568
            'form' => $form,
569
            'logo' => $this->getLogo(),
570
            'message' => $message
571
        ]);
572
573
        return new HtmlResponse($body);
574
    }
575
576
    /**
577
     * @param ServerRequestInterface $request
578
     * @return ResponseInterface
579
     */
580
    public function changeEmailAction(ServerRequestInterface $request): ResponseInterface
581
    {
582
        $user = $request->getAttribute('user');
583
        $form = new LoginForm('changeemail', $this->getTranslator());
584
        $form->getField('email')->setLabel('New email');
585
        $form->getField('submit')->setValue('Submit');
586
        $translator = $this->getTranslator();
587
        $params = [
588
            'form' => $form
589
        ];
590
591
        if ($request->getMethod() === 'POST') {
592
593
            $data = $request->getParsedBody();
594
            $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

594
            $form->populate(/** @scrutinizer ignore-type */ $data);
Loading history...
595
596
            if ($form->isValid($data)) {
0 ignored issues
show
Unused Code introduced by
The call to Del\Form\AbstractForm::isValid() has too many arguments starting with $data. ( Ignorable by Annotation )

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

596
            if ($form->/** @scrutinizer ignore-call */ isValid($data)) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
597
598
                $newEmail = $form->getField('email')->getValue();
599
                $password = $form->getField('password')->getValue();
600
601
                $existing = $this->userService->findUserByEmail($newEmail);
602
603
                if ($existing) {
604
                    $message = [$translator->translate('email.changeemail.registered', 'user') . $this->getSiteConfig()->getTitle() . '.', 'danger'];
605
                } else {
606
                    if ($this->userService->checkPassword($user, $password)) {
607
608
                        $link = $this->userService->generateEmailLink($user);
0 ignored issues
show
Unused Code introduced by
The assignment to $link is dead and can be removed.
Loading history...
609
610
                        try {
611
612
                            $link = $this->userService->generateEmailLink($user);
613
                            $email = $user->getEmail();
614
                            $token = $link->getToken();
615
                            $env = $this->getSiteConfig()->getEnvironment();
616
                            $mail = new EmailMessage();
617
                            $mail->setTo($email);
618
                            $mail->setSubject($translator->translate('email.changeemail.subject', 'user') . $this->mailService->getSiteConfig()->getTitle() . '.');
619
                            $mail->setTemplate('email.user::user_registration/change_email');
620
                            $mail->setViewData([
621
                                'siteUrl' => $env->getSiteURL(),
622
                                'logo' => $this->getSiteConfig()->getEmailLogo(),
623
                                'address' => $this->getSiteConfig()->getAddress(),
624
                                'resetLink' => '/user/reset-email/' . $email . '/' . $newEmail . '/' . $token,
625
                            ]);
626
                            $this->mailService->sendEmail($mail);
627
                            $message = [$translator->translate('email.changeemail.sent', 'user'), 'info'];
628
                            unset ($params['form']);
629
630
                        } catch (Exception $e) {
631
                            $message = [$translator->translate('email.changeemail.notsent', 'user') . $this->config->email->support . '.', 'danger'];
0 ignored issues
show
Bug Best Practice introduced by
The property config does not exist on Bone\User\Controller\BoneUserController. Did you maybe forget to declare it?
Loading history...
632
                        }
633
634
                    } else {
635
                        $message = [$translator->translate('email.changeemail.wrongpass', 'user'), 'danger'];
636
                    }
637
                }
638
            }
639
            $params['message'] = $message;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
640
        }
641
        $params['logo'] = $this->getLogo();
642
643
        $body = $this->getView()->render('boneuser::change-email', $params);
644
645
        return new LayoutResponse($body, 'layouts::admin');
646
    }
647
648
    /**
649
     * @param ServerRequestInterface $request
650
     * @return ResponseInterface
651
     */
652
    public function editProfileAction(ServerRequestInterface $request): ResponseInterface
653
    {
654
        $user = $request->getAttribute('user');
655
        $person = $user->getPerson();
656
        $image = $person->getImage();
657
        $form = new PersonForm('profile', $this->getTranslator());
658
        $array = $this->userService->getPersonSvc()->toArray($person);
659
660
        $form->populate($array);
661
662
        if ($request->getMethod() === 'POST') {
663
            $post = $request->getParsedBody();
664
            $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

664
            $form->populate(/** @scrutinizer ignore-type */ $post);
Loading history...
665
666
            if ($form->isValid()) {
667
                $data = $form->getValues();
668
                $data['image'] = $image;
669
                $dateFormat = $this->getSiteConfig()->getAttribute('i18n')['date_format'];
670
                $data['dob'] = DateTime::createFromFormat($dateFormat, $data['dob']);
671
                $data['country'] = CountryFactory::generate($data['country']);
672
                $this->userService->getPersonSvc()->populateFromArray($person, $data);
673
                $this->userService->saveUser($user);
674
            }
675
        }
676
677
        $body = $this->getView()->render('boneuser::edit-profile', [
678
            'person' => $person,
679
            'form' => $form->render(),
680
        ]);
681
682
        return new LayoutResponse($body, $this->adminLayout);
683
    }
684
685
    /**
686
     * @param ServerRequestInterface $requestApiController
687
     * @return ResponseInterface
688
     */
689
    public function resetEmailAction(ServerRequestInterface $request): ResponseInterface
690
    {
691
        $email = $request->getAttribute('email');
692
        $newEmail = $request->getAttribute('new-email');
693
        $token = $request->getAttribute('token');
694
        $message = null;
695
        $translator = $this->getTranslator();
696
697
        try {
698
699
            $link = $this->userService->findEmailLink($email, $token);
700
            $user = $link->getUser();
701
            $user->setEmail($newEmail);
702
            $this->userService->saveUser($user);
703
            $this->userService->deleteEmailLink($link);
704
            $message = [$translator->translate('email.changeemail.success', 'user') . $newEmail . $translator->translate('email.changeemail.success2', 'user'), 'success'];
705
            SessionManager::set('user', $user->getId());
0 ignored issues
show
Bug Best Practice introduced by
The method Del\SessionManager::set() is not static, but was called statically. ( Ignorable by Annotation )

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

705
            SessionManager::/** @scrutinizer ignore-call */ 
706
                            set('user', $user->getId());
Loading history...
706
707
        } catch (EmailLinkException $e) {
708
            $message = [$e->getMessage(), 'danger'];
709
        } catch (Exception $e) {
710
            throw $e;
711
        }
712
713
        $body = $this->getView()->render('boneuser::reset-email', ['message' => $message, 'logo' => $this->getLogo()]);
714
715
        return new HtmlResponse($body);
716
    }
717
}
718