Passed
Push — master ( 28073e...99ed61 )
by Christian
11:34 queued 10s
created

MailSendSubscriber::getMailTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 9
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Content\MailTemplate\Subscriber;
4
5
use Shopware\Core\Checkout\Document\DocumentService;
6
use Shopware\Core\Content\MailTemplate\Exception\MailEventConfigurationException;
7
use Shopware\Core\Content\MailTemplate\Exception\SalesChannelNotFoundException;
8
use Shopware\Core\Content\MailTemplate\MailTemplateActions;
9
use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
10
use Shopware\Core\Content\MailTemplate\Service\MailServiceInterface;
11
use Shopware\Core\Content\Media\MediaService;
12
use Shopware\Core\Framework\Context;
13
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
14
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
15
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
16
use Shopware\Core\Framework\Event\BusinessEvent;
17
use Shopware\Core\Framework\Event\EventData\EventDataType;
18
use Shopware\Core\Framework\Event\MailActionInterface;
19
use Shopware\Core\Framework\Validation\DataBag\DataBag;
20
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
21
22
class MailSendSubscriber implements EventSubscriberInterface
23
{
24
    public const ACTION_NAME = MailTemplateActions::MAIL_TEMPLATE_MAIL_SEND_ACTION;
25
    public const MAIL_CONFIG_EXTENSION = 'mail-attachments';
26
27
    /**
28
     * @var MailServiceInterface
29
     */
30
    private $mailService;
31
32
    /**
33
     * @var EntityRepositoryInterface
34
     */
35
    private $mailTemplateRepository;
36
37
    /**
38
     * @var MediaService
39
     */
40
    private $mediaService;
41
42
    /**
43
     * @var EntityRepositoryInterface
44
     */
45
    private $mediaRepository;
46
47
    /**
48
     * @var DocumentService
49
     */
50
    private $documentService;
51
52
    /**
53
     * @var EntityRepositoryInterface
54
     */
55
    private $documentRepository;
56
57
    public function __construct(
58
        MailServiceInterface $mailService,
59
        EntityRepositoryInterface $mailTemplateRepository,
60
        MediaService $mediaService,
61
        EntityRepositoryInterface $mediaRepository,
62
        EntityRepositoryInterface $documentRepository,
63
        DocumentService $documentService
64
    ) {
65
        $this->mailService = $mailService;
66
        $this->mailTemplateRepository = $mailTemplateRepository;
67
        $this->mediaService = $mediaService;
68
        $this->mediaRepository = $mediaRepository;
69
        $this->documentRepository = $documentRepository;
70
        $this->documentService = $documentService;
71
    }
72
73
    public static function getSubscribedEvents(): array
74
    {
75
        return [
76
            self::ACTION_NAME => 'sendMail',
77
        ];
78
    }
79
80
    /**
81
     * @throws MailEventConfigurationException
82
     * @throws SalesChannelNotFoundException
83
     * @throws InconsistentCriteriaIdsException
84
     */
85
    public function sendMail(BusinessEvent $event): void
86
    {
87
        $mailEvent = $event->getEvent();
88
89
        $extension = $event->getContext()->getExtension(self::MAIL_CONFIG_EXTENSION);
90
        if (!$extension instanceof MailSendSubscriberConfig) {
91
            $extension = new MailSendSubscriberConfig(false, [], []);
92
        }
93
94
        if ($extension->skip()) {
95
            return;
96
        }
97
98
        if (!$mailEvent instanceof MailActionInterface) {
99
            throw new MailEventConfigurationException('Not a instance of MailActionInterface', get_class($mailEvent));
100
        }
101
102
        $config = $event->getConfig();
103
104
        if (!isset($config['mail_template_id'])) {
105
            return;
106
        }
107
108
        $mailTemplate = $this->getMailTemplate($config['mail_template_id'], $event->getContext());
109
110
        if ($mailTemplate === null) {
111
            return;
112
        }
113
114
        $data = new DataBag();
115
116
        $recipients = $mailEvent->getMailStruct()->getRecipients();
117
        if (isset($config['recipients'])) {
118
            $recipients = $config['recipients'];
119
        }
120
121
        $data->set('recipients', $recipients);
122
        $data->set('senderName', $mailTemplate->getTranslation('senderName'));
123
        $data->set('salesChannelId', $mailEvent->getSalesChannelId());
124
125
        $data->set('templateId', $mailTemplate->getId());
126
        $data->set('customFields', $mailTemplate->getCustomFields());
127
        $data->set('contentHtml', $mailTemplate->getTranslation('contentHtml'));
128
        $data->set('contentPlain', $mailTemplate->getTranslation('contentPlain'));
129
        $data->set('subject', $mailTemplate->getTranslation('subject'));
130
        $data->set('mediaIds', []);
131
132
        $attachments = $this->buildAttachments($event, $mailTemplate, $extension);
133
134
        if (!empty($attachments)) {
135
            $data->set('binAttachments', $attachments);
136
        }
137
138
        $this->mailService->send(
139
            $data->all(),
140
            $event->getContext(),
141
            $this->getTemplateData($mailEvent)
142
        );
143
    }
144
145
    private function getMailTemplate(string $id, Context $context): ?MailTemplateEntity
146
    {
147
        $criteria = new Criteria([$id]);
148
        $criteria->addAssociation('media.media');
149
        $criteria->setLimit(1);
150
151
        return $this->mailTemplateRepository
152
            ->search($criteria, $context)
153
            ->first();
154
    }
155
156
    /**
157
     * @throws MailEventConfigurationException
158
     */
159
    private function getTemplateData(MailActionInterface $event): array
160
    {
161
        $data = [];
162
        /* @var EventDataType $item */
163
        foreach (array_keys($event::getAvailableData()->toArray()) as $key) {
164
            $getter = 'get' . ucfirst($key);
165
            if (method_exists($event, $getter)) {
166
                $data[$key] = $event->$getter();
167
            } else {
168
                throw new MailEventConfigurationException('Data for ' . $key . ' not available.', get_class($event));
169
            }
170
        }
171
172
        return $data;
173
    }
174
175
    private function buildAttachments(BusinessEvent $event, MailTemplateEntity $mailTemplate, MailSendSubscriberConfig $config): array
176
    {
177
        $attachments = [];
178
179
        if ($mailTemplate->getMedia() === null) {
180
            return [];
181
        }
182
183
        if ($mailTemplate->getMedia() !== null) {
184
            foreach ($mailTemplate->getMedia() as $mailTemplateMedia) {
185
                if ($mailTemplateMedia->getMedia() === null) {
186
                    continue;
187
                }
188
                if ($mailTemplateMedia->getLanguageId() !== null && $mailTemplateMedia->getLanguageId() !== $event->getContext()->getLanguageId()) {
189
                    continue;
190
                }
191
192
                $attachments[] = $this->mediaService->getAttachment(
193
                    $mailTemplateMedia->getMedia(),
194
                    $event->getContext()
195
                );
196
            }
197
        }
198
199
        if (!empty($config->getMediaIds())) {
200
            $entities = $this->mediaRepository->search(new Criteria($config->getMediaIds()), $event->getContext());
201
202
            foreach ($entities as $media) {
203
                $attachments[] = $this->mediaService->getAttachment($media, $event->getContext());
0 ignored issues
show
Bug introduced by
$media of type array is incompatible with the type Shopware\Core\Content\Media\MediaEntity expected by parameter $media of Shopware\Core\Content\Me...ervice::getAttachment(). ( Ignorable by Annotation )

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

203
                $attachments[] = $this->mediaService->getAttachment(/** @scrutinizer ignore-type */ $media, $event->getContext());
Loading history...
204
            }
205
        }
206
207
        if (!empty($config->getDocumentIds())) {
208
            $criteria = new Criteria($config->getDocumentIds());
209
            $criteria->addAssociation('documentMediaFile');
210
            $criteria->addAssociation('documentType');
211
212
            $entities = $this->documentRepository->search($criteria, $event->getContext());
213
214
            foreach ($entities as $document) {
215
                $document = $this->documentService->getDocument($document, $event->getContext());
0 ignored issues
show
Bug introduced by
$document of type array is incompatible with the type Shopware\Core\Checkout\Document\DocumentEntity expected by parameter $document of Shopware\Core\Checkout\D...tService::getDocument(). ( Ignorable by Annotation )

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

215
                $document = $this->documentService->getDocument(/** @scrutinizer ignore-type */ $document, $event->getContext());
Loading history...
216
217
                $attachments[] = [
218
                    'content' => $document->getFileBlob(),
219
                    'fileName' => $document->getFilename(),
220
                    'mimeType' => $document->getContentType(),
221
                ];
222
            }
223
        }
224
225
        return $attachments;
226
    }
227
}
228