Completed
Push — master ( f45390...6188e2 )
by Drew
01:58
created

MailChimp::success()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace DrewM\MailChimp;
4
5
/**
6
 * Super-simple, minimum abstraction MailChimp API v3 wrapper
7
 * MailChimp API v3: http://developer.mailchimp.com
8
 * This wrapper: https://github.com/drewm/mailchimp-api
9
 *
10
 * @author Drew McLellan <[email protected]>
11
 * @version 2.1.3
12
 */
13
class MailChimp
14
{
15
    private $api_key;
16
    private $api_endpoint = 'https://<dc>.api.mailchimp.com/3.0';
17
18
    /*  SSL Verification
19
        Read before disabling: 
20
        http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/
21
    */
22
    public $verify_ssl = true;
23
24
    private $request_successful = false;
25
    private $last_error         = '';
26
    private $last_response      = array();
27
    private $last_request       = array();
28
29
    /**
30
     * Create a new instance
31
     * @param string $api_key Your MailChimp API key
32
     * @throws \Exception
33
     */
34
    public function __construct($api_key)
35
    {
36
        $this->api_key = $api_key;
37
38
        if (strpos($this->api_key, '-') === false) {
39
            throw new \Exception('Invalid MailChimp API key supplied.');
40
        }
41
42
        list(, $data_center) = explode('-', $this->api_key);
43
        $this->api_endpoint  = str_replace('<dc>', $data_center, $this->api_endpoint);
44
45
        $this->last_response = array('headers' => null, 'body' => null);
46
    }
47
48
    /**
49
     * Create a new instance of a Batch request. Optionally with the ID of an existing batch.
50
     * @param string $batch_id Optional ID of an existing batch, if you need to check its status for example.
51
     * @return Batch            New Batch object.
52
     */
53
    public function new_batch($batch_id = null)
54
    {
55
        return new Batch($this, $batch_id);
56
    }
57
58
    /**
59
     * Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL
60
     * @param   string $email The subscriber's email address
61
     * @return  string          Hashed version of the input
62
     */
63
    public function subscriberHash($email)
64
    {
65
        return md5(strtolower($email));
66
    }
67
68
    /**
69
     * Was the last request successful?
70
     * @return bool  True for success, false for failure
71
     */
72
    public function success()
73
    {
74
        return $this->request_successful;
75
    }
76
77
    /**
78
     * Get the last error returned by either the network transport, or by the API.
79
     * If something didn't work, this should contain the string describing the problem.
80
     * @return  array|false  describing the error
81
     */
82
    public function getLastError()
83
    {
84
        return $this->last_error ?: false;
85
    }
86
87
    /**
88
     * Get an array containing the HTTP headers and the body of the API response.
89
     * @return array  Assoc array with keys 'headers' and 'body'
90
     */
91
    public function getLastResponse()
92
    {
93
        return $this->last_response;
94
    }
95
96
    /**
97
     * Get an array containing the HTTP headers and the body of the API request.
98
     * @return array  Assoc array
99
     */
100
    public function getLastRequest()
101
    {
102
        return $this->last_request;
103
    }
104
105
    /**
106
     * Make an HTTP DELETE request - for deleting data
107
     * @param   string $method URL of the API request method
108
     * @param   array $args Assoc array of arguments (if any)
109
     * @param   int $timeout Timeout limit for request in seconds
110
     * @return  array|false   Assoc array of API response, decoded from JSON
111
     */
112
    public function delete($method, $args = array(), $timeout = 10)
113
    {
114
        return $this->makeRequest('delete', $method, $args, $timeout);
115
    }
116
117
    /**
118
     * Make an HTTP GET request - for retrieving data
119
     * @param   string $method URL of the API request method
120
     * @param   array $args Assoc array of arguments (usually your data)
121
     * @param   int $timeout Timeout limit for request in seconds
122
     * @return  array|false   Assoc array of API response, decoded from JSON
123
     */
124
    public function get($method, $args = array(), $timeout = 10)
125
    {
126
        return $this->makeRequest('get', $method, $args, $timeout);
127
    }
128
129
    /**
130
     * Make an HTTP PATCH request - for performing partial updates
131
     * @param   string $method URL of the API request method
132
     * @param   array $args Assoc array of arguments (usually your data)
133
     * @param   int $timeout Timeout limit for request in seconds
134
     * @return  array|false   Assoc array of API response, decoded from JSON
135
     */
136
    public function patch($method, $args = array(), $timeout = 10)
137
    {
138
        return $this->makeRequest('patch', $method, $args, $timeout);
139
    }
140
141
    /**
142
     * Make an HTTP POST request - for creating and updating items
143
     * @param   string $method URL of the API request method
144
     * @param   array $args Assoc array of arguments (usually your data)
145
     * @param   int $timeout Timeout limit for request in seconds
146
     * @return  array|false   Assoc array of API response, decoded from JSON
147
     */
148
    public function post($method, $args = array(), $timeout = 10)
149
    {
150
        return $this->makeRequest('post', $method, $args, $timeout);
151
    }
152
153
    /**
154
     * Make an HTTP PUT request - for creating new items
155
     * @param   string $method URL of the API request method
156
     * @param   array $args Assoc array of arguments (usually your data)
157
     * @param   int $timeout Timeout limit for request in seconds
158
     * @return  array|false   Assoc array of API response, decoded from JSON
159
     */
160
    public function put($method, $args = array(), $timeout = 10)
161
    {
162
        return $this->makeRequest('put', $method, $args, $timeout);
163
    }
164
165
    /**
166
     * Performs the underlying HTTP request. Not very exciting.
167
     * @param  string $http_verb The HTTP verb to use: get, post, put, patch, delete
168
     * @param  string $method The API method to be called
169
     * @param  array $args Assoc array of parameters to be passed
170
     * @param int $timeout
171
     * @return array|false Assoc array of decoded result
172
     * @throws Exception
173
     */
174
    private function makeRequest($http_verb, $method, $args = array(), $timeout = 10)
175
    {
176
        if (!function_exists('curl_init') || !function_exists('curl_setopt')) {
177
            throw new Exception("cURL support is required, but can't be found.");
178
        }
179
180
        $url = $this->api_endpoint . '/' . $method;
181
182
        $this->last_error         = '';
183
        $this->request_successful = false;
184
        $response                 = array('headers' => null, 'body' => null);
185
        $this->last_response      = $response;
186
187
        $this->last_request = array(
188
            'method'  => $http_verb,
189
            'path'    => $method,
190
            'url'     => $url,
191
            'body'    => '',
192
            'timeout' => $timeout,
193
        );
194
195
        $ch = curl_init();
196
        curl_setopt($ch, CURLOPT_URL, $url);
197
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
198
            'Accept: application/vnd.api+json',
199
            'Content-Type: application/vnd.api+json',
200
            'Authorization: apikey ' . $this->api_key
201
        ));
202
        curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)');
203
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
204
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
205
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
206
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
207
        curl_setopt($ch, CURLOPT_ENCODING, '');
208
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
209
210
        switch ($http_verb) {
211
            case 'post':
212
                curl_setopt($ch, CURLOPT_POST, true);
213
                $this->attachRequestPayload($ch, $args);
214
                break;
215
216
            case 'get':
217
                $query = http_build_query($args);
218
                curl_setopt($ch, CURLOPT_URL, $url . '?' . $query);
219
                break;
220
221
            case 'delete':
222
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
223
                break;
224
225
            case 'patch':
226
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
227
                $this->attachRequestPayload($ch, $args);
228
                break;
229
230
            case 'put':
231
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
232
                $this->attachRequestPayload($ch, $args);
233
                break;
234
        }
235
236
        $response['body']    = curl_exec($ch);
237
        $response['headers'] = curl_getinfo($ch);
238
239
        if (isset($response['headers']['request_header'])) {
240
            $this->last_request['headers'] = $response['headers']['request_header'];
241
        }
242
243
        if ($response['body'] === false) {
244
            $this->last_error = curl_error($ch);
245
        }
246
247
        curl_close($ch);
248
249
        return $this->formatResponse($response);
250
    }
251
252
    /**
253
     * Encode the data and attach it to the request
254
     * @param   resource $ch cURL session handle, used by reference
255
     * @param   array $data Assoc array of data to attach
256
     */
257
    private function attachRequestPayload(&$ch, $data)
258
    {
259
        $encoded = json_encode($data);
260
        $this->last_request['body'] = $encoded;
261
        curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
262
    }
263
264
    /**
265
     * Decode the response and format any error messages for debugging
266
     * @param array $response The response from the curl request
267
     * @return array|false     The JSON decoded into an array
268
     */
269
    private function formatResponse($response)
270
    {
271
        $this->last_response = $response;
272
273
        if (!empty($response['body'])) {
274
275
            $d = json_decode($response['body'], true);
276
277
            if (isset($d['status']) && $d['status'] != '200' && isset($d['detail'])) {
278
                $this->last_error = sprintf('%d: %s', $d['status'], $d['detail']);
279
            } else {
280
                $this->request_successful = true;
281
            }
282
283
            return $d;
284
        }
285
286
        return false;
287
    }
288
}
289