UserService::deleteUser()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Core\Component\User\Application\Service;
16
17
use Acme\App\Core\Component\User\Application\Repository\UserRepositoryInterface;
18
use Acme\App\Core\Component\User\Application\Validation\UserValidationService;
19
use Acme\App\Core\Component\User\Domain\User\User;
20
use Acme\App\Core\Port\Auth\Authentication\UserSecretEncoderInterface;
21
use Acme\App\Core\Port\Persistence\Exception\EmptyQueryResultException;
22
use Acme\App\Core\Port\Validation\PhoneNumber\PhoneNumberException;
23
use Acme\App\Core\SharedKernel\Exception\AppRuntimeException;
24
25
final class UserService
26
{
27
    /**
28
     * @var UserSecretEncoderInterface
29
     */
30
    private $encoder;
31
32
    /**
33
     * @var UserValidationService
34
     */
35
    private $validator;
36
37
    /**
38
     * @var UserRepositoryInterface
39
     */
40
    private $userRepository;
41
42
    public function __construct(
43
        UserSecretEncoderInterface $encoder,
44
        UserValidationService $validator,
45
        UserRepositoryInterface $userRepository
46
    ) {
47
        $this->encoder = $encoder;
48
        $this->validator = $validator;
49
        $this->userRepository = $userRepository;
50
    }
51
52
    /**
53
     * @throws PhoneNumberException
54
     */
55
    public function createUser(
56
        string $username,
57
        string $plainPassword,
58
        string $email,
59
        string $mobile,
60
        string $fullName,
61
        bool $isAdmin
62
    ): User {
63
        // make sure to validate the user data is correct
64
        $this->validateUserData($username, $plainPassword, $email, $mobile, $fullName);
65
66
        // See https://symfony.com/doc/current/book/security.html#security-encoding-password
67
        // create the user and encode its password
68
        $user = User::constructWithoutPassword(
69
            $username,
70
            $email,
71
            $mobile,
72
            $fullName,
73
            $isAdmin ? User::ROLE_ADMIN : User::ROLE_EDITOR
74
        );
75
        $user->setPassword($this->encoder->encode($plainPassword, $user));
76
        $this->userRepository->add($user);
77
78
        return $user;
79
    }
80
81
    public function deleteUser(string $username): void
82
    {
83
        $this->validator->validateUsername($username);
84
85
        /** @var User $user */
86
        $user = $this->userRepository->findOneByUsername($username);
87
88
        if ($user === null) {
89
            throw new AppRuntimeException(sprintf('User with username "%s" not found.', $username));
90
        }
91
92
        $this->userRepository->remove($user);
93
    }
94
95
    /**
96
     * @throws PhoneNumberException
97
     */
98
    private function validateUserData($username, $plainPassword, $email, $mobile, $fullName): void
99
    {
100
        // first check if a user with the same username already exists.
101
        if ($this->usernameExists($username)) {
102
            throw new AppRuntimeException("There is already a user registered with the \"$username\" username.");
103
        }
104
105
        // validate password and email if is not this input means interactive.
106
        $this->validator->validatePassword($plainPassword);
107
        $this->validator->validateEmail($email);
108
        $this->validator->validateMobile($mobile);
109
        $this->validator->validateFullName($fullName);
110
111
        // check if a user with the same email already exists.
112
        if ($this->emailExists($email)) {
113
            throw new AppRuntimeException("There is already a user registered with the \"$email\" email.");
114
        }
115
    }
116
117
    private function usernameExists(string $username): bool
118
    {
119
        try {
120
            $this->userRepository->findOneByUsername($username);
121
122
            return true;
123
        } catch (EmptyQueryResultException $e) {
124
            return false;
125
        }
126
    }
127
128
    private function emailExists(string $email): bool
129
    {
130
        try {
131
            $this->userRepository->findOneByEmail($email);
132
133
            return true;
134
        } catch (EmptyQueryResultException $e) {
135
            return false;
136
        }
137
    }
138
}
139