Failed Conditions
Push — master ( 0fd122...b2f91e )
by Adrien
06:52
created

Mailer   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Test Coverage

Coverage 94.74%

Importance

Changes 0
Metric Value
eloc 73
dl 0
loc 189
ccs 72
cts 76
cp 0.9474
rs 10
c 0
b 0
f 0
wmc 13

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A queueRegister() 0 10 1
A sendAllMessages() 0 5 2
A queueResetPassword() 0 12 1
A sendMessageAsync() 0 10 2
A sendMessage() 0 21 4
A createMessage() 0 28 1
A modelMessageToMailMessage() 0 14 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service;
6
7
use Application\DBAL\Types\MessageTypeType;
8
use Application\Model\Message;
9
use Application\Model\User;
10
use Cake\Chronos\Chronos;
11
use Doctrine\ORM\EntityManager;
12
use Zend\Mail;
13
use Zend\Mail\Transport\TransportInterface;
14
use Zend\Mime\Message as MimeMessage;
15
use Zend\Mime\Part as MimePart;
16
use Zend\View\Model\ViewModel;
17
use Zend\View\Renderer\RendererInterface;
18
19
class Mailer
20
{
21
    /**
22
     * @var EntityManager
23
     */
24
    private $entityManager;
25
26
    /**
27
     * @var TransportInterface
28
     */
29
    private $transport;
30
31
    /**
32
     * @var string
33
     */
34
    private $hostname;
35
36
    /**
37
     * @var null|string
38
     */
39
    private $emailOverride;
40
41
    /**
42
     * @var RendererInterface
43
     */
44
    private $viewRendered;
45
46 4
    public function __construct(EntityManager $entityManager, TransportInterface $transport, RendererInterface $viewRenderer, string $hostname, ?string $emailOverride)
47
    {
48 4
        $this->entityManager = $entityManager;
49 4
        $this->transport = $transport;
50 4
        $this->hostname = $hostname;
51 4
        $this->emailOverride = $emailOverride;
52 4
        $this->viewRendered = $viewRenderer;
53 4
    }
54
55 2
    public function queueRegister(User $user): Message
56
    {
57 2
        $subject = 'Demande de création de compte Ichtus';
58
        $mailParams = [
59 2
            'token' => $user->createToken(),
60
        ];
61
62 2
        $message = $this->createMessage($user, $user->getEmail(), $subject, MessageTypeType::REGISTER, new ViewModel($mailParams));
0 ignored issues
show
Bug introduced by
It seems like $user->getEmail() can also be of type null; however, parameter $email of Application\Service\Mailer::createMessage() 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

62
        $message = $this->createMessage($user, /** @scrutinizer ignore-type */ $user->getEmail(), $subject, MessageTypeType::REGISTER, new ViewModel($mailParams));
Loading history...
63
64 2
        return $message;
65
    }
66
67
    /**
68
     * Queue a reset password email to specified user
69
     *
70
     * @param User $user The user for which a password reset will be done
71
     * @param string $email the addresse to send the email to. Might be different than the user's email
72
     *
73
     * @return Message
74
     */
75 3
    public function queueResetPassword(User $user, string $email): Message
76
    {
77 3
        $user->createToken();
78
79 3
        $subject = 'Demande de modification de mot de passe';
80
        $mailParams = [
81 3
            'token' => $user->createToken(),
82
        ];
83
84 3
        $message = $this->createMessage($user, $email, $subject, MessageTypeType::RESET_PASSWORD, new ViewModel($mailParams));
85
86 3
        return $message;
87
    }
88
89
    /**
90
     * Create a message by rendering the template
91
     *
92
     * @param null|User $user
93
     * @param string $email
94
     * @param string $subject
95
     * @param string $type
96
     * @param ViewModel $model
97
     *
98
     * @return Message
99
     */
100 5
    private function createMessage(?User $user, string $email, string $subject, string $type, ViewModel $model): Message
101
    {
102
        // First render the view
103 5
        $serverUrl = 'https://' . $this->hostname;
104 5
        $model->setTemplate(str_replace('_', '-', $type));
105 5
        $model->setVariable('email', $email);
106 5
        $model->setVariable('user', $user);
107 5
        $model->setVariable('serverUrl', $serverUrl);
108 5
        $partialContent = $this->viewRendered->render($model);
109
110
        // Then inject it into layout
111 5
        $layoutModel = new ViewModel([$model->captureTo() => $partialContent]);
112 5
        $layoutModel->setTemplate('layout');
113 5
        $layoutModel->setVariable('subject', $subject);
114 5
        $layoutModel->setVariable('user', $user);
115 5
        $layoutModel->setVariable('serverUrl', $serverUrl);
116 5
        $layoutModel->setVariable('hostname', $this->hostname);
117 5
        $content = $this->viewRendered->render($layoutModel);
118
119 5
        $message = new Message();
120 5
        $message->setType($type);
121 5
        $message->setRecipient($user);
122 5
        $message->setSubject($subject);
123 5
        $message->setBody($content);
124 5
        $message->setEmail($email);
125 5
        $this->entityManager->persist($message);
126
127 5
        return $message;
128
    }
129
130
    /**
131
     * Send a message asynchronously in a separate process.
132
     *
133
     * This should be the preferred way to send a message, unless if we are the cron.
134
     *
135
     * @param Message $message
136
     */
137 3
    public function sendMessageAsync(Message $message): void
138
    {
139
        // Be sure we have an ID before "forking" process
140 3
        if ($message->getId() === null) {
0 ignored issues
show
introduced by
The condition $message->getId() === null is always false.
Loading history...
141 3
            _em()->flush();
142
        }
143
144 3
        $dispatcher = realpath('bin/send-message.php');
145 3
        $cmd = $dispatcher . ' ' . $message->getId() . ' > /dev/null 2>&1 &';
146 3
        exec($cmd);
147 3
    }
148
149
    /**
150
     * Send a message
151
     *
152
     * @param Message $message
153
     */
154 1
    public function sendMessage(Message $message): void
155
    {
156 1
        $mailMessage = $this->modelMessageToMailMessage($message);
157
158 1
        $email = $message->getEmail();
159 1
        $overriddenBy = '';
160 1
        if ($this->emailOverride) {
161 1
            $email = $this->emailOverride;
162 1
            $overriddenBy = ' overridden by ' . $email;
163
        }
164
165 1
        $recipientName = $message->getRecipient() ? $message->getRecipient()->getName() : null;
166 1
        if ($email) {
167 1
            $mailMessage->addTo($email, $recipientName);
168 1
            $this->transport->send($mailMessage);
169
        }
170
171 1
        $message->setDateSent(new Chronos());
172 1
        $this->entityManager->flush();
173
174 1
        echo 'email sent to: ' . $message->getEmail() . "\t" . $overriddenBy . "\t" . $message->getSubject() . PHP_EOL;
175 1
    }
176
177
    /**
178
     * Convert our model message to a mail message
179
     *
180
     * @param Message $message
181
     *
182
     * @return Mail\Message
183
     */
184 1
    private function modelMessageToMailMessage(Message $message): Mail\Message
185
    {
186
        // set Mime type html
187 1
        $htmlPart = new MimePart($message->getBody());
188 1
        $htmlPart->type = 'text/html';
189 1
        $body = new MimeMessage();
190 1
        $body->setParts([$htmlPart]);
191
192 1
        $message = new Mail\Message();
193 1
        $message->setSubject($message->getSubject());
194 1
        $message->setBody($body);
195 1
        $message->setFrom('noreply@' . $this->hostname, 'Ichtus');
196
197 1
        return $message;
198
    }
199
200
    /**
201
     * Send all messages that are not sent yet
202
     */
203
    public function sendAllMessages(): void
204
    {
205
        $messages = $this->entityManager->getRepository(Message::class)->getAllMessageToSend();
206
        foreach ($messages as $message) {
207
            $this->sendMessage($message);
208
        }
209
    }
210
}
211