Completed
Push — master ( 6c2fe3...ff207a )
by Gabriel
29s
created

Mandrill::mapAttachment()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 13

Duplication

Lines 20
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 20
loc 20
ccs 0
cts 14
cp 0
rs 9.2
cc 4
eloc 13
nc 5
nop 1
crap 20
1
<?php
2
3
namespace Omnimail;
4
5
use Omnimail\Exception\EmailDeliveryException;
6
use Omnimail\Exception\Exception;
7
use Omnimail\Exception\InvalidRequestException;
8
use Psr\Log\LoggerInterface;
9
10
class Mandrill implements EmailSenderInterface
11
{
12
    private $apiKey;
13
    private $ipPool;
14
    private $logger;
15
    private $mandrill;
16
17
    /**
18
     * @param string $apiKey
19
     * @param string $ipPool
20
     * @param LoggerInterface|null $logger
21
     */
22
    public function __construct($apiKey, $ipPool = null, LoggerInterface $logger = null)
23
    {
24
        $this->apiKey = $apiKey;
25
        $this->ipPool = $ipPool;
26
        $this->logger = $logger;
27
        $this->mandrill = new \Mandrill($apiKey);
28
    }
29
30
    public function send(EmailInterface $email)
31
    {
32
        try {
33
            $from = $email->getFrom();
34
35
            $message = [
36
                'subject' => 'example subject',
37
                'from_email' => $from['email'],
38
                'to' => $this->mapEmails($email->getTos())
39
            ];
40
41
            if (!empty($from['name'])) {
42
                $message['from_name'] = $from['name'];
43
            }
44
45
            if ($email->getReplyTos()) {
46
                $message['headers'] = [
47
                    'Reply-To' => $this->mapEmailsString($email->getReplyTos())
48
                ];
49
            }
50
51
            if ($email->getCcs()) {
52
                $message['to'] = array_merge(
53
                    $message['to'],
54
                    $this->mapEmails($email->getCcs(), 'cc')
55
                );
56
            }
57
58
            if ($email->getBccs()) {
59
                $message['to'] = array_merge(
60
                    $message['to'],
61
                    $this->mapEmails($email->getBccs(), 'bcc')
62
                );
63
            }
64
65
            if ($email->getTextBody()) {
66
                $message['text'] = $email->getTextBody();
67
            }
68
69
            if ($email->getHtmlBody()) {
70
                $message['html'] = $email->getHtmlBody();
71
            }
72
73
            if ($email->getAttachments()) {
74
                $message['attachments'] = $this->mapAttachments($email->getAttachments());
75
                $message['images'] = $this->mapInlineAttachments($email->getAttachments());
76
            }
77
78
            $result = $this->mandrill->messages->send($message, false, $this->ipPool);
0 ignored issues
show
Bug introduced by
The property messages does not seem to exist in Mandrill.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
79
            if ($result && $result['status'] &&
80
                ($result['status'] === 'sent' || $result['status'] === 'queued' || $result['status'] === 'scheduled')
81
            ) {
82
                if ($this->logger) {
83
                    $this->logger->info("Email sent: '{$email->getSubject()}'", $email);
0 ignored issues
show
Documentation introduced by
$email is of type object<Omnimail\EmailInterface>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84
                }
85
            } else {
86
                if (!$result || !$result['status']) {
87
                    $result = ['status' => 'invalid'];
88
                }
89
                if (!$result || !$result['reject_reason']) {
90
                    $result = ['reject_reason' => 'Unknown'];
91
                }
92
                switch ($result['status']) {
93
                    case 'invalid':
94
                        throw new InvalidRequestException($result['reject_reason']);
95
                    case 'rejected':
96
                        throw new EmailDeliveryException($result['reject_reason']);
97
                }
98
            }
99
        } catch (Exception $e) {
100
            if ($this->logger) {
101
                $this->logger->info("Email error: '{$e->getMessage()}'", $email);
0 ignored issues
show
Documentation introduced by
$email is of type object<Omnimail\EmailInterface>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
102
            }
103
            throw $e;
104
        } catch (\Mandrill_Error $e) {
105
            if ($this->logger) {
106
                $this->logger->info("Email error: '{$e->getMessage()}'", $email);
0 ignored issues
show
Documentation introduced by
$email is of type object<Omnimail\EmailInterface>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
107
            }
108
            throw new InvalidRequestException($e->getMessage(), 601, $e);
109
        }
110
    }
111
112
    /**
113
     * @param array|null $attachments
114
     * @return array|null
115
     */
116 View Code Duplication
    private function mapAttachments(array $attachments)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
117
    {
118
        if (null === $attachments || !is_array($attachments) || !count($attachments)) {
119
            return null;
120
        }
121
122
        $finalAttachments = [];
123
        /** @var AttachmentInterface $attachment */
124
        foreach ($attachments as $attachment) {
125
            if ($attachment->getContentId()) {
126
                continue;
127
            }
128
            $finalAttachment = $this->mapAttachment($attachment);
129
            if ($finalAttachment) {
130
                $finalAttachments[] = $finalAttachment;
131
            }
132
        }
133
        return $finalAttachments;
134
    }
135
136
    /**
137
     * @param array|null $attachments
138
     * @return array|null
139
     */
140 View Code Duplication
    private function mapInlineAttachments(array $attachments)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
    {
142
        if (null === $attachments || !is_array($attachments) || !count($attachments)) {
143
            return null;
144
        }
145
146
        $finalAttachments = [];
147
        /** @var AttachmentInterface $attachment */
148
        foreach ($attachments as $attachment) {
149
            if (!$attachment->getContentId()) {
150
                continue;
151
            }
152
            $finalAttachment = $this->mapAttachment($attachment);
153
            if ($finalAttachment) {
154
                $finalAttachments[] = $finalAttachment;
155
            }
156
        }
157
        return $finalAttachments;
158
    }
159
160 View Code Duplication
    private function mapAttachment(AttachmentInterface $attachment)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
    {
162
        $finalAttachment = [
163
            'type' => $attachment->getMimeType(),
164
            'name' => $attachment->getName()
165
        ];
166
        if ($attachment->getPath()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachment->getPath() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
167
            $finalAttachment['content'] = base64_encode(file_get_contents($attachment->getPath()));
168
        } elseif ($attachment->getContent()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachment->getContent() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
169
            $finalAttachment['content'] = base64_encode($attachment->getContent());
170
        } else {
171
            return null;
172
        }
173
174
        if ($attachment->getContentId()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachment->getContentId() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
175
            $finalAttachment['name'] = $attachment->getContentId();
176
        }
177
178
        return $finalAttachment;
179
    }
180
181
    /**
182
     * @param array $emails
183
     * @param string $type
184
     * @return array
185
     */
186
    private function mapEmails(array $emails, $type = 'to')
187
    {
188
        $returnValue = [];
189
        foreach ($emails as $email) {
190
            $returnValue[] = $this->mapEmail($email, $type);
191
        }
192
        return $returnValue;
193
    }
194
195
    /**
196
     * @param array $email
197
     * @param string $type
198
     * @return array
199
     */
200 View Code Duplication
    private function mapEmail(array $email, $type = 'to')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
    {
202
        $returnValue = ['email' => $email['email'], 'type' => $type];
203
        if ($email['name']) {
204
            $returnValue['name'] = $email['name'];
205
        }
206
        return $returnValue;
207
    }
208
209
    /**
210
     * @param array $emails
211
     * @return string
212
     */
213 View Code Duplication
    private function mapEmailsString(array $emails)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
    {
215
        $returnValue = '';
216
        foreach ($emails as $email) {
217
            $returnValue .= $this->mapEmailString($email) . ', ';
218
        }
219
        return $returnValue ? substr($returnValue, 0, -2) : '';
220
    }
221
222
    /**
223
     * @param array $email
224
     * @return string
225
     */
226
    private function mapEmailString(array $email)
227
    {
228
        return !empty($email['name']) ? "'{$email['name']}' <{$email['email']}>" : $email['email'];
229
    }
230
}
231