1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Trello\Api; |
4
|
|
|
|
5
|
|
|
use Trello\Client; |
6
|
|
|
use Trello\HttpClient\Message\ResponseMediator; |
7
|
|
|
use Trello\Exception\InvalidArgumentException; |
8
|
|
|
use Trello\Exception\BadMethodCallException; |
9
|
|
|
use Trello\Exception\MissingArgumentException; |
10
|
|
|
use \DateTime; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Abstract class for Api classes |
14
|
|
|
* |
15
|
|
|
* @author Christian Daguerre <[email protected]> |
16
|
|
|
* @author Joseph Bielawski <[email protected]> |
17
|
|
|
*/ |
18
|
|
|
abstract class AbstractApi implements ApiInterface |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* API sub namespace |
22
|
|
|
* |
23
|
|
|
* @var string |
24
|
|
|
*/ |
25
|
|
|
protected $path; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* The client |
29
|
|
|
* |
30
|
|
|
* @var Client |
31
|
|
|
*/ |
32
|
|
|
protected $client; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var array |
36
|
|
|
*/ |
37
|
|
|
public static $fields; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @param Client $client |
41
|
|
|
*/ |
42
|
334 |
|
public function __construct(Client $client) |
43
|
|
|
{ |
44
|
334 |
|
$this->client = $client; |
45
|
334 |
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Catches any undefined "get{$field}" calls, and passes them |
49
|
|
|
* to the getField() if the $field is in the $this->fields property |
50
|
|
|
* |
51
|
|
|
* @param string $method called method |
52
|
|
|
* @param array $arguments array of arguments passed to called method |
53
|
|
|
* |
54
|
|
|
* @return array |
55
|
|
|
* |
56
|
|
|
* @throws BadMethodCallException If the method does not start with "get" |
57
|
|
|
* or the field is not included in the $fields property |
58
|
|
|
*/ |
59
|
|
|
public function __call($method, $arguments) |
60
|
|
|
{ |
61
|
|
|
if (isset($this->fields) && substr($method, 0, 3) === 'get') { |
62
|
|
|
$property = lcfirst(substr($method, 3)); |
63
|
|
|
if (in_array($property, $this->fields) && count($arguments) === 2) { |
64
|
|
|
return $this->getField($arguments[0], $arguments[1]); |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
throw new BadMethodCallException(sprintf( |
69
|
|
|
'There is no method named "%s" in class "%s".', |
70
|
|
|
$method, |
71
|
|
|
get_called_class() |
72
|
|
|
)); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Get field names (properties) |
77
|
|
|
* |
78
|
|
|
* @return array array of fields |
79
|
|
|
*/ |
80
|
|
|
public function getFields() |
81
|
|
|
{ |
82
|
|
|
return static::$fields; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Get a field value by field name |
87
|
|
|
* |
88
|
|
|
* @param string $id the board's id |
89
|
|
|
* @param string $field the field |
90
|
|
|
* |
91
|
|
|
* @return mixed field value |
92
|
|
|
* |
93
|
|
|
* @throws InvalidArgumentException If the field does not exist |
94
|
|
|
*/ |
95
|
5 |
|
public function getField($id, $field) |
96
|
|
|
{ |
97
|
5 |
|
if (!in_array($field, static::$fields)) { |
98
|
2 |
|
throw new InvalidArgumentException(sprintf('There is no field named %s.', $field)); |
99
|
|
|
} |
100
|
|
|
|
101
|
3 |
|
$response = $this->get($this->path.'/'.rawurlencode($id).'/'.rawurlencode($field)); |
102
|
|
|
|
103
|
3 |
|
return isset($response['_value']) ? $response['_value'] : $response; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Send a GET request with query parameters. |
108
|
|
|
* |
109
|
|
|
* @param string $path Request path. |
110
|
|
|
* @param array $parameters GET parameters. |
111
|
|
|
* @param array $requestHeaders Request Headers. |
112
|
|
|
* |
113
|
|
|
* @return \Guzzle\Http\EntityBodyInterface|mixed|string |
114
|
|
|
*/ |
115
|
|
|
protected function get($path, array $parameters = array(), $requestHeaders = array()) |
116
|
|
|
{ |
117
|
|
|
$response = $this->client->getHttpClient()->get($path, $parameters, $requestHeaders); |
118
|
|
|
|
119
|
|
|
return ResponseMediator::getContent($response); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Send a HEAD request with query parameters |
124
|
|
|
* |
125
|
|
|
* @param string $path Request path. |
126
|
|
|
* @param array $parameters HEAD parameters. |
127
|
|
|
* @param array $requestHeaders Request headers. |
128
|
|
|
* |
129
|
|
|
* @return \Guzzle\Http\Message\Response |
130
|
|
|
*/ |
131
|
|
|
protected function head($path, array $parameters = array(), $requestHeaders = array()) |
132
|
|
|
{ |
133
|
|
|
$response = $this->client->getHttpClient()->request($path, null, 'HEAD', $requestHeaders, array( |
134
|
|
|
'query' => $parameters, |
135
|
|
|
)); |
136
|
|
|
|
137
|
|
|
return $response; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Send a POST request with JSON-encoded parameters. |
142
|
|
|
* |
143
|
|
|
* @param string $path Request path. |
144
|
|
|
* @param array $parameters POST parameters to be JSON encoded. |
145
|
|
|
* @param array $requestHeaders Request headers. |
146
|
|
|
* |
147
|
|
|
* @return mixed |
148
|
|
|
*/ |
149
|
|
|
protected function post($path, array $parameters = array(), $requestHeaders = array()) |
150
|
|
|
{ |
151
|
|
|
return $this->postRaw( |
152
|
|
|
$path, |
153
|
|
|
$this->createParametersBody($parameters), |
154
|
|
|
$requestHeaders |
155
|
|
|
); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Send a POST request with raw data. |
160
|
|
|
* |
161
|
|
|
* @param string $path Request path. |
162
|
|
|
* @param mixed $body Request body. |
163
|
|
|
* @param array $requestHeaders Request headers. |
164
|
|
|
* |
165
|
|
|
* @return \Guzzle\Http\EntityBodyInterface|mixed|string |
166
|
|
|
*/ |
167
|
|
|
protected function postRaw($path, $body, $requestHeaders = array()) |
168
|
|
|
{ |
169
|
|
|
$response = $this->client->getHttpClient()->post( |
170
|
|
|
$path, |
171
|
|
|
$body, |
172
|
|
|
$requestHeaders |
173
|
|
|
); |
174
|
|
|
|
175
|
|
|
return ResponseMediator::getContent($response); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Send a PATCH request with JSON-encoded parameters. |
180
|
|
|
* |
181
|
|
|
* @param string $path Request path. |
182
|
|
|
* @param array $parameters POST parameters to be JSON encoded. |
183
|
|
|
* @param array $requestHeaders Request headers. |
184
|
|
|
* |
185
|
|
|
* @return mixed |
186
|
|
|
*/ |
187
|
|
View Code Duplication |
protected function patch($path, array $parameters = array(), $requestHeaders = array()) |
|
|
|
|
188
|
|
|
{ |
189
|
|
|
$response = $this->client->getHttpClient()->patch( |
190
|
|
|
$path, |
191
|
|
|
$this->createParametersBody($parameters), |
192
|
|
|
$requestHeaders |
193
|
|
|
); |
194
|
|
|
|
195
|
|
|
return ResponseMediator::getContent($response); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Send a PUT request with JSON-encoded parameters. |
200
|
|
|
* |
201
|
|
|
* @param string $path Request path. |
202
|
|
|
* @param array $parameters POST parameters to be JSON encoded. |
203
|
|
|
* @param array $requestHeaders Request headers. |
204
|
|
|
* |
205
|
|
|
* @return mixed |
206
|
|
|
*/ |
207
|
|
|
protected function put($path, array $parameters = array(), $requestHeaders = array()) |
208
|
|
|
{ |
209
|
|
|
foreach ($parameters as $name => $parameter) { |
210
|
|
|
if (is_bool($parameter)) { |
211
|
|
|
$parameters[$name] = $parameter ? 'true' : 'false'; |
212
|
|
|
} |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
$response = $this->client->getHttpClient()->put( |
216
|
|
|
$path, |
217
|
|
|
$this->createParametersBody($parameters), |
218
|
|
|
$requestHeaders |
219
|
|
|
); |
220
|
|
|
|
221
|
|
|
return ResponseMediator::getContent($response); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Send a DELETE request with JSON-encoded parameters. |
226
|
|
|
* |
227
|
|
|
* @param string $path Request path. |
228
|
|
|
* @param array $parameters POST parameters to be JSON encoded. |
229
|
|
|
* @param array $requestHeaders Request headers. |
230
|
|
|
* |
231
|
|
|
* @return mixed |
232
|
|
|
*/ |
233
|
|
View Code Duplication |
protected function delete($path, array $parameters = array(), $requestHeaders = array()) |
|
|
|
|
234
|
|
|
{ |
235
|
|
|
$response = $this->client->getHttpClient()->delete( |
236
|
|
|
$path, |
237
|
|
|
$this->createParametersBody($parameters), |
238
|
|
|
$requestHeaders |
239
|
|
|
); |
240
|
|
|
|
241
|
|
|
return ResponseMediator::getContent($response); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Prepare request parameters. |
246
|
|
|
* |
247
|
|
|
* @param array $parameters Request parameters |
248
|
|
|
* |
249
|
|
|
* @return null|string |
250
|
|
|
*/ |
251
|
|
|
protected function createParametersBody(array $parameters) |
252
|
|
|
{ |
253
|
|
|
foreach ($parameters as $name => $parameter) { |
254
|
|
|
if (is_bool($parameter)) { |
255
|
|
|
$parameters[$name] = $parameter ? 'true' : 'false'; |
256
|
|
|
} elseif (is_array($parameter)) { |
257
|
|
|
foreach ($parameter as $subName => $subParameter) { |
258
|
|
|
if (is_bool($subParameter)) { |
259
|
|
|
$subParameter = $subParameter ? 'true' : 'false'; |
260
|
|
|
} |
261
|
|
|
$parameters[$name.'/'.$subName] = $subParameter; |
262
|
|
|
} |
263
|
|
|
unset($parameters[$name]); |
264
|
|
|
} elseif ($parameter instanceof DateTime) { |
265
|
|
|
$parameters[$name] = $parameter->format($parameter::ATOM); |
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
return $parameters; |
270
|
|
|
} |
271
|
|
|
|
272
|
191 |
|
protected function getPath($id = null) |
273
|
|
|
{ |
274
|
191 |
|
if ($id) { |
275
|
91 |
|
return preg_replace('/\#id\#/', $id, $this->path); |
276
|
|
|
} |
277
|
|
|
|
278
|
100 |
|
return $this->path; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Validate parameters array |
283
|
|
|
* |
284
|
|
|
* @param string[] $required required properties (array keys) |
285
|
|
|
* @param array $params array to check for existence of the required keys |
286
|
|
|
* |
287
|
|
|
* @throws MissingArgumentException if a required parameter is missing |
288
|
|
|
*/ |
289
|
30 |
View Code Duplication |
protected function validateRequiredParameters(array $required, array $params) |
|
|
|
|
290
|
|
|
{ |
291
|
30 |
|
foreach ($required as $param) { |
292
|
30 |
|
if (!isset($params[$param])) { |
293
|
18 |
|
throw new MissingArgumentException(sprintf('The "%s" parameter is required.', $param)); |
294
|
|
|
} |
295
|
15 |
|
} |
296
|
12 |
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Validate allowed parameters array |
300
|
|
|
* Checks whether the passed parameters are allowed |
301
|
|
|
* |
302
|
|
|
* @param string[] $allowed allowed properties |
303
|
|
|
* @param array|string $params array to check |
304
|
|
|
* @param string $paramName |
305
|
|
|
* |
306
|
|
|
* @return array array of validated parameters |
307
|
|
|
* |
308
|
|
|
* @throws InvalidArgumentException if a parameter is not allowed |
309
|
|
|
*/ |
310
|
70 |
|
protected function validateAllowedParameters(array $allowed, $params, $paramName) |
311
|
|
|
{ |
312
|
70 |
|
if (!is_array($params)) { |
313
|
61 |
|
$params = array($params); |
314
|
61 |
|
} |
315
|
|
|
|
316
|
70 |
|
foreach ($params as $param) { |
317
|
70 |
|
if (!in_array($param, $allowed)) { |
318
|
21 |
|
throw new InvalidArgumentException(sprintf( |
319
|
21 |
|
'The "%s" parameter may contain only values within "%s". "%s" given.', |
320
|
21 |
|
$paramName, |
321
|
21 |
|
implode(", ", $allowed), |
322
|
|
|
$param |
323
|
21 |
|
)); |
324
|
|
|
} |
325
|
49 |
|
} |
326
|
|
|
|
327
|
49 |
|
return $params; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Validate that the params array includes at least one of |
332
|
|
|
* the keys in a given array |
333
|
|
|
* |
334
|
|
|
* @param string[] $atLeastOneOf allowed properties |
335
|
|
|
* @param array $params array to check |
336
|
|
|
* |
337
|
|
|
* @return boolean |
338
|
|
|
* |
339
|
|
|
* @throws MissingArgumentException |
340
|
|
|
*/ |
341
|
6 |
View Code Duplication |
protected function validateAtLeastOneOf(array $atLeastOneOf, array $params) |
|
|
|
|
342
|
|
|
{ |
343
|
6 |
|
foreach ($atLeastOneOf as $param) { |
344
|
6 |
|
if (isset($params[$param])) { |
345
|
3 |
|
return true; |
346
|
|
|
} |
347
|
4 |
|
} |
348
|
|
|
|
349
|
3 |
|
throw new MissingArgumentException(sprintf( |
350
|
3 |
|
'You need to provide at least one of the following parameters "%s".', |
351
|
3 |
|
implode('", "', $atLeastOneOf) |
352
|
3 |
|
)); |
353
|
|
|
} |
354
|
|
|
} |
355
|
|
|
|
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.