Passed
Push — v2 ( 227daa...82a867 )
by Daniel
05:48
created

UserMailer::sendPasswordChangedEmail()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
c 1
b 0
f 0
dl 0
loc 15
ccs 0
cts 12
cp 0
rs 9.9
cc 2
nc 2
nop 1
crap 6
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
        $resetUrl = $this->pathToReferrerUrl(
64
            $user->getNewPasswordConfirmationToken(),
0 ignored issues
show
Bug introduced by
It seems like $user->getNewPasswordConfirmationToken() can also be of type null; however, parameter $token of Silverback\ApiComponentB...er::pathToReferrerUrl() does only seem to accept string, 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

64
            /** @scrutinizer ignore-type */ $user->getNewPasswordConfirmationToken(),
Loading history...
65
            $user->getUsername(),
0 ignored issues
show
Bug introduced by
It seems like $user->getUsername() can also be of type null; however, parameter $email of Silverback\ApiComponentB...er::pathToReferrerUrl() does only seem to accept string, 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

65
            /** @scrutinizer ignore-type */ $user->getUsername(),
Loading history...
66
            'resetPath',
67
            $this->defaultPasswordResetPath
68
        );
69
        $email = (new TemplatedEmail())
70
            ->to(Address::fromString($userEmail))
71
            ->subject('Your password reset request')
72
            ->htmlTemplate('@SilverbackApiComponent/emails/user_forgot_password.html.twig')
73
            ->context([
74
                'user' => $user,
75
                'reset_url' => $resetUrl,
76
                'website_name' => $this->websiteName,
77
            ]);
78
        $this->mailer->send($email);
79
    }
80
81
    public function sendChangeEmailConfirmationEmail(AbstractUser $user): void
82
    {
83
        $userEmail = $this->getUserEmail($user);
84
        $verifyUrl = $this->pathToReferrerUrl(
85
            $user->getNewEmailConfirmationToken(),
0 ignored issues
show
Bug introduced by
It seems like $user->getNewEmailConfirmationToken() can also be of type null; however, parameter $token of Silverback\ApiComponentB...er::pathToReferrerUrl() does only seem to accept string, 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

85
            /** @scrutinizer ignore-type */ $user->getNewEmailConfirmationToken(),
Loading history...
86
            $user->getUsername(),
0 ignored issues
show
Bug introduced by
It seems like $user->getUsername() can also be of type null; however, parameter $email of Silverback\ApiComponentB...er::pathToReferrerUrl() does only seem to accept string, 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

86
            /** @scrutinizer ignore-type */ $user->getUsername(),
Loading history...
87
            'verifyPath',
88
            $this->defaultChangeEmailVerifyPath
89
        );
90
        $email = (new TemplatedEmail())
91
            ->to(Address::fromString($userEmail))
92
            ->subject('Your password reset request')
93
            ->htmlTemplate('@SilverbackApiComponent/emails/user_verify_email.html.twig')
94
            ->context([
95
                'user' => $user,
96
                'verify_url' => $verifyUrl,
97
                'website_name' => $this->websiteName,
98
            ]);
99
        $this->mailer->send($email);
100
    }
101
102
    public function sendUserWelcomeEmail(AbstractUser $user): void
103
    {
104
        if (!$this->sendUserWelcomeEmailEnabled) {
105
            return;
106
        }
107
        $userEmail = $this->getUserEmail($user);
108
        $email = (new TemplatedEmail())
109
            ->to(Address::fromString($userEmail))
110
            ->subject(sprintf('Welcome to %s', $this->websiteName))
111
            ->htmlTemplate('@SilverbackApiComponent/emails/user_welcome.html.twig')
112
            ->context([
113
                'user' => $user,
114
                'website_name' => $this->websiteName,
115
            ]);
116
        $this->mailer->send($email);
117
    }
118
119
    public function sendUserEnabledEmail(AbstractUser $user): void
120
    {
121
        if (!$this->sendUserEnabledEmailEnabled) {
122
            return;
123
        }
124
        $userEmail = $this->getUserEmail($user);
125
        $email = (new TemplatedEmail())
126
            ->to(Address::fromString($userEmail))
127
            ->subject('Your account has been enabled')
128
            ->htmlTemplate('@SilverbackApiComponent/emails/user_enabled.html.twig')
129
            ->context([
130
                'user' => $user,
131
                'website_name' => $this->websiteName,
132
            ]);
133
        $this->mailer->send($email);
134
    }
135
136
    public function sendUsernameChangedEmail(AbstractUser $user): void
137
    {
138
        if (!$this->sendUserUsernameChangedEmailEnabled) {
139
            return;
140
        }
141
        $userEmail = $this->getUserEmail($user);
142
        $email = (new TemplatedEmail())
143
            ->to(Address::fromString($userEmail))
144
            ->subject('Your username has been changed')
145
            ->htmlTemplate('@SilverbackApiComponent/emails/username_changed.html.twig')
146
            ->context([
147
                'user' => $user,
148
                'website_name' => $this->websiteName,
149
            ]);
150
        $this->mailer->send($email);
151
    }
152
153
    public function sendPasswordChangedEmail(AbstractUser $user): void
154
    {
155
        if (!$this->sendUserPasswordChangedEmailEnabled) {
156
            return;
157
        }
158
        $userEmail = $this->getUserEmail($user);
159
        $email = (new TemplatedEmail())
160
            ->to(Address::fromString($userEmail))
161
            ->subject('Your password has been changed')
162
            ->htmlTemplate('@SilverbackApiComponent/emails/user_password_changed.html.twig')
163
            ->context([
164
                'user' => $user,
165
                'website_name' => $this->websiteName,
166
            ]);
167
        $this->mailer->send($email);
168
    }
169
170
    private function getUserEmail(AbstractUser $user): string
171
    {
172
        if (!($userEmail = $user->getEmailAddress())) {
173
            throw new InvalidParameterException('The user must have an email address to send a password reset email');
174
        }
175
176
        return $userEmail;
177
    }
178
179
    private function pathToReferrerUrl(string $token, string $email, string $queryKey, string $defaultPath): string
180
    {
181
        $request = $this->requestStack->getCurrentRequest();
182
        $path = $request ? $request->query->get($queryKey, $defaultPath) : $defaultPath;
183
        $urlParts = $request ? parse_url($request->headers->get('referer')) : ['scheme' => 'https', 'host' => 'no-referrer'];
184
        $path = str_replace(['{{ token }}', '{{ email }}'], [$token, $email], $path);
185
186
        return sprintf(
187
            '%s://%s/%s',
188
            $urlParts['scheme'],
189
            $urlParts['host'],
190
            ltrim($path, '/')
191
        );
192
    }
193
}
194