Completed
Push — master ( 9497ed...4a101c )
by Drew
61:48
created

MailChimp::formatResponse()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 8.8571
cc 5
eloc 8
nc 3
nop 1
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.0.7
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 $last_error    = '';
25
    private $last_response = array();
26
27
    /**
28
     * Create a new instance
29
     * @param string $api_key Your MailChimp API key
30
     */
31
    public function __construct($api_key)
32
    {
33
        $this->api_key = $api_key;
34
35
        list(, $datacentre)  = explode('-', $this->api_key);
36
        $this->api_endpoint  = str_replace('<dc>', $datacentre, $this->api_endpoint);
37
38
        $this->last_response = array('headers'=>null, 'body'=>null);
39
    }
40
41
    /**
42
     * Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL
43
     * @param   string  $email  The subscriber's email address
44
     * @return  string          Hashed version of the input
45
     */
46
    public function subscriberHash($email)
47
    {
48
        return md5(strtolower($email));
49
    }
50
51
    /**
52
     * Get the last error returned by either the network transport, or by the API.
53
     * If something didn't work, this should contain the string describing the problem.
54
     * @return  array|false  describing the error
55
     */
56
    public function getLastError()
57
    {
58
        if ($this->last_error) return $this->last_error;
59
        return false;
60
    }
61
62
    /**
63
     * Get an array containing the HTTP headers and the body of the API response.
64
     * @return array  Assoc array with keys 'headers' and 'body'
65
     */
66
    public function getLastResponse()
67
    {
68
        return $this->last_response;
69
    }
70
    
71
    /**
72
     * Make an HTTP DELETE request - for deleting data
73
     * @param   string        URL of the API request method
74
     * @param   array         Assoc array of arguments (if any)
75
     * @param   int           Timeout limit for request in seconds
76
     * @return  array|false   Assoc array of API response, decoded from JSON
77
     */
78
    public function delete($method, $args=array(), $timeout=10)
79
    {
80
        return $this->makeRequest('delete', $method, $args, $timeout);
81
    }
82
83
    /**
84
     * Make an HTTP GET request - for retrieving data
85
     * @param   string        URL of the API request method
86
     * @param   array         Assoc array of arguments (usually your data)
87
     * @param   int           Timeout limit for request in seconds
88
     * @return  array|false   Assoc array of API response, decoded from JSON
89
     */
90
    public function get($method, $args=array(), $timeout=10)
91
    {
92
        return $this->makeRequest('get', $method, $args, $timeout);
93
    }
94
95
    /**
96
     * Make an HTTP PATCH request - for performing partial updates
97
     * @param   string        URL of the API request method
98
     * @param   array         Assoc array of arguments (usually your data)
99
     * @param   int           Timeout limit for request in seconds
100
     * @return  array|false   Assoc array of API response, decoded from JSON
101
     */
102
    public function patch($method, $args=array(), $timeout=10)
103
    {
104
        return $this->makeRequest('patch', $method, $args, $timeout);
105
    }
106
107
    /**
108
     * Make an HTTP POST request - for creating and updating items
109
     * @param   string        URL of the API request method
110
     * @param   array         Assoc array of arguments (usually your data)
111
     * @param   int           Timeout limit for request in seconds
112
     * @return  array|false   Assoc array of API response, decoded from JSON
113
     */
114
    public function post($method, $args=array(), $timeout=10)
115
    {
116
        return $this->makeRequest('post', $method, $args, $timeout);
117
    }
118
119
    /**
120
     * Make an HTTP PUT request - for creating new items
121
     * @param   string        URL of the API request method
122
     * @param   array         Assoc array of arguments (usually your data)
123
     * @param   int           Timeout limit for request in seconds
124
     * @return  array|false   Assoc array of API response, decoded from JSON
125
     */
126
    public function put($method, $args=array(), $timeout=10)
127
    {
128
        return $this->makeRequest('put', $method, $args, $timeout);
129
    }
130
131
    /**
132
     * Performs the underlying HTTP request. Not very exciting
133
     * @param  string $http_verb   The HTTP verb to use: get, post, put, patch, delete
134
     * @param  string $method       The API method to be called
135
     * @param  array  $args         Assoc array of parameters to be passed
136
     * @return array|false          Assoc array of decoded result
137
     */
138
    private function makeRequest($http_verb, $method, $args=array(), $timeout=10)
139
    {
140
        $url = $this->api_endpoint.'/'.$method;
141
142
        $this->last_error    = '';
143
        $response            = array('headers'=>null, 'body'=>null);
144
        $this->last_response = $response;
145
146
        if (function_exists('curl_init') && function_exists('curl_setopt')) {
147
            $ch = curl_init();
148
            curl_setopt($ch, CURLOPT_URL, $url);
149
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/vnd.api+json',
150
                                                        'Content-Type: application/vnd.api+json',
151
                                                        'Authorization: apikey '.$this->api_key));
152
            curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)');
153
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
154
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
155
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
156
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
157
            curl_setopt($ch, CURLOPT_ENCODING, '');
158
159
            switch($http_verb) {
160 View Code Duplication
                case 'post':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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
                    curl_setopt($ch, CURLOPT_POST, true);
162
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args));
163
                    break;
164
165
                case 'get':
166
                    $query = http_build_query($args);
167
                    curl_setopt($ch, CURLOPT_URL, $url.'?'.$query);
168
                    break;
169
170
                case 'delete':
171
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
172
                    break;
173
174 View Code Duplication
                case 'patch':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
175
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
176
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args));
177
                    break;
178
                
179 View Code Duplication
                case 'put':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
180
                    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
181
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args)); 
182
                    break;
183
            }
184
185
            $response['body']    = curl_exec($ch);
186
            $response['headers'] = curl_getinfo($ch);
187
            
188
            if ($response['body'] === false) {
189
                $this->last_error = curl_error($ch);
190
            }
191
            
192
            curl_close($ch);
193
        } else {
194
            throw new \Exception("cURL support is required, but can't be found.");
195
        }
196
197
        return $this->formatResponse($response);
198
    }
199
200
    private function formatResponse($response)
201
    {
202
        $this->last_response = $response;
203
204
        if (!empty($response['body'])) {
205
206
            $d = json_decode($response['body'], true);
207
            
208
            if (isset($d['status']) && $d['status']!='200' && isset($d['detail'])) {
209
                $this->last_error = sprintf('%d: %s', $d['status'], $d['detail']);
210
            }
211
            
212
            return $d;
213
        }
214
215
        return false;
216
    }
217
}
218