Completed
Push — master ( 7c83da...9e19f1 )
by Tobias
08:04 queued 05:57
created

Mailgun   C

Complexity

Total Complexity 36

Size/Duplication

Total Lines 370
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 17

Test Coverage

Coverage 52.27%

Importance

Changes 0
Metric Value
wmc 36
lcom 4
cbo 17
dl 0
loc 370
ccs 46
cts 88
cp 0.5227
rs 6.9142
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 9 1
A create() 0 6 1
A sendMessage() 0 18 3
B verifyWebhookSignature() 0 17 6
A getLastResponse() 0 4 1
A post() 0 4 1
A get() 0 4 1
A getAttachment() 0 4 1
A delete() 0 4 1
A put() 0 4 1
A setApiVersion() 0 6 1
A setSslEnabled() 0 6 1
A MessageBuilder() 0 4 1
A OptInHandler() 0 4 1
A BatchMessage() 0 4 1
A stats() 0 4 1
A domains() 0 4 1
A tags() 0 4 1
A events() 0 4 1
A routes() 0 4 1
A webhooks() 0 4 1
A messages() 0 4 1
A suppressions() 0 4 1
B __construct() 0 31 6
1
<?PHP
2
3
/*
4
 * Copyright (C) 2013-2016 Mailgun
5
 *
6
 * This software may be modified and distributed under the terms
7
 * of the MIT license. See the LICENSE file for details.
8
 */
9
10
namespace Mailgun;
11
12
use Http\Client\Common\HttpMethodsClient;
13
use Http\Client\HttpClient;
14
use Mailgun\Connection\RestClient;
15
use Mailgun\Constants\ExceptionMessages;
16
use Mailgun\HttpClient\Plugin\History;
17
use Mailgun\Lists\OptInHandler;
18
use Mailgun\Messages\BatchMessage;
19
use Mailgun\Messages\Exceptions;
20
use Mailgun\Messages\MessageBuilder;
21
use Mailgun\Hydrator\ModelHydrator;
22
use Mailgun\Hydrator\Hydrator;
23
use Psr\Http\Message\ResponseInterface;
24
25
/**
26
 * This class is the base class for the Mailgun SDK.
27
 */
28
class Mailgun
29
{
30
    /**
31
     * @var RestClient
32
     *
33
     * @depracated Will be removed in 3.0
34
     */
35
    protected $restClient;
36
37
    /**
38
     * @var null|string
39
     */
40
    protected $apiKey;
41
42
    /**
43
     * @var HttpMethodsClient
44
     */
45
    private $httpClient;
46
47
    /**
48
     * @var Hydrator
49
     */
50
    private $hydrator;
51
52
    /**
53
     * @var RequestBuilder
54
     */
55
    private $requestBuilder;
56
57
    /**
58
     * This is a object that holds the last response from the API.
59
     *
60
     * @var History
61
     */
62
    private $responseHistory = null;
63
64
    /**
65
     * @param string|null                 $apiKey
66
     * @param HttpClient|null             $httpClient
67
     * @param string                      $apiEndpoint
68
     * @param Hydrator|null               $hydrator
69
     * @param HttpClientConfigurator|null $clientConfigurator
70
     * @param RequestBuilder|null         $requestBuilder
71
     */
72 6
    public function __construct(
73
        $apiKey = null,
74
        HttpClient $httpClient = null, /* Deprecated, will be removed in 3.0 */
75
        $apiEndpoint = 'api.mailgun.net', /* Deprecated, will be removed in 3.0 */
76 1
        Hydrator $hydrator = null,
77
        HttpClientConfigurator $clientConfigurator = null,
78
        RequestBuilder $requestBuilder = null
79
    ) {
80 6
        $this->apiKey = $apiKey;
81 6
        $this->restClient = new RestClient($apiKey, $apiEndpoint, $httpClient);
0 ignored issues
show
Deprecated Code introduced by
The class Mailgun\Connection\RestClient has been deprecated with message: Will be removed in 3.0

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
82
83 6
        if (null === $clientConfigurator) {
84 6
            $clientConfigurator = new HttpClientConfigurator();
85
86
            /*
87
             * To be backward compatible
88
             */
89 6
            if ($apiEndpoint !== 'api.mailgun.net') {
90
                $clientConfigurator->setEndpoint($apiEndpoint);
91
            }
92 6
            if ($httpClient !== null) {
93
                $clientConfigurator->setHttpClient($httpClient);
94
            }
95 6
        }
96
97 6
        $clientConfigurator->setApiKey($apiKey);
98
99 6
        $this->httpClient = $clientConfigurator->createConfiguredClient();
0 ignored issues
show
Documentation Bug introduced by
It seems like $clientConfigurator->createConfiguredClient() of type object<Http\Client\Common\PluginClient> is incompatible with the declared type object<Http\Client\Common\HttpMethodsClient> of property $httpClient.

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...
100 6
        $this->requestBuilder = $requestBuilder ?: new RequestBuilder();
101 6
        $this->hydrator = $hydrator ?: new ModelHydrator();
102 6
    }
103
104
    /**
105
     * @param HttpClientConfigurator $httpClientConfigurator
106
     * @param Hydrator|null          $hydrator
107
     * @param RequestBuilder|null    $requestBuilder
108
     *
109
     * @return Mailgun
110
     */
111
    public static function configure(
112
        HttpClientConfigurator $httpClientConfigurator,
113
        Hydrator $hydrator = null,
114
        RequestBuilder $requestBuilder = null
115
    ) {
116
        $httpClient = $httpClientConfigurator->createConfiguredClient();
117
118
        return new self($httpClient, $hydrator, $requestBuilder);
0 ignored issues
show
Documentation introduced by
$httpClient is of type object<Http\Client\Common\PluginClient>, but the function expects a string|null.

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...
Bug introduced by
It seems like $hydrator defined by parameter $hydrator on line 113 can also be of type object<Mailgun\Hydrator\Hydrator>; however, Mailgun\Mailgun::__construct() does only seem to accept null|object<Http\Client\HttpClient>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Documentation introduced by
$requestBuilder is of type null|object<Mailgun\RequestBuilder>, but the function expects a string.

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...
119
    }
120
121
    /**
122
     * @param string $apiKey
123
     *
124
     * @return Mailgun
125
     */
126 1
    public static function create($apiKey)
127 1
    {
128
        $httpClientConfigurator = (new HttpClientConfigurator())->setApiKey($apiKey);
129
130
        return self::configure($httpClientConfigurator);
131
    }
132
133
    /**
134
     *  This function allows the sending of a fully formed message OR a custom
135
     *  MIME string. If sending MIME, the string must be passed in to the 3rd
136
     *  position of the function call.
137
     *
138
     * @param string $workingDomain
139
     * @param array  $postData
140
     * @param array  $postFiles
141
     *
142
     * @throws Exceptions\MissingRequiredMIMEParameters
143
     *
144
     * @return \stdClass
145
     *
146
     * @deprecated Use Mailgun->message() instead. Will be removed in 3.0
147
     */
148 7
    public function sendMessage($workingDomain, $postData, $postFiles = [])
149
    {
150 7
        if (is_array($postFiles)) {
151 5
            return $this->post("$workingDomain/messages", $postData, $postFiles);
0 ignored issues
show
Deprecated Code introduced by
The method Mailgun\Mailgun::post() has been deprecated with message: Will be removed in 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
152 2
        } elseif (is_string($postFiles)) {
153 1
            $tempFile = tempnam(sys_get_temp_dir(), 'MG_TMP_MIME');
154 1
            $fileHandle = fopen($tempFile, 'w');
155 1
            fwrite($fileHandle, $postFiles);
156
157 1
            $result = $this->post("$workingDomain/messages.mime", $postData, ['message' => $tempFile]);
0 ignored issues
show
Deprecated Code introduced by
The method Mailgun\Mailgun::post() has been deprecated with message: Will be removed in 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
158 1
            fclose($fileHandle);
159 1
            unlink($tempFile);
160
161 1
            return $result;
162
        } else {
163 1
            throw new Exceptions\MissingRequiredMIMEParameters(ExceptionMessages::EXCEPTION_MISSING_REQUIRED_MIME_PARAMETERS);
164
        }
165
    }
166
167
    /**
168
     * This function checks the signature in a POST request to see if it is
169
     * authentic.
170
     *
171
     * Pass an array of parameters.  If you pass nothing, $_POST will be
172
     * used instead.
173
     *
174
     * If this function returns FALSE, you must not process the request.
175
     * You should reject the request with status code 403 Forbidden.
176
     *
177
     * @param array|null $postData
178
     *
179
     * @return bool
180
     *
181
     * @deprecated Use Mailgun->webhook() instead. Will be removed in 3.0
182
     */
183 3
    public function verifyWebhookSignature($postData = null)
0 ignored issues
show
Coding Style introduced by
verifyWebhookSignature uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
184
    {
185 3
        if ($postData === null) {
186
            $postData = $_POST;
187
        }
188 3
        if (!isset($postData['timestamp']) || !isset($postData['token']) || !isset($postData['signature'])) {
189 1
            return false;
190
        }
191 2
        $hmac = hash_hmac('sha256', "{$postData['timestamp']}{$postData['token']}", $this->apiKey);
192 2
        $sig = $postData['signature'];
193 2
        if (function_exists('hash_equals')) {
194
            // hash_equals is constant time, but will not be introduced until PHP 5.6
195
            return hash_equals($hmac, $sig);
196
        } else {
197 2
            return $hmac === $sig;
198
        }
199
    }
200
201
    /**
202
     * @return ResponseInterface|null
203
     */
204
    public function getLastResponse()
205
    {
206
        return $this->responseHistory->getLastResponse();
207
    }
208
209
    /**
210
     * @param string $endpointUrl
211
     * @param array  $postData
212
     * @param array  $files
213
     *
214
     * @return \stdClass
215
     *
216
     * @deprecated Will be removed in 3.0
217
     */
218 8
    public function post($endpointUrl, $postData = [], $files = [])
219
    {
220 8
        return $this->restClient->post($endpointUrl, $postData, $files);
221
    }
222
223
    /**
224
     * @param string $endpointUrl
225
     * @param array  $queryString
226
     *
227
     * @return \stdClass
228
     *
229
     * @deprecated Will be removed in 3.0
230
     */
231
    public function get($endpointUrl, $queryString = [])
232
    {
233
        return $this->restClient->get($endpointUrl, $queryString);
234
    }
235
236
    /**
237
     * @param string $url
238
     *
239
     * @return \stdClass
240
     *
241
     * @deprecated Will be removed in 3.0
242
     */
243 2
    public function getAttachment($url)
244
    {
245 2
        return $this->restClient->getAttachment($url);
246
    }
247
248
    /**
249
     * @param string $endpointUrl
250
     *
251
     * @return \stdClass
252
     *
253
     * @deprecated Will be removed in 3.0
254
     */
255
    public function delete($endpointUrl)
256
    {
257
        return $this->restClient->delete($endpointUrl);
258
    }
259
260
    /**
261
     * @param string $endpointUrl
262
     * @param array  $putData
263
     *
264
     * @return \stdClass
265
     *
266
     * @deprecated Will be removed in 3.0
267
     */
268
    public function put($endpointUrl, $putData)
269
    {
270
        return $this->restClient->put($endpointUrl, $putData);
271
    }
272
273
    /**
274
     * @param string $apiVersion
275
     *
276
     * @return Mailgun
277
     *
278
     * @deprecated Will be removed in 3.0
279
     */
280
    public function setApiVersion($apiVersion)
281
    {
282
        $this->restClient->setApiVersion($apiVersion);
283
284
        return $this;
285
    }
286
287
    /**
288
     * @param bool $sslEnabled
289
     *
290
     * @return Mailgun
291
     *
292
     * @deprecated This will be removed in 3.0. Mailgun does not support non-secure connections to their API.
293
     */
294
    public function setSslEnabled($sslEnabled)
295
    {
296
        $this->restClient->setSslEnabled($sslEnabled);
0 ignored issues
show
Deprecated Code introduced by
The method Mailgun\Connection\RestClient::setSslEnabled() has been deprecated with message: To be removed in 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
297
298
        return $this;
299
    }
300
301
    /**
302
     * @return MessageBuilder
303
     *
304
     * @deprecated Will be removed in 3.0
305
     */
306 30
    public function MessageBuilder()
307
    {
308 30
        return new MessageBuilder();
309
    }
310
311
    /**
312
     * @return OptInHandler
313
     *
314
     * @deprecated Will be removed in 3.0
315
     */
316 3
    public function OptInHandler()
317
    {
318 3
        return new OptInHandler();
319
    }
320
321
    /**
322
     * @param string $workingDomain
323
     * @param bool   $autoSend
324
     *
325
     * @return BatchMessage
326
     *
327
     * @deprecated Will be removed in 3.0
328
     */
329 15
    public function BatchMessage($workingDomain, $autoSend = true)
330
    {
331 15
        return new BatchMessage($this->restClient, $workingDomain, $autoSend);
332
    }
333
334
    /**
335
     * @return Api\Stats
336
     */
337
    public function stats()
338
    {
339
        return new Api\Stats($this->httpClient, $this->requestBuilder, $this->hydrator);
340
    }
341
342
    /**
343
     * @return Api\Domain
344
     */
345
    public function domains()
346
    {
347
        return new Api\Domain($this->httpClient, $this->requestBuilder, $this->hydrator);
348
    }
349
350
    /**
351
     * @return Api\Tag
352
     */
353
    public function tags()
354
    {
355
        return new Api\Tag($this->httpClient, $this->requestBuilder, $this->hydrator);
356
    }
357
358
    /**
359
     * @return Api\Event
360
     */
361
    public function events()
362
    {
363
        return new Api\Event($this->httpClient, $this->requestBuilder, $this->hydrator);
364
    }
365
366
    /**
367
     * @return Api\Route
368
     */
369
    public function routes()
370
    {
371
        return new Api\Route($this->httpClient, $this->requestBuilder, $this->hydrator);
372
    }
373
374
    /**
375
     * @return Api\Webhook
376
     */
377
    public function webhooks()
378
    {
379
        return new Api\Webhook($this->httpClient, $this->requestBuilder, $this->hydrator);
380
    }
381
382
    /**
383
     * @return Api\Message
384
     */
385
    public function messages()
386
    {
387
        return new Api\Message($this->httpClient, $this->requestBuilder, $this->hydrator);
388
    }
389
390
    /**
391
     * @return Api\Suppression
392
     */
393
    public function suppressions()
394
    {
395
        return new Api\Suppression($this->httpClient, $this->requestBuilder, $this->hydrator);
396
    }
397
}
398