Test Failed
Pull Request — master (#30)
by Evgeniy
02:07
created

Message::withSubject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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