Passed
Push — 6.4 ( b2f05b...7c0c3d )
by Christian
12:48 queued 13s
created

MailAttachmentsBuilder   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 75
c 1
b 0
f 0
dl 0
loc 181
rs 10
wmc 19

6 Methods

Rating   Name   Duplication   Size   Complexity  
B buildAttachments() 0 52 11
A __construct() 0 14 1
A mappingAttachments() 0 18 3
A buildOrderAttachments() 0 11 1
A mappingAttachmentsInfo() 0 15 2
A getLatestDocumentsOfTypes() 0 20 1
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Content\Mail\Service;
4
5
use Doctrine\DBAL\Connection;
6
use Shopware\Core\Checkout\Document\DocumentCollection;
7
use Shopware\Core\Checkout\Document\DocumentService;
8
use Shopware\Core\Checkout\Document\Service\DocumentGenerator;
9
use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
10
use Shopware\Core\Content\MailTemplate\Subscriber\MailSendSubscriberConfig;
11
use Shopware\Core\Content\Media\MediaCollection;
12
use Shopware\Core\Content\Media\MediaEntity;
13
use Shopware\Core\Content\Media\MediaService;
14
use Shopware\Core\Framework\Context;
15
use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\FetchModeHelper;
16
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
17
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
18
use Shopware\Core\Framework\Feature;
19
use Shopware\Core\Framework\Uuid\Uuid;
20
21
/**
22
 * @internal
23
 *
24
 * @phpstan-type MailAttachments array<int, array{id?: string, content: string, fileName: string, mimeType: string|null}>
25
 */
26
class MailAttachmentsBuilder
27
{
28
    private MediaService $mediaService;
29
30
    private EntityRepositoryInterface $mediaRepository;
31
32
    private EntityRepositoryInterface $documentRepository;
33
34
    private DocumentGenerator $documentGenerator;
35
36
    private DocumentService $documentService;
37
38
    private Connection $connection;
39
40
    public function __construct(
41
        MediaService $mediaService,
42
        EntityRepositoryInterface $mediaRepository,
43
        EntityRepositoryInterface $documentRepository,
44
        DocumentGenerator $documentGenerator,
45
        DocumentService $documentService,
46
        Connection $connection
47
    ) {
48
        $this->mediaService = $mediaService;
49
        $this->mediaRepository = $mediaRepository;
50
        $this->documentRepository = $documentRepository;
51
        $this->documentGenerator = $documentGenerator;
52
        $this->documentService = $documentService;
53
        $this->connection = $connection;
54
    }
55
56
    /**
57
     * @param array<string, mixed> $eventConfig
58
     *
59
     * @return MailAttachments
60
     */
61
    public function buildAttachments(
62
        Context $context,
63
        MailTemplateEntity $mailTemplate,
64
        MailSendSubscriberConfig $extensions,
65
        array $eventConfig,
66
        ?string $orderId
67
    ): array {
68
        $attachments = [];
69
70
        foreach ($mailTemplate->getMedia() ?? [] as $mailTemplateMedia) {
71
            if ($mailTemplateMedia->getMedia() === null || $mailTemplateMedia->getLanguageId() !== $context->getLanguageId()) {
72
                continue;
73
            }
74
75
            $attachments[] = $this->mediaService->getAttachment(
76
                $mailTemplateMedia->getMedia(),
77
                $context
78
            );
79
        }
80
81
        $documentIds = $extensions->getDocumentIds();
82
83
        if (!empty($eventConfig['documentTypeIds']) && \is_array($eventConfig['documentTypeIds']) && $orderId) {
84
            $latestDocuments = $this->getLatestDocumentsOfTypes($orderId, $eventConfig['documentTypeIds']);
85
86
            $documentIds = array_unique(array_merge($documentIds, $latestDocuments));
87
        }
88
89
        if (!empty($documentIds)) {
90
            $extensions->setDocumentIds($documentIds);
91
            if (Feature::isActive('v6.5.0.0')) {
92
                $attachments = $this->mappingAttachments($documentIds, $attachments, $context);
93
            } else {
94
                $attachments = $this->buildOrderAttachments($documentIds, $attachments, $context);
95
            }
96
        }
97
98
        if (empty($extensions->getMediaIds())) {
99
            return $attachments;
100
        }
101
102
        $criteria = new Criteria($extensions->getMediaIds());
103
        $criteria->setTitle('send-mail::load-media');
104
105
        /** @var MediaCollection<MediaEntity> $entities */
106
        $entities = $this->mediaRepository->search($criteria, $context);
107
108
        foreach ($entities as $media) {
109
            $attachments[] = $this->mediaService->getAttachment($media, $context);
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

109
            $attachments[] = $this->mediaService->getAttachment(/** @scrutinizer ignore-type */ $media, $context);
Loading history...
110
        }
111
112
        return $attachments;
113
    }
114
115
    /**
116
     * @param array<string> $documentIds
117
     * @param MailAttachments $attachments
118
     *
119
     * @return MailAttachments
120
     */
121
    private function buildOrderAttachments(array $documentIds, array $attachments, Context $context): array
122
    {
123
        $criteria = new Criteria($documentIds);
124
        $criteria->setTitle('send-mail::load-attachments');
125
        $criteria->addAssociation('documentMediaFile');
126
        $criteria->addAssociation('documentType');
127
128
        /** @var DocumentCollection $documents */
129
        $documents = $this->documentRepository->search($criteria, $context)->getEntities();
130
131
        return $this->mappingAttachmentsInfo($documents, $attachments, $context);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->mappingAtt...$attachments, $context) returns the type array|array<mixed,array<string,mixed|string>> which is incompatible with the documented return type Shopware\Core\Content\Mail\Service\MailAttachments.
Loading history...
132
    }
133
134
    /**
135
     * @param array<string> $documentTypeIds
136
     *
137
     * @return array<string>
138
     */
139
    private function getLatestDocumentsOfTypes(string $orderId, array $documentTypeIds): array
140
    {
141
        $documents = $this->connection->fetchAllAssociative(
142
            'SELECT
143
                LOWER(hex(`document`.`document_type_id`)) as doc_type,
144
                LOWER(hex(`document`.`id`)) as doc_id
145
            FROM `document`
146
            WHERE `document`.`order_id` = :orderId
147
            AND `document`.`document_type_id` IN (:documentTypeIds)
148
            ORDER BY `document`.`created_at` ASC',
149
            [
150
                'orderId' => Uuid::fromHexToBytes($orderId),
151
                'documentTypeIds' => Uuid::fromHexToBytesList($documentTypeIds),
152
            ],
153
            [
154
                'documentTypeIds' => Connection::PARAM_STR_ARRAY,
155
            ]
156
        );
157
158
        return array_column(FetchModeHelper::groupUnique($documents), 'doc_id');
159
    }
160
161
    /**
162
     * @param MailAttachments $attachments
163
     *
164
     * @return MailAttachments
165
     */
166
    private function mappingAttachmentsInfo(DocumentCollection $documents, array $attachments, Context $context): array
167
    {
168
        foreach ($documents as $document) {
169
            $documentId = $document->getId();
170
            $document = $this->documentService->getDocument($document, $context);
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

170
            $document = $this->documentService->getDocument(/** @scrutinizer ignore-type */ $document, $context);
Loading history...
171
172
            $attachments[] = [
173
                'id' => $documentId,
174
                'content' => $document->getFileBlob(),
175
                'fileName' => $document->getFilename(),
176
                'mimeType' => $document->getContentType(),
177
            ];
178
        }
179
180
        return $attachments;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $attachments returns the type array|array<mixed,array<string,mixed|string>> which is incompatible with the documented return type Shopware\Core\Content\Mail\Service\MailAttachments.
Loading history...
181
    }
182
183
    /**
184
     * @param array<string> $documentIds
185
     * @param MailAttachments $attachments
186
     *
187
     * @return MailAttachments
188
     */
189
    private function mappingAttachments(array $documentIds, array $attachments, Context $context): array
190
    {
191
        foreach ($documentIds as $documentId) {
192
            $document = $this->documentGenerator->readDocument($documentId, $context);
193
194
            if ($document === null) {
195
                continue;
196
            }
197
198
            $attachments[] = [
199
                'id' => $documentId,
200
                'content' => $document->getContent(),
201
                'fileName' => $document->getName(),
202
                'mimeType' => $document->getContentType(),
203
            ];
204
        }
205
206
        return $attachments;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $attachments returns the type array|array<mixed,array<string,string>> which is incompatible with the documented return type Shopware\Core\Content\Mail\Service\MailAttachments.
Loading history...
207
    }
208
}
209