Passed
Push — v2 ( 82a867...9b853e )
by Daniel
05:33
created

UserMailer::pathToReferrerUrl()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 12
ccs 0
cts 10
cp 0
rs 9.9666
cc 3
nc 4
nop 4
crap 12
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Component Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentBundle\Mailer;
15
16
use Silverback\ApiComponentBundle\Entity\User\AbstractUser;
17
use Silverback\ApiComponentBundle\Exception\InvalidParameterException;
18
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
use Symfony\Component\Mailer\MailerInterface;
21
use Symfony\Component\Mime\Address;
22
23
/**
24
 * @author Daniel West <[email protected]>
25
 */
26
class UserMailer
27
{
28
    private MailerInterface $mailer;
29
    private RequestStack $requestStack;
30
    private string $websiteName;
31
    private string $defaultPasswordResetPath;
32
    private string $defaultChangeEmailVerifyPath;
33
    private bool $sendUserWelcomeEmailEnabled;
34
    private bool $sendUserEnabledEmailEnabled;
35
    private bool $sendUserUsernameChangedEmailEnabled;
36
    private bool $sendUserPasswordChangedEmailEnabled;
37
38
    public function __construct(
39
        MailerInterface $mailer,
40
        RequestStack $requestStack,
41
        string $websiteName,
42
        string $defaultPasswordResetPath,
43
        string $defaultChangeEmailVerifyPath,
44
        bool $sendUserWelcomeEmailEnabled = true,
45
        bool $sendUserEnabledEmailEnabled = true,
46
        bool $sendUserUsernameChangedEmailEnabled = true,
47
        bool $sendUserPasswordChangedEmailEnabled = true)
48
    {
49
        $this->mailer = $mailer;
50
        $this->requestStack = $requestStack;
51
        $this->defaultPasswordResetPath = $defaultPasswordResetPath;
52
        $this->defaultChangeEmailVerifyPath = $defaultChangeEmailVerifyPath;
53
        $this->websiteName = $websiteName;
54
        $this->sendUserWelcomeEmailEnabled = $sendUserWelcomeEmailEnabled;
55
        $this->sendUserEnabledEmailEnabled = $sendUserEnabledEmailEnabled;
56
        $this->sendUserUsernameChangedEmailEnabled = $sendUserUsernameChangedEmailEnabled;
57
        $this->sendUserPasswordChangedEmailEnabled = $sendUserPasswordChangedEmailEnabled;
58
    }
59
60
    public function sendPasswordResetEmail(AbstractUser $user): void
61
    {
62
        $userEmail = $this->getUserEmail($user);
63
        $userUsername = $this->getUserUsername($user);
64
        $token = $user->getNewPasswordConfirmationToken();
65
        if (!$token) {
66
            throw new InvalidParameterException('A new password confirmation token must be set to send the `password reset` email');
67
        }
68
        $resetUrl = $this->pathToReferrerUrl(
69
            $token,
70
            $userUsername,
71
            'resetPath',
72
            $this->defaultPasswordResetPath
73
        );
74
        $email = (new TemplatedEmail())
75
            ->to(Address::fromString($userEmail))
76
            ->subject('Your password reset request')
77
            ->htmlTemplate('@SilverbackApiComponent/emails/user_forgot_password.html.twig')
78
            ->context([
79
                'user' => $user,
80
                'username' => $userUsername,
81
                'reset_url' => $resetUrl,
82
                'website_name' => $this->websiteName,
83
            ]);
84
        $this->mailer->send($email);
85
    }
86
87
    public function sendChangeEmailConfirmationEmail(AbstractUser $user): void
88
    {
89
        $userEmail = $this->getUserEmail($user);
90
        $userUsername = $this->getUserUsername($user);
91
        $verifyUrl = $this->getEmailConfirmationUrl($user, $userUsername);
92
        $email = (new TemplatedEmail())
93
            ->to(Address::fromString($userEmail))
94
            ->subject('Your password reset request')
95
            ->htmlTemplate('@SilverbackApiComponent/emails/user_verify_email.html.twig')
96
            ->context([
97
                'user' => $user,
98
                'username' => $userUsername,
99
                'verify_url' => $verifyUrl,
100
                'website_name' => $this->websiteName,
101
            ]);
102
        $this->mailer->send($email);
103
    }
104
105
    public function sendUserWelcomeEmail(AbstractUser $user): void
106
    {
107
        if (!$this->sendUserWelcomeEmailEnabled) {
108
            return;
109
        }
110
        $userEmail = $this->getUserEmail($user);
111
        $userUsername = $this->getUserUsername($user);
112
        $verifyUrl = $this->getEmailConfirmationUrl($user, $userUsername);
113
        $email = (new TemplatedEmail())
114
            ->to(Address::fromString($userEmail))
115
            ->subject(sprintf('Welcome to %s', $this->websiteName))
116
            ->htmlTemplate('@SilverbackApiComponent/emails/user_welcome.html.twig')
117
            ->context([
118
                'user' => $user,
119
                'username' => $userUsername,
120
                'verify_url' => $verifyUrl,
121
                'website_name' => $this->websiteName,
122
            ]);
123
        $this->mailer->send($email);
124
    }
125
126
    public function sendUserEnabledEmail(AbstractUser $user): void
127
    {
128
        if (!$this->sendUserEnabledEmailEnabled) {
129
            return;
130
        }
131
        $userEmail = $this->getUserEmail($user);
132
        $userUsername = $this->getUserUsername($user);
133
        $email = (new TemplatedEmail())
134
            ->to(Address::fromString($userEmail))
135
            ->subject('Your account has been enabled')
136
            ->htmlTemplate('@SilverbackApiComponent/emails/user_enabled.html.twig')
137
            ->context([
138
                'user' => $user,
139
                'username' => $userUsername,
140
                'website_name' => $this->websiteName,
141
            ]);
142
        $this->mailer->send($email);
143
    }
144
145
    public function sendUsernameChangedEmail(AbstractUser $user): void
146
    {
147
        if (!$this->sendUserUsernameChangedEmailEnabled) {
148
            return;
149
        }
150
        $userEmail = $this->getUserEmail($user);
151
        $userUsername = $this->getUserUsername($user);
152
        $email = (new TemplatedEmail())
153
            ->to(Address::fromString($userEmail))
154
            ->subject('Your username has been changed')
155
            ->htmlTemplate('@SilverbackApiComponent/emails/username_changed.html.twig')
156
            ->context([
157
                'user' => $user,
158
                'username' => $userUsername,
159
                'website_name' => $this->websiteName,
160
            ]);
161
        $this->mailer->send($email);
162
    }
163
164
    public function sendPasswordChangedEmail(AbstractUser $user): void
165
    {
166
        if (!$this->sendUserPasswordChangedEmailEnabled) {
167
            return;
168
        }
169
        $userEmail = $this->getUserEmail($user);
170
        $userUsername = $this->getUserUsername($user);
171
        $email = (new TemplatedEmail())
172
            ->to(Address::fromString($userEmail))
173
            ->subject('Your password has been changed')
174
            ->htmlTemplate('@SilverbackApiComponent/emails/user_password_changed.html.twig')
175
            ->context([
176
                'user' => $user,
177
                'username' => $userUsername,
178
                'website_name' => $this->websiteName,
179
            ]);
180
        $this->mailer->send($email);
181
    }
182
183
    private function getUserEmail(AbstractUser $user): string
184
    {
185
        if (!($userEmail = $user->getEmailAddress())) {
186
            throw new InvalidParameterException('The user must have an email address set to send them any email');
187
        }
188
189
        return $userEmail;
190
    }
191
192
    private function getUserUsername(AbstractUser $user): string
193
    {
194
        if (!($userUsername = $user->getUsername())) {
195
            throw new InvalidParameterException('The user must have a username set to send them any email');
196
        }
197
198
        return $userUsername;
199
    }
200
201
    private function getEmailConfirmationUrl(AbstractUser $user, string $userUsername): string
202
    {
203
        $token = $user->getNewEmailConfirmationToken();
204
        if (!$token) {
205
            throw new InvalidParameterException('A new email confirmation token must be set to send the `email verification` email');
206
        }
207
208
        return $this->pathToReferrerUrl(
209
            $token,
210
            $userUsername,
211
            'verifyPath',
212
            $this->defaultChangeEmailVerifyPath
213
        );
214
    }
215
216
    private function pathToReferrerUrl(string $token, string $email, string $queryKey, string $defaultPath): string
217
    {
218
        $request = $this->requestStack->getCurrentRequest();
219
        $path = $request ? $request->query->get($queryKey, $defaultPath) : $defaultPath;
220
        $urlParts = $request ? parse_url($request->headers->get('referer')) : ['scheme' => 'https', 'host' => 'no-referrer'];
221
        $path = str_replace(['{{ token }}', '{{ email }}'], [$token, $email], $path);
222
223
        return sprintf(
224
            '%s://%s/%s',
225
            $urlParts['scheme'],
226
            $urlParts['host'],
227
            ltrim($path, '/')
228
        );
229
    }
230
}
231