Passed
Push — master ( 29ad4f...edce1c )
by Alexander
02:26
created

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