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.
Completed
Push — develop ( 23c14d...945ba9 )
by Jasper
07:31
created

PayloadBuilder   B

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
wmc 50
lcom 1
cbo 8
dl 0
loc 382
ccs 171
cts 171
cp 1
rs 8.6206
c 0
b 0
f 0

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 PayloadBuilder 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 PayloadBuilder, 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 PayloadBuilder implements PayloadBuilderInterface
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 60
    public function __construct(Configuration $config, RandomNumberGenerator $randomNumberGenerator)
35
    {
36 60
        $this->config                = clone $config;
37 60
        $this->randomNumberGenerator = $randomNumberGenerator;
38 60
    }
39
40
    /**
41
     * @param Swift_Mime_Message $message
42
     *
43
     * @return array
44
     */
45 57
    public function buildPayload(Swift_Mime_Message $message)
46
    {
47
        $payload = [
48 57
            'recipients' => $this->buildRecipients($message),
49 54
            'content'    => $this->buildContent($message),
50 18
        ];
51
52 54
        if ($campaignId = $this->buildCampaignId($message)) {
53 3
            $payload['campaign_id'] = $campaignId;
54 1
        }
55
56 54
        if ($metadata = $this->buildMetadata($message)) {
57 3
            $payload['metadata'] = $metadata;
58 1
        }
59
60 54
        if ($substitutionData = $this->buildSubstitutionData($message)) {
61 3
            $payload['substitution_data'] = $substitutionData;
62 1
        }
63
64 54
        if ($options = $this->buildOptions($message)) {
65 54
            $payload['options'] = $options;
66 18
        }
67
68 54
        return $payload;
69
    }
70
71
    /**
72
     * @param Swift_Mime_Message $message
73
     *
74
     * @return array
75
     * @throws Exception
76
     */
77 57
    private function buildRecipients(Swift_Mime_Message $message)
78
    {
79 57
        $tos = array_merge((array) $message->getTo(), (array) $message->getCc());
80 57
        $bcc = (array) $message->getBcc();
81
82 57
        if (count($tos) === 0) {
83 3
            throw new Exception('Cannot send message without a recipient address');
84
        }
85
86 54
        $tags             = [];
87 54
        $metadata         = [];
88 54
        $substitutionData = [];
89
90 54
        if ($message instanceof Message) {
91 15
            $tags             = $message->getPerRecipientTags();
92 15
            $metadata         = $message->getPerRecipientMetadata();
93 15
            $substitutionData = $message->getPerRecipientSubstitutionData();
94 5
        }
95
96 54
        $recipients = [];
97
98 54
        foreach ($tos as $email => $name) {
99 54
            $recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData);
100 18
        }
101
102 54
        $originalEmail = current($recipients)['address']['email'];
103
104 54
        foreach ($bcc as $email => $name) {
105 27
            $recipients[] = $this->buildRecipient($email, $name, $tags, $metadata, $substitutionData, $originalEmail);
106 18
        }
107
108 54
        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 54
    private function buildRecipient(
122
        $email,
123
        $name,
124
        array $tags,
125
        array $metadata,
126
        array $substitutionData,
127
        $originalEmail = ''
128
    ) {
129 54
        $recipient = ['address' => ['email' => $this->overrideRecipient($email)]];
130
131 54
        if ($name) {
132 21
            $recipient['address']['name'] = $name;
133 7
        }
134
135 54
        if ($originalEmail) {
136 27
            $recipient['address']['header_to'] = $originalEmail;
137 9
        }
138
139 54
        if (isset($tags[$email])) {
140 9
            $recipient['tags'] = $tags[$email];
141 3
        }
142
143 54
        if (isset($metadata[$email])) {
144 9
            $recipient['metadata'] = $metadata[$email];
145 3
        }
146
147 54
        if (isset($substitutionData[$email])) {
148 9
            $recipient['substitution_data'] = $substitutionData[$email];
149 3
        }
150
151 54
        return $recipient;
152
    }
153
154
    /**
155
     * @param Swift_Mime_Message $message
156
     *
157
     * @return array
158
     */
159 54
    private function buildContent(Swift_Mime_Message $message)
160
    {
161
        $content = [
162 54
            'subject' => $this->convertAsteriskPipeToCurlyBraces($message->getSubject()),
163 54
            'from'    => $this->buildFrom($message),
164 18
        ];
165
166 54
        if ($message->getReplyTo()) {
167 27
            $content['reply_to'] = key($message->getReplyTo());
168 9
        }
169
170 54
        $contentMap = ['text/html' => 'html', 'text/plain' => 'text'];
171
172 54
        $contentType = $this->readUserContentType($message);
173 54
        if (isset($contentMap[$contentType])) {
174 54
            $content[$contentMap[$contentType]] = $this->convertAsteriskPipeToCurlyBraces($message->getBody());
175 18
        }
176
177 54
        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 18
        }
187
188 54
        if ($headers = $this->buildHeaders($message)) {
189 3
            $content['headers'] = $headers;
190 1
        }
191
192 54
        if ($attachments = $this->buildAttachments($message)) {
193 3
            $content['attachments'] = $attachments;
194 1
        }
195
196 54
        return $content;
197
    }
198
199
    /**
200
     * @param Swift_Mime_Message $message
201
     *
202
     * @return array|string
203
     */
204 54
    private function buildFrom(Swift_Mime_Message $message)
205
    {
206 54
        $from = $message->getFrom();
207
208 54
        if (current($from)) {
209 21
            return ['email' => key($from), 'name' => current($from)];
210
        }
211
212 33
        return key($from);
213
    }
214
215
    /**
216
     * @param Swift_Mime_Message $message
217
     *
218
     * @return array
219
     */
220 54
    private function buildHeaders(Swift_Mime_Message $message)
221
    {
222 54
        $headers = [];
223
        $filter  = [
224 54
            'Bcc',
225 18
            'Cc',
226 18
            'Content-Transfer-Encoding',
227 18
            'Content-Type',
228 18
            'Date',
229 18
            'DKIM-Signature',
230 18
            'DomainKey-Signature',
231 18
            'From',
232 18
            'Message-ID',
233 18
            'MIME-Version',
234 18
            'Received',
235 18
            'Reply-To',
236 18
            'Return-Path',
237 18
            'Sender',
238 18
            'Subject',
239 18
            'To',
240 18
        ];
241
242
        /** @var Swift_Mime_Header $header */
243 54
        foreach ($message->getHeaders()->getAll() as $header) {
244 54
            if (in_array($header->getFieldName(), $filter, true)) {
245 54
                continue;
246
            }
247
248 3
            $headers[] = trim($header->toString());
249 18
        }
250
251 54
        return $headers;
252
    }
253
254
    /**
255
     * @param Swift_Mime_Message $message
256
     *
257
     * @return array
258
     */
259 54
    private function buildAttachments(Swift_Mime_Message $message)
260
    {
261 54
        $attachments = [];
262
263 54
        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 18
        }
272
273 54
        return $attachments;
274
    }
275
276
    /**
277
     * @param Swift_Mime_Message $message
278
     *
279
     * @return string
280
     */
281 54
    private function buildCampaignId(Swift_Mime_Message $message)
282
    {
283 54
        if (!($message instanceof Message)) {
284 39
            return '';
285
        }
286
287 15
        return $message->getCampaignId();
288
    }
289
290
    /**
291
     * @param Swift_Mime_Message $message
292
     *
293
     * @return array
294
     */
295 54
    private function buildMetadata(Swift_Mime_Message $message)
296
    {
297 54
        if (!($message instanceof Message)) {
298 39
            return [];
299
        }
300
301 15
        return $message->getMetadata();
302
    }
303
304
    /**
305
     * @param Swift_Mime_Message $message
306
     *
307
     * @return array
308
     */
309 54
    private function buildSubstitutionData(Swift_Mime_Message $message)
310
    {
311 54
        if (!($message instanceof Message)) {
312 39
            return [];
313
        }
314
315 15
        return $message->getSubstitutionData();
316
    }
317
318
    /**
319
     * @param Swift_Mime_Message $message
320
     *
321
     * @return array
322
     */
323 54
    private function buildOptions(Swift_Mime_Message $message)
324
    {
325 54
        $options = $this->config->getOptions();
326
327 54
        if (!$this->configuredIpPoolShouldBeUsed()) {
328 6
            unset($options[Configuration::OPT_IP_POOL]);
329 2
        }
330
331 54
        if ($message instanceof Message) {
332 15
            $options = array_merge($options, $message->getOptions());
333 5
        }
334
335 54
        return $options;
336
    }
337
338
    /**
339
     * Convert *|foo|* to {{foo}}
340
     *
341
     * @param string
342
     *
343
     * @return string
344
     */
345 54
    private function convertAsteriskPipeToCurlyBraces($content)
346
    {
347 54
        return preg_replace('/\*\|(.+?)\|\*/', '{{\1}}', $content);
348
    }
349
350
    /**
351
     * @param Swift_Mime_Message $message
352
     *
353
     * @return string
354
     */
355 54
    private function readUserContentType(Swift_Mime_Message $message)
356
    {
357 54
        $ro = new \ReflectionObject($message);
358 54
        $rp = $ro->getProperty('_userContentType');
359 54
        $rp->setAccessible(true);
360 54
        return (string) $rp->getValue($message);
361
    }
362
363
    /**
364
     * @param string $email
365
     *
366
     * @return string
367
     */
368 54
    private function overrideRecipient($email)
369
    {
370 54
        if (!$this->config->overrideRecipients()) {
371 42
            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), '-');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
380
381 6
        return sprintf('%s+%s@%s', $userPart, $reformattedEmail, $domainPart);
382
    }
383
384
    /**
385
     * @return bool
386
     */
387 54
    private function configuredIpPoolShouldBeUsed()
388
    {
389 54
        if ($this->config->getIpPoolProbability() === 0.0) {
390 3
            return false;
391
        }
392
393 51
        if ($this->config->getIpPoolProbability() === 1.0) {
394 45
            return true;
395
        }
396
397 6
        return ($this->randomNumberGenerator->generate() <= $this->config->getIpPoolProbability());
398
    }
399
}
400