Passed
Push — master ( 72b2aa...c8dd73 )
by Christian
13:52 queued 11s
created

MailFactory::createMessage()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 22
c 1
b 0
f 0
nc 9
nop 6
dl 0
loc 43
rs 8.9457
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Content\Mail\Service;
4
5
use League\Flysystem\FilesystemInterface;
6
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\ConstraintBuilder;
7
use Shopware\Core\Framework\Feature;
8
use Shopware\Core\Framework\Feature\Exception\FeatureActiveException;
9
use Shopware\Core\Framework\Feature\Exception\FeatureNotActiveException;
10
use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
11
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
12
use Symfony\Component\Mime\Email;
13
use Symfony\Component\Validator\ConstraintViolationList;
14
use Symfony\Component\Validator\Validator\ValidatorInterface;
15
16
class MailFactory extends AbstractMailFactory
17
{
18
    /**
19
     * @var ValidatorInterface
20
     */
21
    private $validator;
22
23
    /**
24
     * @var FilesystemInterface
25
     */
26
    private $filesystem;
27
28
    public function __construct(ValidatorInterface $validator, FilesystemInterface $filesystem)
29
    {
30
        $this->validator = $validator;
31
        $this->filesystem = $filesystem;
32
    }
33
34
    /**
35
     * @param array $sender     e.g. ['[email protected]' => 'Shopware AG', '[email protected]' => 'Symfony']
36
     * @param array $recipients e.g. ['[email protected]' => 'Shopware AG', '[email protected]' => 'Symfony']
37
     * @param array $contents   e.g. ['text/plain' => 'Foo', 'text/html' => '<h1>Bar</h1>']
38
     *
39
     * @deprecated tag:v6.4.0 (flag:FEATURE_NEXT_12246) method will be removed. Use createMail instead.
40
     */
41
    public function createMessage(
42
        string $subject,
43
        array $sender,
44
        array $recipients,
45
        array $contents,
46
        array $attachments,
47
        ?array $binAttachments = null
48
    ): \Swift_Message {
49
        if (Feature::isActive('FEATURE_NEXT_12246')) {
50
            throw new FeatureActiveException('FEATURE_NEXT_12246');
51
        }
52
53
        $this->assertValidAddresses(array_keys($recipients));
54
55
        $message = (new \Swift_Message($subject))
56
            ->setFrom($sender)
57
            ->setTo($recipients);
58
59
        foreach ($contents as $contentType => $data) {
60
            $message->addPart($data, $contentType);
61
        }
62
63
        foreach ($attachments as $url) {
64
            $attachment = new \Swift_Attachment(
65
                $this->filesystem->read($url),
0 ignored issues
show
Bug introduced by
It seems like $this->filesystem->read($url) can also be of type false; however, parameter $data of Swift_Attachment::__construct() does only seem to accept Swift_OutputByteStream|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

65
                /** @scrutinizer ignore-type */ $this->filesystem->read($url),
Loading history...
66
                basename($url),
67
                $this->filesystem->getMimetype($url)
0 ignored issues
show
Bug introduced by
It seems like $this->filesystem->getMimetype($url) can also be of type false; however, parameter $contentType of Swift_Attachment::__construct() 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

67
                /** @scrutinizer ignore-type */ $this->filesystem->getMimetype($url)
Loading history...
68
            );
69
            $message->attach($attachment);
70
        }
71
72
        if (isset($binAttachments)) {
73
            foreach ($binAttachments as $binAttachment) {
74
                $attachment = new \Swift_Attachment(
75
                    $binAttachment['content'],
76
                    $binAttachment['fileName'],
77
                    $binAttachment['mimeType']
78
                );
79
                $message->attach($attachment);
80
            }
81
        }
82
83
        return $message;
84
    }
85
86
    public function create(
87
        string $subject,
88
        array $sender,
89
        array $recipients,
90
        array $contents,
91
        array $attachments,
92
        array $additionalData,
93
        ?array $binAttachments = null
94
    ): Email {
95
        if (!Feature::isActive('FEATURE_NEXT_12246')) {
96
            throw new FeatureNotActiveException('FEATURE_NEXT_12246');
97
        }
98
99
        $this->assertValidAddresses(array_keys($recipients));
100
101
        $mail = (new Email())
102
            ->subject($subject)
103
            ->from(...$this->formatMailAddresses($sender))
104
            ->to(...$this->formatMailAddresses($recipients));
105
106
        foreach ($contents as $contentType => $data) {
107
            if ($contentType === 'text/html') {
108
                $mail->html($data);
109
            } else {
110
                $mail->text($data);
111
            }
112
        }
113
114
        foreach ($attachments as $url) {
115
            $mail->embed($this->filesystem->read($url) ?: '', basename($url), $this->filesystem->getMimetype($url) ?: null);
116
        }
117
118
        if (isset($binAttachments)) {
119
            foreach ($binAttachments as $binAttachment) {
120
                $mail->embed(
121
                    $binAttachment['content'],
122
                    $binAttachment['fileName'],
123
                    $binAttachment['mimeType']
124
                );
125
            }
126
        }
127
128
        foreach ($additionalData as $key => $value) {
129
            switch ($key) {
130
                case 'recipientsCc':
131
                    $mail->addCc(...$this->formatMailAddresses([$value => $value]));
132
133
                    break;
134
                case 'recipientsBcc':
135
                    $mail->addBcc(...$this->formatMailAddresses([$value => $value]));
136
137
                    break;
138
                case 'replyTo':
139
                    $mail->addReplyTo(...$this->formatMailAddresses([$value => $value]));
140
141
                    break;
142
                case 'returnPath':
143
                    $mail->returnPath(...$this->formatMailAddresses([$value => $value]));
0 ignored issues
show
Bug introduced by
$this->formatMailAddress...rray($value => $value)) is expanded, but the parameter $address of Symfony\Component\Mime\Email::returnPath() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
                    $mail->returnPath(/** @scrutinizer ignore-type */ ...$this->formatMailAddresses([$value => $value]));
Loading history...
144
            }
145
        }
146
147
        return $mail;
148
    }
149
150
    public function getDecorated(): AbstractMailFactory
151
    {
152
        throw new DecorationPatternException(self::class);
153
    }
154
155
    /**
156
     * @throws ConstraintViolationException
157
     */
158
    private function assertValidAddresses(array $addresses): void
159
    {
160
        $constraints = (new ConstraintBuilder())
161
            ->isNotBlank()
162
            ->isEmail()
163
            ->getConstraints();
164
165
        $violations = new ConstraintViolationList();
166
        foreach ($addresses as $address) {
167
            $violations->addAll($this->validator->validate($address, $constraints));
168
        }
169
170
        if ($violations->count() > 0) {
171
            throw new ConstraintViolationException($violations, $addresses);
172
        }
173
    }
174
175
    private function formatMailAddresses(array $addresses): array
176
    {
177
        $formattedAddresses = [];
178
        foreach ($addresses as $mail => $name) {
179
            $formattedAddresses[] = $name . ' <' . $mail . '>';
180
        }
181
182
        return $formattedAddresses;
183
    }
184
}
185