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

UserMailer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 20
ccs 0
cts 10
cp 0
rs 9.9666
cc 1
nc 1
nop 9
crap 2

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
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