GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

StandardPayloadBuilder   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 382
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 382
c 0
b 0
f 0
wmc 50
lcom 1
cbo 8
ccs 171
cts 171
cp 1
rs 8.6206

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B buildPayload() 0 25 5
B buildRecipients() 0 33 5
B buildRecipient() 0 32 6
C buildContent() 0 39 8
A buildFrom() 0 10 2
B buildHeaders() 0 33 3
A buildAttachments() 0 16 3
A buildCampaignId() 0 8 2
A buildMetadata() 0 8 2
A buildSubstitutionData() 0 8 2
A buildOptions() 0 14 3
A convertAsteriskPipeToCurlyBraces() 0 4 1
A readUserContentType() 0 7 1
A overrideRecipient() 0 15 3
A configuredIpPoolShouldBeUsed() 0 12 3

How to fix   Complexity   

Complex Class

Complex classes like StandardPayloadBuilder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use StandardPayloadBuilder, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @license https://github.com/f500/swiftmailer-sparkpost/blob/master/LICENSE MIT
5
 */
6
7
namespace SwiftSparkPost;
8
9
use Swift_Attachment;
10
use Swift_Mime_Header;
11
use Swift_Mime_Message;
12
use Swift_MimePart;
13
14
/**
15
 * @copyright Future500 B.V.
16
 * @author    Jasper N. Brouwer <[email protected]>
17
 */
18
final class StandardPayloadBuilder implements PayloadBuilder
19
{
20
    /**
21
     * @var Configuration
22
     */
23
    private $config;
24
25
    /**
26
     * @var RandomNumberGenerator
27
     */
28
    private $randomNumberGenerator;
29
30
    /**
31
     * @param Configuration         $config
32
     * @param RandomNumberGenerator $randomNumberGenerator
33
     */
34 63
    public function __construct(Configuration $config, RandomNumberGenerator $randomNumberGenerator)
35
    {
36 63
        $this->config                = clone $config;
37 63
        $this->randomNumberGenerator = $randomNumberGenerator;
38 63
    }
39
40
    /**
41
     * @param Swift_Mime_Message $message
42
     *
43
     * @return array
44
     */
45 60
    public function buildPayload(Swift_Mime_Message $message)
46
    {
47
        $payload = [
48 60
            'recipients' => $this->buildRecipients($message),
49 57
            'content'    => $this->buildContent($message),
50 19
        ];
51
52 57
        if ($campaignId = $this->buildCampaignId($message)) {
53 3
            $payload['campaign_id'] = $campaignId;
54 1
        }
55
56 57
        if ($metadata = $this->buildMetadata($message)) {
57 3
            $payload['metadata'] = $metadata;
58 1
        }
59
60 57
        if ($substitutionData = $this->buildSubstitutionData($message)) {
61 3
            $payload['substitution_data'] = $substitutionData;
62 1
        }
63
64 57
        if ($options = $this->buildOptions($message)) {
65 57
            $payload['options'] = $options;
66 19
        }
67
68 57
        return $payload;
69
    }
70
71
    /**
72
     * @param Swift_Mime_Message $message
73
     *
74
     * @return array
75
     * @throws Exception
76
     */
77 60
    private function buildRecipients(Swift_Mime_Message $message)
78
    {
79 60
        $tos = array_merge((array) $message->getTo(), (array) $message->getCc());
80 60
        $bcc = (array) $message->getBcc();
81
82 60
        if (count($tos) === 0) {
83 3
            throw new Exception('Cannot send message without a recipient address');
84
        }
85
86 57
        $tags             = [];
87 57
        $metadata         = [];
88 57
        $substitutionData = [];
89
90 57
        if ($message instanceof Message) {
91 15
            $tags             = $message->getPerRecipientTags();
92 15
            $metadata         = $message->getPerRecipientMetadata();
93 15
            $substitutionData = $message->getPerRecipientSubstitutionData();
94 5
        }
95
96 57
        $recipients = [];
97
98 57
        foreach ($tos as $email => $name) {
99 57
            $recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData);
100 19
        }
101
102 57
        $originalEmail = current($recipients)['address']['email'];
103
104 57
        foreach ($bcc as $email => $name) {
105 27
            $recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData, $originalEmail);
106 19
        }
107
108 57
        return $recipients;
109
    }
110
111
    /**
112
     * @param string $email
113
     * @param string $name
114
     * @param array  $tags
115
     * @param array  $metadata
116
     * @param array  $substitutionData
117
     * @param string $originalEmail
118
     *
119
     * @return array
120
     */
121 57
    private function buildRecipient(
122
        $email,
123
        $name,
124
        array $tags,
125
        array $metadata,
126
        array $substitutionData,
127
        $originalEmail = ''
128
    ) {
129 57
        $recipient = ['address' => ['email' => $this->overrideRecipient($email)]];
130
131 57
        if ($name) {
132 21
            $recipient['address']['name'] = $name;
133 7
        }
134
135 57
        if ($originalEmail) {
136 27
            $recipient['address']['header_to'] = $originalEmail;
137 9
        }
138
139 57
        if (isset($tags[$email])) {
140 9
            $recipient['tags'] = $tags[$email];
141 3
        }
142
143 57
        if (isset($metadata[$email])) {
144 9
            $recipient['metadata'] = $metadata[$email];
145 3
        }
146
147 57
        if (isset($substitutionData[$email])) {
148 9
            $recipient['substitution_data'] = $substitutionData[$email];
149 3
        }
150
151 57
        return $recipient;
152
    }
153
154
    /**
155
     * @param Swift_Mime_Message $message
156
     *
157
     * @return array
158
     */
159 57
    private function buildContent(Swift_Mime_Message $message)
160
    {
161
        $content = [
162 57
            'subject' => $this->convertAsteriskPipeToCurlyBraces($message->getSubject()),
163 57
            'from'    => $this->buildFrom($message),
164 19
        ];
165
166 57
        if ($message->getReplyTo()) {
167 27
            $content['reply_to'] = key($message->getReplyTo());
168 9
        }
169
170 57
        $contentMap = ['text/html' => 'html', 'text/plain' => 'text'];
171
172 57
        $contentType = $this->readUserContentType($message);
173 57
        if (isset($contentMap[$contentType])) {
174 57
            $content[$contentMap[$contentType]] = $this->convertAsteriskPipeToCurlyBraces($message->getBody());
175 19
        }
176
177 57
        foreach ($message->getChildren() as $part) {
178 6
            if (!($part instanceof Swift_MimePart)) {
179 3
                continue;
180
            }
181
182 6
            $contentType = $part->getContentType();
183 6
            if (isset($contentMap[$contentType])) {
184 6
                $content[$contentMap[$contentType]] = $this->convertAsteriskPipeToCurlyBraces($part->getBody());
185 2
            }
186 19
        }
187
188 57
        if ($headers = $this->buildHeaders($message)) {
189 6
            $content['headers'] = $headers;
190 2
        }
191
192 57
        if ($attachments = $this->buildAttachments($message)) {
193 3
            $content['attachments'] = $attachments;
194 1
        }
195
196 57
        return $content;
197
    }
198
199
    /**
200
     * @param Swift_Mime_Message $message
201
     *
202
     * @return array|string
203
     */
204 57
    private function buildFrom(Swift_Mime_Message $message)
205
    {
206 57
        $from = $message->getFrom();
207
208 57
        if (current($from)) {
209 21
            return ['email' => key($from), 'name' => current($from)];
210
        }
211
212 36
        return key($from);
213
    }
214
215
    /**
216
     * @param Swift_Mime_Message $message
217
     *
218
     * @return array
219
     */
220 57
    private function buildHeaders(Swift_Mime_Message $message)
221
    {
222 57
        $headers = [];
223
        $filter  = [
224 57
            'Bcc',
225 19
            'Cc',
226 19
            'Content-Transfer-Encoding',
227 19
            'Content-Type',
228 19
            'Date',
229 19
            'DKIM-Signature',
230 19
            'DomainKey-Signature',
231 19
            'From',
232 19
            'Message-ID',
233 19
            'MIME-Version',
234 19
            'Received',
235 19
            'Reply-To',
236 19
            'Return-Path',
237 19
            'Sender',
238 19
            'Subject',
239 19
            'To',
240 19
        ];
241
242
        /** @var Swift_Mime_Header $header */
243 57
        foreach ($message->getHeaders()->getAll() as $header) {
244 57
            if (in_array($header->getFieldName(), $filter, true)) {
245 57
                continue;
246
            }
247
248 6
            $headers[trim($header->getFieldName())] = trim($header->getFieldBody());
249 19
        }
250
251 57
        return $headers;
252
    }
253
254
    /**
255
     * @param Swift_Mime_Message $message
256
     *
257
     * @return array
258
     */
259 57
    private function buildAttachments(Swift_Mime_Message $message)
260
    {
261 57
        $attachments = [];
262
263 57
        foreach ($message->getChildren() as $part) {
264 6
            if ($part instanceof Swift_Attachment) {
265 3
                $attachments[] = [
266 3
                    'type' => $part->getContentType(),
267 3
                    'name' => $part->getFilename(),
268 5
                    'data' => base64_encode($part->getBody()),
269
                ];
270 1
            }
271 19
        }
272
273 57
        return $attachments;
274
    }
275
276
    /**
277
     * @param Swift_Mime_Message $message
278
     *
279
     * @return string
280
     */
281 57
    private function buildCampaignId(Swift_Mime_Message $message)
282
    {
283 57
        if (!($message instanceof Message)) {
284 42
            return '';
285
        }
286
287 15
        return $message->getCampaignId();
288
    }
289
290
    /**
291
     * @param Swift_Mime_Message $message
292
     *
293
     * @return array
294
     */
295 57
    private function buildMetadata(Swift_Mime_Message $message)
296
    {
297 57
        if (!($message instanceof Message)) {
298 42
            return [];
299
        }
300
301 15
        return $message->getMetadata();
302
    }
303
304
    /**
305
     * @param Swift_Mime_Message $message
306
     *
307
     * @return array
308
     */
309 57
    private function buildSubstitutionData(Swift_Mime_Message $message)
310
    {
311 57
        if (!($message instanceof Message)) {
312 42
            return [];
313
        }
314
315 15
        return $message->getSubstitutionData();
316
    }
317
318
    /**
319
     * @param Swift_Mime_Message $message
320
     *
321
     * @return array
322
     */
323 57
    private function buildOptions(Swift_Mime_Message $message)
324
    {
325 57
        $options = $this->config->getOptions();
326
327 57
        if (!$this->configuredIpPoolShouldBeUsed()) {
328 6
            unset($options[Option::IP_POOL]);
329 2
        }
330
331 57
        if ($message instanceof Message) {
332 15
            $options = array_merge($options, $message->getOptions());
333 5
        }
334
335 57
        return $options;
336
    }
337
338
    /**
339
     * Convert *|foo|* to {{foo}}
340
     *
341
     * @param string
342
     *
343
     * @return string
344
     */
345 57
    private function convertAsteriskPipeToCurlyBraces($content)
346
    {
347 57
        return preg_replace('/\*\|(.+?)\|\*/', '{{\1}}', $content);
348
    }
349
350
    /**
351
     * @param Swift_Mime_Message $message
352
     *
353
     * @return string
354
     */
355 57
    private function readUserContentType(Swift_Mime_Message $message)
356
    {
357 57
        $ro = new \ReflectionObject($message);
358 57
        $rp = $ro->getProperty('_userContentType');
359 57
        $rp->setAccessible(true);
360 57
        return (string) $rp->getValue($message);
361
    }
362
363
    /**
364
     * @param string $email
365
     *
366
     * @return string
367
     */
368 57
    private function overrideRecipient($email)
369
    {
370 57
        if (!$this->config->overrideRecipients()) {
371 45
            return $email;
372
        }
373
374 12
        if (!$this->config->overrideGmailStyle()) {
375 6
            return $this->config->getRecipientOverride();
376
        }
377
378 6
        list ($userPart, $domainPart) = explode('@', $this->config->getRecipientOverride());
379 6
        $reformattedEmail = trim(preg_replace('/([^a-z0-9]+)/i', '-', $email), '-');
380
381 6
        return sprintf('%s+%s@%s', $userPart, $reformattedEmail, $domainPart);
382
    }
383
384
    /**
385
     * @return bool
386
     */
387 57
    private function configuredIpPoolShouldBeUsed()
388
    {
389 57
        if ($this->config->getIpPoolProbability() === 0.0) {
390 3
            return false;
391
        }
392
393 54
        if ($this->config->getIpPoolProbability() === 1.0) {
394 48
            return true;
395
        }
396
397 6
        return ($this->randomNumberGenerator->generate() <= $this->config->getIpPoolProbability());
398
    }
399
}
400