|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* @file |
|
4
|
|
|
* A lightweight wrapper for the Eventbrite API using Guzzle 6. Inspired by |
|
5
|
|
|
* drewm/mailchimp-api. |
|
6
|
|
|
*/ |
|
7
|
|
|
namespace jamiehollern\eventbrite; |
|
8
|
|
|
|
|
9
|
|
|
use GuzzleHttp\Client; |
|
10
|
|
|
use GuzzleHttp\Psr7\Request; |
|
11
|
|
|
use GuzzleHttp\Exception\BadResponseException; |
|
12
|
|
|
use Psr\Http\Message\ResponseInterface; |
|
13
|
|
|
use Exception; |
|
14
|
|
|
|
|
15
|
|
|
/** |
|
16
|
|
|
* Class Eventbrite |
|
17
|
|
|
* |
|
18
|
|
|
* @package EventbritePHP |
|
19
|
|
|
* @todo Add a batch method. |
|
20
|
|
|
* @todo Allow the token to be passed as a query string. |
|
21
|
|
|
*/ |
|
22
|
|
|
class Eventbrite |
|
23
|
|
|
{ |
|
24
|
|
|
/** |
|
25
|
|
|
* The current version of this library. |
|
26
|
|
|
*/ |
|
27
|
|
|
const VERSION = '0.1'; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* The API endpoint to get the current user's details. |
|
31
|
|
|
*/ |
|
32
|
|
|
const CURRENT_USER_ENDPOINT = 'users/me/'; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* @var string The Eventbrite OAuth token. |
|
36
|
|
|
*/ |
|
37
|
|
|
private $token; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* @var \GuzzleHttp\Client |
|
41
|
|
|
*/ |
|
42
|
|
|
private $client; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* @var \Psr\Http\Message\ResponseInterface |
|
46
|
|
|
*/ |
|
47
|
|
|
private $last_response = null; |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* @param string $token |
|
51
|
|
|
* The OAuth token to authenticate the request |
|
52
|
|
|
* @param array $config |
|
53
|
|
|
* An array of Guzzle config options so that everything is configurable. |
|
54
|
|
|
* |
|
55
|
|
|
* @throws \Exception |
|
56
|
|
|
*/ |
|
57
|
|
|
public function __construct($token, $config = []) |
|
58
|
|
|
{ |
|
59
|
|
|
$default_config = [ |
|
60
|
|
|
'base_uri' => 'https://www.eventbriteapi.com/v3/', |
|
61
|
|
|
// Turn exceptions off so we can handle the responses ourselves. |
|
62
|
|
|
'exceptions' => false, |
|
63
|
|
|
'timeout' => 30, |
|
64
|
|
|
]; |
|
65
|
|
|
$config = array_merge($config, $default_config); |
|
66
|
|
|
// Add this last so it's always there and isn't overwritten. |
|
67
|
|
|
$config['headers']['User-Agent'] = 'jamiehollern\eventbrite v' . self::VERSION . ' ' . \GuzzleHttp\default_user_agent(); |
|
68
|
|
|
if (!empty($token)) { |
|
69
|
|
|
$this->token = $token; |
|
70
|
|
|
// Set the authorisation header. |
|
71
|
|
|
$config['headers']['Authorization'] = 'Bearer ' . $this->token; |
|
72
|
|
|
$this->client = new Client($config); |
|
73
|
|
|
} else { |
|
74
|
|
|
throw new \Exception('An OAuth token is required to connect to the Eventbrite API.'); |
|
75
|
|
|
} |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Make the call to Eventbrite, only synchronous calls at present. |
|
80
|
|
|
* |
|
81
|
|
|
* @param string $verb |
|
82
|
|
|
* @param string $endpoint |
|
83
|
|
|
* @param array $options |
|
84
|
|
|
* |
|
85
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
86
|
|
|
* @throws \Exception |
|
87
|
|
|
*/ |
|
88
|
|
|
public function call($verb, $endpoint, $options = []) |
|
89
|
|
|
{ |
|
90
|
|
|
if ($this->validMethod($verb)) { |
|
91
|
|
|
// Get the headers and body from the options. |
|
92
|
|
|
$headers = isset($options['headers']) ? $options['headers'] : []; |
|
93
|
|
|
$body = isset($options['body']) ? $options['body'] : []; |
|
94
|
|
|
$pv = isset($options['protocol_version']) ? $options['protocol_version'] : '1.1'; |
|
95
|
|
|
// Make the request. |
|
96
|
|
|
$request = new Request($verb, $endpoint, $headers, $body, $pv); |
|
97
|
|
|
// Send it. |
|
98
|
|
|
$response = $this->client->send($request, $options); |
|
99
|
|
|
if ($response instanceof ResponseInterface) { |
|
100
|
|
|
// Set the last response. |
|
101
|
|
|
$this->last_response = $response; |
|
102
|
|
|
// If the caller wants the raw response, give it to them. |
|
103
|
|
|
if (isset($options['parse_response']) && $options['parse_response'] === false) { |
|
104
|
|
|
return $response; |
|
105
|
|
|
} |
|
106
|
|
|
$parsed_response = $this->parseResponse($response); |
|
107
|
|
|
return $parsed_response; |
|
108
|
|
|
} else { |
|
109
|
|
|
// This only really happens when the network is interrupted. |
|
110
|
|
|
throw new BadResponseException('A bad response was received.', |
|
111
|
|
|
$request); |
|
112
|
|
|
} |
|
113
|
|
|
} else { |
|
114
|
|
|
throw new \Exception('Unrecognised HTTP verb.'); |
|
115
|
|
|
} |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
/** |
|
119
|
|
|
* A slightly abstracted wrapper around call(). |
|
120
|
|
|
* |
|
121
|
|
|
* This essentially splits the call options array into different parameters |
|
122
|
|
|
* to make it more obvious to less advanced users what parameters can be |
|
123
|
|
|
* passed to the client. |
|
124
|
|
|
* |
|
125
|
|
|
* @param $verb |
|
126
|
|
|
* @param $endpoint |
|
127
|
|
|
* @param null $params |
|
128
|
|
|
* @param null $body |
|
129
|
|
|
* @param null $headers |
|
130
|
|
|
* @param array $options |
|
131
|
|
|
* |
|
132
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
133
|
|
|
* @throws \Exception |
|
134
|
|
|
*/ |
|
135
|
|
|
public function makeRequest($verb, $endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
136
|
|
|
{ |
|
137
|
|
|
// Merge the query string. |
|
138
|
|
View Code Duplication |
if ($params !== null) { |
|
|
|
|
|
|
139
|
|
|
if (!isset($options['query'])) { |
|
140
|
|
|
$options['query'] = []; |
|
141
|
|
|
} |
|
142
|
|
|
$options['query'] = array_merge($options['query'], $params); |
|
143
|
|
|
} |
|
144
|
|
|
// We can only have one body, so overwrite it if it exists. |
|
145
|
|
|
if ($body !== null) { |
|
146
|
|
|
$options['body'] = $body; |
|
147
|
|
|
} |
|
148
|
|
|
// Merge the headers. |
|
149
|
|
View Code Duplication |
if ($headers !== null) { |
|
|
|
|
|
|
150
|
|
|
if (!isset($options['headers'])) { |
|
151
|
|
|
$options['headers'] = []; |
|
152
|
|
|
} |
|
153
|
|
|
$options['headers'] = array_merge($options['headers'], $headers); |
|
154
|
|
|
} |
|
155
|
|
|
return $this->call($verb, $endpoint, $options); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Checks if the HTTP method being used is correct. |
|
160
|
|
|
* |
|
161
|
|
|
* @param $http_method |
|
162
|
|
|
* |
|
163
|
|
|
* @return bool |
|
164
|
|
|
*/ |
|
165
|
|
|
public function validMethod($http_method) |
|
166
|
|
|
{ |
|
167
|
|
|
$valid_methods = ['get', 'post', 'put', 'patch', 'delete']; |
|
168
|
|
|
if (in_array(strtolower($http_method), $valid_methods)) { |
|
169
|
|
|
return true; |
|
170
|
|
|
} |
|
171
|
|
|
return false; |
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* Parses the response from |
|
176
|
|
|
* |
|
177
|
|
|
* @param \Psr\Http\Message\ResponseInterface $response |
|
178
|
|
|
* |
|
179
|
|
|
* @return array |
|
180
|
|
|
*/ |
|
181
|
|
|
private function parseResponse(ResponseInterface $response) |
|
182
|
|
|
{ |
|
183
|
|
|
$body = $response->getBody()->getContents(); |
|
184
|
|
|
return [ |
|
185
|
|
|
'code' => $response->getStatusCode(), |
|
186
|
|
|
'headers' => $response->getHeaders(), |
|
187
|
|
|
'body' => ($this->isValidJson($body)) ? json_decode($body, |
|
188
|
|
|
true) : $body, |
|
189
|
|
|
]; |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
/** |
|
193
|
|
|
* Checks a string to see if it's JSON. True if it is, false if it's not. |
|
194
|
|
|
* |
|
195
|
|
|
* @param string $string |
|
196
|
|
|
* |
|
197
|
|
|
* @return bool |
|
198
|
|
|
*/ |
|
199
|
|
|
public function isValidJson($string) |
|
200
|
|
|
{ |
|
201
|
|
|
if (is_string($string)) { |
|
202
|
|
|
json_decode($string); |
|
203
|
|
|
return (json_last_error() === JSON_ERROR_NONE); |
|
204
|
|
|
} |
|
205
|
|
|
return false; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
/** |
|
209
|
|
|
* Checks if the class can connect to the Eventbrite API. |
|
210
|
|
|
* |
|
211
|
|
|
* Checks if we can connect to the API by calling the user endpoint and |
|
212
|
|
|
* checking the response code. If the response code is 2xx it returns true, |
|
213
|
|
|
* otherwise false. |
|
214
|
|
|
* |
|
215
|
|
|
* @return bool |
|
216
|
|
|
*/ |
|
217
|
|
|
public function canConnect() |
|
218
|
|
|
{ |
|
219
|
|
|
$data = $this->get(self::CURRENT_USER_ENDPOINT); |
|
220
|
|
|
if (strpos($data['code'], '2') === 0) { |
|
221
|
|
|
return true; |
|
222
|
|
|
} |
|
223
|
|
|
return false; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
/** |
|
227
|
|
|
* Wrapper shortcut on the makeRequest method for "GET" requests. |
|
228
|
|
|
* |
|
229
|
|
|
* @param string $endpoint |
|
230
|
|
|
* @param array $options |
|
231
|
|
|
* |
|
232
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
233
|
|
|
* @throws \Exception |
|
234
|
|
|
*/ |
|
235
|
|
|
public function get($endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
236
|
|
|
{ |
|
237
|
|
|
return $this->makeRequest('GET', $endpoint, $params, $body, $headers, $options); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Wrapper shortcut on the makeRequest method for "POST" requests. |
|
242
|
|
|
* |
|
243
|
|
|
* @param $endpoint |
|
244
|
|
|
* @param array $options |
|
245
|
|
|
* |
|
246
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
247
|
|
|
* @throws \Exception |
|
248
|
|
|
*/ |
|
249
|
|
|
public function post($endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
250
|
|
|
{ |
|
251
|
|
|
return $this->makeRequest('POST', $endpoint, $params, $body, $headers, |
|
252
|
|
|
$options); |
|
253
|
|
|
} |
|
254
|
|
|
|
|
255
|
|
|
/** |
|
256
|
|
|
* Wrapper shortcut on the makeRequest method for "PUT" requests. |
|
257
|
|
|
* |
|
258
|
|
|
* @param $endpoint |
|
259
|
|
|
* @param array $options |
|
260
|
|
|
* |
|
261
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
262
|
|
|
* @throws \Exception |
|
263
|
|
|
*/ |
|
264
|
|
|
public function put($endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
265
|
|
|
{ |
|
266
|
|
|
return $this->makeRequest('PUT', $endpoint, $params, $body, $headers, $options); |
|
267
|
|
|
} |
|
268
|
|
|
|
|
269
|
|
|
/** |
|
270
|
|
|
* Wrapper shortcut on the makeRequest method for "PATCH" requests. |
|
271
|
|
|
* |
|
272
|
|
|
* @param $endpoint |
|
273
|
|
|
* @param array $options |
|
274
|
|
|
* |
|
275
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
276
|
|
|
* @throws \Exception |
|
277
|
|
|
*/ |
|
278
|
|
|
public function patch($endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
279
|
|
|
{ |
|
280
|
|
|
return $this->makeRequest('PATCH', $endpoint, $params, $body, $headers, $options); |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
/** |
|
284
|
|
|
* Wrapper shortcut on the makeRequest method for "DELETE" requests. |
|
285
|
|
|
* |
|
286
|
|
|
* @param $endpoint |
|
287
|
|
|
* @param array $options |
|
288
|
|
|
* |
|
289
|
|
|
* @return array|mixed|\Psr\Http\Message\ResponseInterface |
|
290
|
|
|
* @throws \Exception |
|
291
|
|
|
*/ |
|
292
|
|
|
public function delete($endpoint, $params = null, $body = null, $headers = null, $options = []) |
|
293
|
|
|
{ |
|
294
|
|
|
return $this->makeRequest('DELETE', $endpoint, $params, $body, $headers, $options); |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
/** |
|
298
|
|
|
* Returns the last response object for inspection. |
|
299
|
|
|
* |
|
300
|
|
|
* @return \Psr\Http\Message\ResponseInterface |
|
301
|
|
|
*/ |
|
302
|
|
|
public function getLastResponse() |
|
303
|
|
|
{ |
|
304
|
|
|
return $this->last_response; |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
} |
|
308
|
|
|
|
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.