Completed
Push — master ( 1ff499...32025a )
by Loz
06:06 queued 04:18
created

Mailer   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 21
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 225
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A setMailgunClient() 0 5 1
A getMailgunClient() 0 4 1
A sendPlain() 0 4 1
A sendHTML() 0 4 1
A sendMessage() 0 21 3
C buildMessage() 0 37 8
A prepareAttachments() 0 15 2
A writeToTempFile() 0 13 1
A closeTempFileHandles() 0 8 2
1
<?php
2
3
namespace Kinglozzer\SilverStripeMailgunner;
4
5
use Mailer as SilverstripeMailer;
6
use Mailgun\Mailgun;
7
use Mailgun\Messages\MessageBuilder;
8
9
class Mailer extends SilverstripeMailer
10
{
11
    /**
12
     * @var string
13
     * @config
14
     */
15
    private static $api_domain = '';
16
17
    /**
18
     * @var string
19
     * @config
20
     */
21
    private static $api_endpoint = 'api.mailgun.net';
22
23
    /**
24
     * @var string
25
     * @config
26
     */
27
    private static $api_key = '';
28
29
    /**
30
     * @var boolean
31
     * @config
32
     */
33
    private static $api_ssl = true;
34
35
    /**
36
     * @var string
37
     * @config
38
     */
39
    private static $api_version = 'v3';
40
41
    /**
42
     * An array of temporary file handles opened to store attachments
43
     * @var array
44
     */
45
    protected $tempFileHandles = [];
46
47
    /**
48
     * @var Mailgun\Mailgun
49
     */
50
    protected $mailgunClient;
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function __construct()
56
    {
57
        $config = $this->config();
58
        $this->setMailgunClient(new Mailgun(
59
            $config->api_key,
60
            $config->api_endpoint,
61
            $config->api_version,
62
            $config->api_ssl
63
        ));
64
    }
65
66
    /**
67
     * @param Mailgun\Mailgun $client
0 ignored issues
show
Documentation introduced by
Should the type for parameter $client not be Mailgun?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
68
     * @return self
69
     */
70
    public function setMailgunClient(Mailgun $client)
71
    {
72
        $this->mailgunClient = $client;
0 ignored issues
show
Documentation Bug introduced by
It seems like $client of type object<Mailgun\Mailgun> is incompatible with the declared type object<Mailgun\Mailgun\Mailgun> of property $mailgunClient.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
73
        return $this;
74
    }
75
76
    /**
77
     * @return Mailgun\Mailgun
78
     */
79
    public function getMailgunClient()
80
    {
81
        return $this->mailgunClient;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function sendPlain($to, $from, $subject, $plainContent, $attachments = [], $headers = [])
88
    {
89
        $this->sendMessage($to, $from, $subject, $htmlContent = '', $plainContent, $attachments, $headers);
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95
    public function sendHTML($to, $from, $subject, $htmlContent, $attachments = [], $headers = [], $plainContent = '')
96
    {
97
        $this->sendMessage($to, $from, $subject, $htmlContent, $plainContent, $attachments, $headers);
98
    }
99
100
    /**
101
     * @param string $to
102
     * @param string $from
103
     * @param string $subject
104
     * @param string $content
105
     * @param string $plainContent
106
     * @param array $attachments
107
     * @param array $headers
108
     */
109
    protected function sendMessage($to, $from, $subject, $content, $plainContent, $attachments, $headers)
110
    {
111
        $client = $this->getMailgunClient();
112
        $messageBuilder = $client->MessageBuilder();
113
114
        $this->buildMessage($messageBuilder, $to, $from, $subject, $content, $plainContent, $headers);
115
116
        if (!empty($attachments)) {
117
            $attachments = $this->prepareAttachments($attachments);
118
        }
119
120
        try {
121
            $client->sendMessage($this->config()->api_domain, $messageBuilder->getMessage(), $attachments);
122
        } catch (\Exception $e) {
123
            // Close and remove any temp files created for attachments, then let the exception bubble up
124
            $this->closeTempFileHandles();
125
            throw $e;
126
        }
127
128
        $this->closeTempFileHandles();
129
    }
130
131
    /**
132
     * @param Mailgun\Messages\MessageBuilder $messageBuilder
0 ignored issues
show
Documentation introduced by
There is no parameter named $messageBuilder. Did you maybe mean $builder?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
133
     * @param string $to
134
     * @param string $from
135
     * @param string $subject
136
     * @param string $content
137
     * @param string $plainContent
138
     * @param array $attachments
0 ignored issues
show
Bug introduced by
There is no parameter named $attachments. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
139
     * @param array $headers
140
     */
141
    protected function buildMessage(MessageBuilder $builder, $to, $from, $subject, $content, $plainContent, $headers)
142
    {
143
        // Add base info
144
        $builder->addToRecipient($to);
145
        $builder->setFromAddress($from);
146
        $builder->setSubject($subject);
147
148
        // HTML content (if not empty)
149
        if ($content) {
150
            $builder->setHtmlBody($content);
151
        }
152
153
        // Plain text content (if not empty)
154
        if ($plainContent) {
155
            $builder->setTextBody($plainContent);
156
        }
157
158
        // Parse Cc & Bcc headers out if they're set
159
        if (isset($headers['Cc'])) {
160
            foreach (explode(', ', $headers['Cc']) as $ccAddress) {
161
                $builder->addCcRecipient($ccAddress);
162
            }
163
            unset($headers['Cc']);
164
        }
165
166
        if (isset($headers['Bcc'])) {
167
            foreach (explode(', ', $headers['Bcc']) as $bccAddress) {
168
                $builder->addBccRecipient($bccAddress);
169
            }
170
            unset($headers['Bcc']);
171
        }
172
173
        // Add remaining custom headers
174
        foreach ($headers as $name => $data) {
175
            $builder->addCustomHeader($name, $data);
176
        }
177
    }
178
179
    /**
180
     * Prepare attachments for sending. SilverStripe extracts the content and
181
     * passes that to the mailer, so to save encoding it we just write them all
182
     * to individual files and let Mailgun deal with the rest.
183
     * 
184
     * @todo Can we handle this better?
185
     * @param array $attachments
186
     * @return array
187
     */
188
    protected function prepareAttachments(array $attachments)
189
    {
190
        $prepared = [];
191
            
192
        foreach ($attachments as $attachment) {
193
            $tempFile = $this->writeToTempFile($attachment['contents']);
194
            
195
            $prepared[] = [
196
                'filePath' => $tempFile,
197
                'remoteName' => $attachment['filename']
198
            ];
199
        }
200
201
       return ['attachment' => $prepared];
202
    }
203
204
    /**
205
     * @param string $contents
206
     * @return string
207
     */
208
    protected function writeToTempFile($contents)
209
    {
210
        $tempFile = tempnam(sys_get_temp_dir(), 'SS_MG_TMP');
211
        $fileHandle = fopen($tempFile, 'r+');
212
        fwrite($fileHandle, $contents);
213
214
        $this->tempFileHandles[] = [
215
            'handle' => $fileHandle,
216
            'path' => $tempFile
217
        ];
218
219
        return $tempFile;
220
    }
221
222
    /**
223
     * @return void
224
     */
225
    protected function closeTempFileHandles()
226
    {
227
        foreach ($this->tempFileHandles as $key => $data) {
228
            fclose($data['handle']);
229
            unlink($data['path']);
230
            unset($this->tempFileHandles[$key]);
231
        }
232
    }
233
}
234