Test Failed
Pull Request — master (#30)
by Evgeniy
08:35
created

Message::withAddedHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mailer\SwiftMailer;
6
7
use Swift_Attachment;
8
use Swift_EmbeddedFile;
9
use Swift_Message;
10
use Swift_Mime_MimePart;
11
use Swift_Signer;
12
use Throwable;
13
use Yiisoft\Mailer\MessageInterface;
14
15
use function reset;
16
17
/**
18
 * Message implements a message class based on SwiftMailer.
19
 *
20
 * @see https://swiftmailer.symfony.com/docs/messages.html
21
 * @see Mailer
22
 */
23
final class Message implements MessageInterface
24
{
25
    private Swift_Message $swiftMessage;
26 7
    private ?Throwable $error = null;
27
28 7
    public function __construct()
29
    {
30
        $this->swiftMessage = new Swift_Message();
31 51
    }
32
33 51
    public function __clone()
34 51
    {
35
        $this->swiftMessage = clone $this->swiftMessage;
36
    }
37
38
    /**
39
     * @return Swift_Message Swift message instance.
40 1
     */
41
    public function getSwiftMessage(): Swift_Message
42 1
    {
43 1
        return $this->swiftMessage;
44
    }
45 2
46
    public function getCharset(): string
47 2
    {
48
        return $this->swiftMessage->getCharset();
49
    }
50 4
51
    public function withCharset(string $charset): self
52 4
    {
53
        $new = clone $this;
54 4
        $new->swiftMessage->setCharset($charset);
55
        return $new;
56
    }
57 4
58
    public function getFrom()
59 4
    {
60
        return $this->swiftMessage->getFrom() ?? '';
61
    }
62 10
63
    public function withFrom($from): self
64 10
    {
65
        $new = clone $this;
66 10
        $new->swiftMessage->setFrom($from);
67
        return $new;
68
    }
69 4
70
    public function getTo()
71 4
    {
72
        return $this->swiftMessage->getTo() ?? '';
73
    }
74 5
75
    public function withTo($to): self
76 5
    {
77
        $new = clone $this;
78 5
        $new->swiftMessage->setTo($to);
79
        return $new;
80
    }
81 6
82
    public function getReplyTo()
83 6
    {
84
        return $this->swiftMessage->getReplyTo() ?? '';
85
    }
86 11
87
    public function withReplyTo($replyTo): self
88 11
    {
89
        $new = clone $this;
90 11
        $new->swiftMessage->setReplyTo($replyTo);
91
        return $new;
92
    }
93 4
94
    public function getCc()
95 4
    {
96
        return $this->swiftMessage->getCc() ?? '';
97
    }
98 5
99
    public function withCc($cc): self
100 5
    {
101
        $new = clone $this;
102 5
        $new->swiftMessage->setCc($cc);
103
        return $new;
104
    }
105 4
106
    public function getBcc()
107 4
    {
108
        return $this->swiftMessage->getBcc() ?? '';
109
    }
110 5
111
    public function withBcc($bcc): self
112 5
    {
113
        $new = clone $this;
114 5
        $new->swiftMessage->setBcc($bcc);
115
        return $new;
116
    }
117 3
118
    public function getSubject(): string
119 3
    {
120
        return (string) $this->swiftMessage->getSubject() ?? '';
121
    }
122 8
123
    public function withSubject(string $subject): self
124 8
    {
125
        $new = clone $this;
126 8
        $new->swiftMessage->setSubject($subject);
127
        return $new;
128
    }
129 1
130
    public function getTextBody(): string
131 1
    {
132
        return $this->swiftMessage->getBody() ?? '';
133
    }
134 6
135
    public function withTextBody(string $text): self
136 6
    {
137
        $new = clone $this;
138 6
        $new->setBody($text, 'text/plain');
139
        return $new;
140
    }
141 2
142
    public function getHtmlBody(): string
143 2
    {
144
        return $this->swiftMessage->getBody() ?? '';
145
    }
146 4
147
    public function withHtmlBody(string $html): self
148 4
    {
149
        $new = clone $this;
150 4
        $new->setBody($html, 'text/html');
151
        return $new;
152
    }
153
154
    public function withAttached(string $fileName, array $options = []): self
155
    {
156
        $attachment = Swift_Attachment::fromPath($fileName);
157
158
        if (!empty($options['fileName'])) {
159
            $attachment->setFilename($options['fileName']);
160
        }
161 8
162
        if (!empty($options['contentType'])) {
163 8
            $attachment->setContentType($options['contentType']);
164 8
        }
165 8
166 8
        $new = clone $this;
167 8
        $new->swiftMessage->attach($attachment);
168 8
        return $new;
169 8
    }
170 1
171
    public function withAttachedContent(string $content, array $options = []): self
172
    {
173
        $attachment = new Swift_Attachment($content);
174
175 1
        if (!empty($options['fileName'])) {
176 1
            $attachment->setFilename($options['fileName']);
177 1
        }
178 1
179 1
        if (!empty($options['contentType'])) {
180
            $attachment->setContentType($options['contentType']);
181
        }
182
183 8
        $new = clone $this;
184 1
        $new->swiftMessage->attach($attachment);
185 1
        return $new;
186 1
    }
187
188 8
    public function embed(string $fileName, array $options = []): string
189
    {
190
        $embedFile = Swift_EmbeddedFile::fromPath($fileName);
191 3
192 3
        if (!empty($options['fileName'])) {
193 1
            $embedFile->setFilename($options['fileName']);
194
        }
195 2
196 2
        if (!empty($options['contentType'])) {
197 2
            $embedFile->setContentType($options['contentType']);
198 2
        }
199
200
        $this->swiftMessage = clone $this->swiftMessage;
201 8
        return $this->swiftMessage->embed($embedFile);
202
    }
203 1
204
    public function embedContent(string $content, array $options = []): string
205 1
    {
206 1
        $embedFile = new Swift_EmbeddedFile($content);
207 1
208
        if (!empty($options['fileName'])) {
209 1
            $embedFile->setFilename($options['fileName']);
210 1
        }
211
212 1
        if (!empty($options['contentType'])) {
213
            $embedFile->setContentType($options['contentType']);
214 1
        }
215
216
        $this->swiftMessage = clone $this->swiftMessage;
217 1
        return $this->swiftMessage->embed($embedFile);
218
    }
219 1
220 1
    public function getHeader(string $name): array
221 1
    {
222
        $headerSet = $this->swiftMessage->getHeaders();
223 1
224 1
        if (!$headerSet->has($name)) {
225
            return [];
226 1
        }
227
228 1
        $headers = [];
229
230
        foreach ($headerSet->getAll($name) as $header) {
231
            $headers[] = $header->getValue();
232
        }
233
234
        return $headers;
235
    }
236
237
    public function withAddedHeader(string $name, string $value): self
238
    {
239
        $new = clone $this;
240
        $new->swiftMessage->getHeaders()->addTextHeader($name, $value);
241
        return $new;
242
    }
243
244
    public function withHeader(string $name, $value): self
245
    {
246
        $new = clone $this;
247
        $headerSet = $new->swiftMessage->getHeaders();
248
249
        if ($headerSet->has($name)) {
250
            $headerSet->remove($name);
251
        }
252
253
        foreach ((array) $value as $v) {
254
            $headerSet->addTextHeader($name, $v);
255
        }
256
257 3
        return $new;
258
    }
259 3
260
    public function withHeaders(array $headers): self
261
    {
262 1
        $new = clone $this;
263
264 1
        foreach ($headers as $name => $value) {
265
            $new = $new->withHeader($name, $value);
266 1
        }
267
268
        return $new;
269 3
    }
270
271 3
    public function getError(): ?Throwable
272
    {
273 3
        return $this->error;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->error also could return the type null which is incompatible with the return type mandated by Yiisoft\Mailer\MessageInterface::getError() of Throwable.
Loading history...
274 1
    }
275
276
    public function withError(Throwable $e): self
277 3
    {
278 3
        $new = clone $this;
279
        $new->error = $e;
280
        return $new;
281 3
    }
282
283
    public function __toString(): string
284 3
    {
285
        return $this->swiftMessage->toString();
286 3
    }
287 3
288 2
    /**
289
     * Returns the return-path (the bounce address) of this message.
290
     *
291 3
     * @return string The bounce email address.
292 3
     */
293 3
    public function getReturnPath(): string
294
    {
295
        return $this->swiftMessage->getReturnPath() ?? '';
296 3
    }
297
298
    /**
299 1
     * Set the return-path (the bounce address) of this message.
300
     *
301 1
     * @param string $address The bounce email address.
302 1
     *
303
     * @return self
304
     */
305 1
    public function withReturnPath(string $address): self
306
    {
307
        $new = clone $this;
308
        $new->swiftMessage->setReturnPath($address);
309
        return $new;
310
    }
311
312
    /**
313 1
     * Returns the priority of this message.
314
     *
315 1
     * @return int The priority value as integer in range: `1..5`,
316
     * where 1 is the highest priority and 5 is the lowest.
317
     */
318
    public function getPriority(): int
319
    {
320
        return (int) $this->swiftMessage->getPriority();
321
    }
322
323
    /**
324
     * Set the priority of this message.
325 2
     *
326
     * @param int $priority The priority value, should be an integer in range: `1..5`,
327 2
     * where 1 is the highest priority and 5 is the lowest.
328
     *
329 2
     * @return self
330
     */
331
    public function withPriority(int $priority): self
332
    {
333
        $new = clone $this;
334
        $new->swiftMessage->setPriority($priority);
335
        return $new;
336
    }
337
338 5
    /**
339
     * Get the addresses to which a read-receipt will be sent.
340
     *
341 5
     * @return array|string The receipt receive email addresses.
342
     */
343
    public function getReadReceiptTo()
344
    {
345
        return $this->swiftMessage->getReadReceiptTo() ?? '';
346
    }
347
348
    /**
349
     * Sets the ask for a delivery receipt from the recipient to be sent to $addresses.
350
     *
351
     * @param array|string $addresses The receipt receive email address(es).
352 6
     *
353
     * @return self
354 6
     */
355
    public function withReadReceiptTo($addresses): self
356 6
    {
357
        $new = clone $this;
358
        $new->swiftMessage->setReadReceiptTo((array) $addresses);
359
        return $new;
360
    }
361
362
    /**
363
     * Attaches signers.
364 4
     *
365
     * @param Swift_Signer[] $signers
366 4
     *
367
     * @return self
368
     */
369
    public function withAttachedSigners(array $signers): self
370
    {
371
        $new = clone $this;
372
373
        foreach ($signers as $signer) {
374
            $new->swiftMessage->attachSigner($signer);
375
        }
376 5
377
        return $new;
378 5
    }
379
380 5
    /**
381
     * Sets the message body.
382
     *
383
     * If body is already set and its content type matches given one, it will
384
     * be overridden, if content type miss match the multipart message will be composed.
385
     *
386
     * @param string $body The body content.
387
     * @param string $contentType The body content type.
388
     */
389
    private function setBody(string $body, string $contentType): void
390 2
    {
391
        $oldBody = $this->swiftMessage->getBody();
392 2
        $charset = $this->swiftMessage->getCharset();
393 2
394
        if (!empty($oldBody)) {
395
            $oldContentType = $this->swiftMessage->getContentType();
396 2
397
            if ($oldContentType === $contentType) {
398
                $this->swiftMessage->setBody($body, $contentType);
399
                return;
400
            }
401
402
            $this->swiftMessage->setBody(null);
403
            $this->swiftMessage->setContentType('');
404
            $this->swiftMessage->addPart($oldBody, $oldContentType, $charset);
405
            $this->swiftMessage->addPart($body, $contentType, $charset);
406
            return;
407
        }
408
409
        $parts = $this->swiftMessage->getChildren();
410
        $partFound = false;
411
412
        foreach ($parts as $key => $part) {
413
            if ($part instanceof Swift_Mime_MimePart) {
414
                if ($part->getContentType() === $contentType) {
415
                    $charset = $part->getCharset();
416
                    unset($parts[$key]);
417
                    $partFound = true;
418
                    break;
419
                }
420
            }
421
        }
422
423
        if (!$partFound) {
424
            $this->swiftMessage->setBody($body, $contentType);
425
            return;
426
        }
427
428
        reset($parts);
429
        $this->swiftMessage->setChildren($parts);
430
        $this->swiftMessage->addPart($body, $contentType, $charset);
431
    }
432
}
433