Passed
Push — develop ( 19858a...77414c )
by Daniel
07:32
created

Mailer::sendEmail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 5
1
<?php
2
3
namespace Silverback\ApiComponentBundle\Mailer;
4
5
use Silverback\ApiComponentBundle\Entity\User\User;
6
use Silverback\ApiComponentBundle\Exception\InvalidParameterException;
7
use Symfony\Component\HttpFoundation\RequestStack;
8
use Twig\Environment;
9
10
final class Mailer
11
{
12
    private $mailer;
13
    private $twig;
14
    private $requestStack;
15
    private $fromEmailAddress;
16
    private $logoSrc;
17
    private $websiteName;
18
    private $requestTimeout;
19
20
    public function __construct(
21
        \Swift_Mailer $mailer,
22
        Environment $twig,
23
        RequestStack $requestStack,
24
        string $fromEmailAddress,
25
        ?string $logoSrc,
26
        ?string $websiteName,
27
        int $requestTimeout
28
    ) {
29
        $this->mailer = $mailer;
30
        $this->twig = $twig;
31
        $this->requestStack = $requestStack;
32
        $this->fromEmailAddress = $fromEmailAddress;
33
        $this->logoSrc = $logoSrc;
34
        $this->websiteName = $websiteName;
35
        $this->requestTimeout = gmdate('G', $requestTimeout);
36
        if ($this->requestTimeout > 1) {
37
            $this->requestTimeout .= ' hours';
38
        } else {
39
            $this->requestTimeout .= ' hour';
40
        }
41
    }
42
43
    public function getMessage(string $toEmail, string $subject, string $htmlBody, string $textBody, ?string $replyTo = null)
44
    {
45
        $htmlTemplate = $this->twig->render('@SilverbackApiComponent/emails/template.html.twig', [
46
            'subject' => $subject,
47
            'body_html' => $htmlBody,
48
            'logo_src' => $this->logoSrc,
49
            'website_name' => $this->websiteName
50
        ]);
51
        $message = (new \Swift_Message($subject))
52
            ->setFrom($this->fromEmailAddress)
53
            ->setTo($toEmail)
54
            ->setBody($htmlTemplate, 'text/html')
55
            ->addPart($textBody, 'text/plain')
56
        ;
57
        if ($replyTo) {
58
            $message->setReplyTo($replyTo);
59
        }
60
        return $message;
61
    }
62
63
    public function sendEmail(string $toEmail, string $subject, string $htmlBody, string $textBody, ?string $replyTo = null): int
64
    {
65
        $message = $this->getMessage($toEmail, $subject, $htmlBody, $textBody, $replyTo);
66
        return $this->mailer->send($message);
67
    }
68
69
    public function passwordResetEmail(User $user, string $resetUrl): int
70
    {
71
        $confirmationToken = $user->getPasswordResetConfirmationToken();
72
        if (!$confirmationToken) {
73
            throw new InvalidParameterException(sprintf('The entity %s should have a confirmation token set to send a password reset email.', User::class));
74
        }
75
        $username = $user->getUsername();
76
        if (!$username) {
77
            throw new InvalidParameterException(sprintf('The entity %s should have a username set to send a password reset email.', User::class));
78
        }
79
        $resetUrl = $this->pathToAppUrl(
80
            $resetUrl,
81
            $confirmationToken,
82
            $username
83
        );
84
        $subject = 'Password Reset Request';
85
        $htmlEmail = $this->twig->render(
86
            '@SilverbackApiComponent/emails/password_reset.html.twig',
87
            ['user' => $user, 'reset_url' => $resetUrl, 'website_name' => $this->websiteName, 'timeout' => $this->requestTimeout]
88
        );
89
        $textEmail = $this->twig->render(
90
            '@SilverbackApiComponent/emails/password_reset.txt.twig',
91
            ['user' => $user, 'reset_url' => $resetUrl, 'website_name' => $this->websiteName, 'timeout' => $this->requestTimeout]
92
        );
93
94
        return $this->sendEmail($user->getUsername(), $subject, $htmlEmail, $textEmail);
95
    }
96
97
    public function newUsernameConfirmation(User $user, string $confirmUrl): int
98
    {
99
        $confirmationToken = $user->getUsernameConfirmationToken();
100
        if (!$confirmationToken) {
101
            throw new InvalidParameterException(sprintf('The entity %s should have a confirmation token set to send a new user confirmation email.', User::class));
102
        }
103
        $username = $user->getNewUsername();
104
        if (!$username) {
105
            throw new InvalidParameterException(sprintf('The entity %s should have a new username set to send a new user confirmation email.', User::class));
106
        }
107
108
        $confirmUrl = $this->pathToAppUrl(
109
            $confirmUrl,
110
            $confirmationToken,
111
            $username
112
        );
113
        $htmlEmail = $this->twig->render(
114
            '@SilverbackApiComponent/emails/new_username_confirmation.html.twig',
115
            ['user' => $user, 'confirm_url' => $confirmUrl, 'website_name' => $this->websiteName]
116
        );
117
        $textEmail = $this->twig->render(
118
            '@SilverbackApiComponent/emails/new_username_confirmation.txt.twig',
119
            ['user' => $user, 'confirm_url' => $confirmUrl, 'website_name' => $this->websiteName]
120
        );
121
        return $this->sendEmail($username, 'Confirm change of username', $htmlEmail, $textEmail);
122
    }
123
124
    private function pathToAppUrl(string $path, string $token, string $email): string
125
    {
126
        $request = $this->requestStack->getCurrentRequest();
127
        $urlParts = $request ? parse_url($request->headers->get('referer')) : ['scheme' => 'https', 'host' => 'no-referrer'];
128
        $path = str_replace(['{{ token }}', '{{ email }}'], [$token, $email], $path);
129
        return sprintf(
130
            '%s://%s/%s',
131
            $urlParts['scheme'],
132
            $urlParts['host'],
133
            ltrim($path, '/')
134
        );
135
    }
136
}
137