Passed
Push — master ( 77c902...b2ee30 )
by Alexander
02:49
created

Message::withAddedHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mailer\Symfony;
6
7
use DateTimeImmutable;
8
use DateTimeInterface;
9
use Symfony\Component\Mime\Address;
10
use Symfony\Component\Mime\Email;
11
use Symfony\Component\Mime\Header\HeaderInterface;
12
use Throwable;
13
use Yiisoft\Mailer\File;
14
use Yiisoft\Mailer\MessageInterface;
15
16
use function is_string;
17
18
/**
19
 * Message implements a message class based on Symfony Mailer.
20
 *
21
 * @see https://symfony.com/doc/current/mailer.html#creating-sending-messages
22
 * @see Mailer
23
 */
24
final class Message implements MessageInterface
25
{
26
    private Email $email;
27
    private ?Throwable $error = null;
28
    private string $charset = 'utf-8';
29
30 57
    public function __construct()
31
    {
32 57
        $this->email = new Email();
33 57
    }
34
35 56
    public function __clone()
36
    {
37 56
        $this->email = clone $this->email;
38 56
    }
39
40 3
    public function getCharset(): string
41
    {
42 3
        return $this->charset;
43
    }
44
45 5
    public function withCharset(string $charset): self
46
    {
47 5
        $new = clone $this;
48 5
        $new->charset = $charset;
49 5
        return $new;
50
    }
51
52 5
    public function getFrom()
53
    {
54 5
        return $this->convertAddressesToStrings($this->email->getFrom());
55
    }
56
57 21
    public function withFrom($from): self
58
    {
59 21
        $new = clone $this;
60 21
        $new->email->from(...$this->convertStringsToAddresses($from));
61 21
        return $new;
62
    }
63
64 5
    public function getTo()
65
    {
66 5
        return $this->convertAddressesToStrings($this->email->getTo());
67
    }
68
69 21
    public function withTo($to): self
70
    {
71 21
        $new = clone $this;
72 21
        $new->email->to(...$this->convertStringsToAddresses($to));
73 21
        return $new;
74
    }
75
76 5
    public function getReplyTo()
77
    {
78 5
        return $this->convertAddressesToStrings($this->email->getReplyTo());
79
    }
80
81 6
    public function withReplyTo($replyTo): self
82
    {
83 6
        $new = clone $this;
84 6
        $new->email->replyTo(...$this->convertStringsToAddresses($replyTo));
85 6
        return $new;
86
    }
87
88 5
    public function getCc()
89
    {
90 5
        return $this->convertAddressesToStrings($this->email->getCc());
91
    }
92
93 6
    public function withCc($cc): self
94
    {
95 6
        $new = clone $this;
96 6
        $new->email->cc(...$this->convertStringsToAddresses($cc));
97 6
        return $new;
98
    }
99
100 5
    public function getBcc()
101
    {
102 5
        return $this->convertAddressesToStrings($this->email->getBcc());
103
    }
104
105 5
    public function withBcc($bcc): self
106
    {
107 5
        $new = clone $this;
108 5
        $new->email->bcc(...$this->convertStringsToAddresses($bcc));
109 5
        return $new;
110
    }
111
112 2
    public function getSubject(): string
113
    {
114 2
        return (string) $this->email->getSubject();
115
    }
116
117 16
    public function withSubject(string $subject): self
118
    {
119 16
        $new = clone $this;
120 16
        $new->email->subject($subject);
121 16
        return $new;
122
    }
123
124 4
    public function getTextBody(): string
125
    {
126 4
        return (string) $this->email->getTextBody();
127
    }
128
129 16
    public function withTextBody(string $text): self
130
    {
131 16
        $new = clone $this;
132 16
        $new->email->text($text, $this->charset);
133 16
        return $new;
134
    }
135
136 2
    public function getHtmlBody(): string
137
    {
138 2
        return (string) $this->email->getHtmlBody();
139
    }
140
141 6
    public function withHtmlBody(string $html): self
142
    {
143 6
        $new = clone $this;
144 6
        $new->email->html($html, $this->charset);
145 6
        return $new;
146
    }
147
148 3
    public function withAttached(File $file): self
149
    {
150 3
        $new = clone $this;
151
152 3
        $file->path() === null
153 2
            ? $new->email->attach((string) $file->content(), $file->name(), $file->contentType())
154 1
            : $new->email->attachFromPath($file->path(), $file->name(), $file->contentType())
155
        ;
156
157 3
        return $new;
158
    }
159
160 3
    public function withEmbedded(File $file): self
161
    {
162 3
        $new = clone $this;
163
164 3
        $file->path() === null
165 2
            ? $new->email->embed((string) $file->content(), $file->name(), $file->contentType())
166 1
            : $new->email->embedFromPath($file->path(), $file->name(), $file->contentType())
167
        ;
168
169 3
        return $new;
170
    }
171
172 6
    public function getHeader(string $name): array
173
    {
174 6
        $headers = $this->email->getHeaders();
175
176 6
        if (!$headers->has($name)) {
177 1
            return [];
178
        }
179
180 5
        $values = [];
181
182
        /** @var HeaderInterface $header */
183 5
        foreach ($headers->all($name) as $header) {
184 5
            $values[] = $header->getBodyAsString();
185
        }
186
187 5
        return $values;
188
    }
189
190 2
    public function withAddedHeader(string $name, string $value): self
191
    {
192 2
        $new = clone $this;
193 2
        $new->email->getHeaders()->addTextHeader($name, $value);
194 2
        return $new;
195
    }
196
197 6
    public function withHeader(string $name, $value): self
198
    {
199 6
        $new = clone $this;
200 6
        $headers = $new->email->getHeaders();
201
202 6
        if ($headers->has($name)) {
203 1
            $headers->remove($name);
204
        }
205
206 6
        foreach ((array) $value as $v) {
207 6
            $headers->addTextHeader($name, $v);
208
        }
209
210 6
        return $new;
211
    }
212
213 3
    public function withHeaders(array $headers): self
214
    {
215 3
        $new = clone $this;
216
217 3
        foreach ($headers as $name => $value) {
218 2
            $new = $new->withHeader($name, $value);
219
        }
220
221 3
        return $new;
222
    }
223
224 2
    public function getError(): ?Throwable
225
    {
226 2
        return $this->error;
227
    }
228
229 2
    public function withError(Throwable $e): self
230
    {
231 2
        $new = clone $this;
232 2
        $new->error = $e;
233 2
        return $new;
234
    }
235
236 5
    public function __toString(): string
237
    {
238 5
        return $this->email->toString();
239
    }
240
241
    /**
242
     * Returns a Symfony email instance.
243
     *
244
     * @return Email Symfony email instance.
245
     */
246 12
    public function getSymfonyEmail(): Email
247
    {
248 12
        return $this->email;
249
    }
250
251
    /**
252
     * Returns the date when the message was sent, or null if it was not set.
253
     *
254
     * @return DateTimeImmutable|null The date when the message was sent.
255
     */
256 2
    public function getDate(): ?DateTimeImmutable
257
    {
258 2
        return $this->email->getDate();
259
    }
260
261
    /**
262
     * Returns a new instance with the specified date when the message was sent.
263
     *
264
     * @param DateTimeInterface $date The date when the message was sent.
265
     *
266
     * @return self
267
     */
268 3
    public function withDate(DateTimeInterface $date): self
269
    {
270 3
        $new = clone $this;
271 3
        $new->email->date($date);
272 3
        return $new;
273
    }
274
275
    /**
276
     * Returns the priority of this message.
277
     *
278
     * @return int The priority value as integer in range: `1..5`,
279
     * where 1 is the highest priority and 5 is the lowest.
280
     */
281 6
    public function getPriority(): int
282
    {
283 6
        return $this->email->getPriority();
284
    }
285
286
    /**
287
     * Returns a new instance with the specified priority of this message.
288
     *
289
     * @param int $priority The priority value, should be an integer in range: `1..5`,
290
     * where 1 is the highest priority and 5 is the lowest.
291
     *
292
     * @return self
293
     */
294 7
    public function withPriority(int $priority): self
295
    {
296 7
        $new = clone $this;
297 7
        $new->email->priority($priority);
298 7
        return $new;
299
    }
300
301
    /**
302
     * Returns the return-path (the bounce address) of this message.
303
     *
304
     * @return string The bounce email address.
305
     */
306 2
    public function getReturnPath(): string
307
    {
308 2
        $returnPath = $this->email->getReturnPath();
309 2
        return $returnPath === null ? '' : $returnPath->getAddress();
310
    }
311
312
    /**
313
     * Returns a new instance with the specified return-path (the bounce address) of this message.
314
     *
315
     * @param string $address The bounce email address.
316
     *
317
     * @return self
318
     */
319 3
    public function withReturnPath(string $address): self
320
    {
321 3
        $new = clone $this;
322 3
        $new->email->returnPath($address);
323 3
        return $new;
324
    }
325
326
    /**
327
     * Returns the message actual sender email address.
328
     *
329
     * @return string The actual sender email address.
330
     */
331 2
    public function getSender(): string
332
    {
333 2
        $sender = $this->email->getSender();
334 2
        return $sender === null ? '' : $sender->getAddress();
335
    }
336
337
    /**
338
     * Returns a new instance with the specified actual sender email address.
339
     *
340
     * @param string $address The actual sender email address.
341
     *
342
     * @return self
343
     */
344 4
    public function withSender(string $address): self
345
    {
346 4
        $new = clone $this;
347 4
        $new->email->sender($address);
348 4
        return $new;
349
    }
350
351
    /**
352
     * Converts address instances to their string representations.
353
     *
354
     * @param Address[] $addresses
355
     *
356
     * @return string|array<string, string>
357
     */
358 21
    private function convertAddressesToStrings(array $addresses)
359
    {
360 21
        $strings = [];
361
362 21
        foreach ($addresses as $address) {
363 20
            $strings[$address->getAddress()] = $address->getName();
364
        }
365
366 21
        return empty($strings) ? '' : $strings;
367
    }
368
369
    /**
370
     * Converts string representations of address to their instances.
371
     *
372
     * @param string|array<int|string, string> $strings
373
     *
374
     * @return Address[]
375
     */
376 37
    private function convertStringsToAddresses($strings): array
377
    {
378 37
        if (is_string($strings)) {
379 22
            return [new Address($strings)];
380
        }
381
382 15
        $addresses = [];
383
384 15
        foreach ($strings as $address => $name) {
385 15
            if (!is_string($address)) {
386
                // email address without name
387 5
                $addresses[] = new Address($name);
388 5
                continue;
389
            }
390
391 10
            $addresses[] = new Address($address, $name);
392
        }
393
394 15
        return $addresses;
395
    }
396
}
397