1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Moip\Resource; |
4
|
|
|
|
5
|
|
|
use JsonSerializable; |
6
|
|
|
use Moip\Exceptions; |
7
|
|
|
use Moip\Helper\Filters; |
8
|
|
|
use Moip\Helper\Links; |
9
|
|
|
use Moip\Helper\Pagination; |
10
|
|
|
use Moip\Moip; |
11
|
|
|
use Requests; |
12
|
|
|
use Requests_Exception; |
13
|
|
|
use stdClass; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Class MoipResource. |
17
|
|
|
*/ |
18
|
|
|
abstract class MoipResource implements JsonSerializable |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* Version of API. |
22
|
|
|
* |
23
|
|
|
* @const string |
24
|
|
|
*/ |
25
|
|
|
const VERSION = 'v2'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var \Moip\Moip |
29
|
|
|
*/ |
30
|
|
|
protected $moip; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var \stdClass |
34
|
|
|
*/ |
35
|
|
|
protected $data; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Initialize a new instance. |
39
|
|
|
*/ |
40
|
|
|
abstract protected function initialize(); |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Mount information of a determined object. |
44
|
|
|
* |
45
|
|
|
* @param \stdClass $response |
46
|
|
|
* |
47
|
|
|
* @return mixed |
48
|
|
|
*/ |
49
|
|
|
abstract protected function populate(stdClass $response); |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Create a new instance. |
53
|
|
|
* |
54
|
|
|
* @param \Moip\Moip $moip |
55
|
|
|
*/ |
56
|
|
|
public function __construct(Moip $moip) |
57
|
|
|
{ |
58
|
|
|
$this->moip = $moip; |
59
|
|
|
$this->data = new stdClass(); |
60
|
|
|
$this->initialize(); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Get a key of an object if it exists. |
65
|
|
|
* |
66
|
|
|
* @param string $key |
67
|
|
|
* @param \stdClass|null $data |
68
|
|
|
* |
69
|
|
|
* @return mixed |
70
|
|
|
*/ |
71
|
|
|
protected function getIfSet($key, stdClass $data = null) |
72
|
|
|
{ |
73
|
|
|
if (empty($data)) { |
74
|
|
|
$data = $this->data; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
if (isset($data->$key)) { |
78
|
|
|
return $data->$key; |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @return \Moip\Helper\Links |
84
|
|
|
*/ |
85
|
|
|
public function getLinks() |
86
|
|
|
{ |
87
|
|
|
$links = $this->getIfSet('_links'); |
88
|
|
|
|
89
|
|
|
if ($links !== null) { |
90
|
|
|
return new Links($links); |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @param $key |
96
|
|
|
* @param $fmt |
97
|
|
|
* @param stdClass|null $data |
98
|
|
|
* |
99
|
|
|
* @return bool|\DateTime|null |
100
|
|
|
*/ |
101
|
|
View Code Duplication |
protected function getIfSetDateFmt($key, $fmt, stdClass $data = null) |
|
|
|
|
102
|
|
|
{ |
103
|
|
|
$val = $this->getIfSet($key, $data); |
104
|
|
|
if (!empty($val)) { |
105
|
|
|
$dt = \DateTime::createFromFormat($fmt, $val); |
106
|
|
|
|
107
|
|
|
return $dt ? $dt : null; |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Get a key, representing a date (Y-m-d), of an object if it exists. |
113
|
|
|
* |
114
|
|
|
* @param string $key |
115
|
|
|
* @param stdClass|null $data |
116
|
|
|
* |
117
|
|
|
* @return \DateTime|null |
118
|
|
|
*/ |
119
|
|
|
protected function getIfSetDate($key, stdClass $data = null) |
120
|
|
|
{ |
121
|
|
|
return $this->getIfSetDateFmt($key, 'Y-m-d', $data); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Get a key representing a datetime (\Datetime::ATOM), of an object if it exists. |
126
|
|
|
* |
127
|
|
|
* @param string $key |
128
|
|
|
* @param stdClass|null $data |
129
|
|
|
* |
130
|
|
|
* @return \DateTime|null |
131
|
|
|
*/ |
132
|
|
View Code Duplication |
protected function getIfSetDateTime($key, stdClass $data = null) |
|
|
|
|
133
|
|
|
{ |
134
|
|
|
$rawDateTime = $this->getIfSet($key, $data); |
135
|
|
|
|
136
|
|
|
$dateTime = null; |
137
|
|
|
if (!empty($rawDateTime)) { |
138
|
|
|
$dateTime = new \DateTime($rawDateTime); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $dateTime; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Specify data which should be serialized to JSON. |
146
|
|
|
* |
147
|
|
|
* @return \stdClass |
148
|
|
|
*/ |
149
|
|
|
public function jsonSerialize() |
150
|
|
|
{ |
151
|
|
|
return $this->data; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Generate URL to request. |
156
|
|
|
* |
157
|
|
|
* @param $action |
158
|
|
|
* @param $id |
159
|
|
|
* |
160
|
|
|
* @return string |
161
|
|
|
*/ |
162
|
|
|
public function generatePath($action, $id = null) |
163
|
|
|
{ |
164
|
|
|
if (!is_null($id)) { |
165
|
|
|
return sprintf('%s/%s/%s/%s', self::VERSION, static::PATH, $action, $id); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return sprintf('%s/%s/%s', self::VERSION, static::PATH, $action); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Generate URL to request a get list. |
173
|
|
|
* |
174
|
|
|
* @param Pagination $pagination |
175
|
|
|
* @param Filters $filters |
176
|
|
|
* @param array $params |
177
|
|
|
* |
178
|
|
|
* @return string |
179
|
|
|
*/ |
180
|
|
|
public function generateListPath(Pagination $pagination = null, Filters $filters = null, $params = []) |
181
|
|
|
{ |
182
|
|
|
$queryParams = []; |
183
|
|
|
|
184
|
|
|
if (!is_null($pagination)) { |
185
|
|
|
if ($pagination->getLimit() != 0) { |
186
|
|
|
$queryParams['limit'] = $pagination->getLimit(); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
if ($pagination->getOffset() >= 0) { |
190
|
|
|
$queryParams['offset'] = $pagination->getOffset(); |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
if (!is_null($filters)) { |
195
|
|
|
$queryParams['filters'] = $filters->__toString(); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
if (!empty($params)) { |
199
|
|
|
$queryParams = array_merge($queryParams, $params); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
if (!empty($queryParams)) { |
203
|
|
|
return sprintf('/%s/%s?%s', self::VERSION, static::PATH, http_build_query($queryParams)); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return sprintf('/%s/%s', self::VERSION, static::PATH); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Execute a http request. If payload == null no body will be sent. Empty body ('{}') is supported by sending a |
211
|
|
|
* empty stdClass. |
212
|
|
|
* |
213
|
|
|
* @param string $path |
214
|
|
|
* @param string $method |
215
|
|
|
* @param mixed|null $payload |
216
|
|
|
* |
217
|
|
|
* @throws Exceptions\ValidationException if the API returns a 4xx http status code. Usually means invalid data was sent. |
218
|
|
|
* @throws Exceptions\UnautorizedException if the API returns a 401 http status code. Check API token and key. |
219
|
|
|
* @throws Exceptions\UnexpectedException if the API returns a 500 http status code or something unexpected happens (ie.: Network error). |
220
|
|
|
* |
221
|
|
|
* @return stdClass |
222
|
|
|
*/ |
223
|
|
|
protected function httpRequest($path, $method, $payload = null) |
224
|
|
|
{ |
225
|
|
|
$http_sess = $this->moip->getSession(); |
226
|
|
|
$headers = []; |
227
|
|
|
$body = null; |
228
|
|
|
if ($payload !== null) { |
229
|
|
|
$body = json_encode($payload, JSON_UNESCAPED_SLASHES); |
230
|
|
|
if ($body) {// if it's json serializable |
231
|
|
|
$headers['Content-Type'] = 'application/json'; |
232
|
|
|
} else { |
233
|
|
|
$body = null; |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
try { |
238
|
|
|
$http_response = $http_sess->request($path, $headers, $body, $method); |
239
|
|
|
} catch (Requests_Exception $e) { |
240
|
|
|
throw new Exceptions\UnexpectedException($e); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
$code = $http_response->status_code; |
244
|
|
|
$response_body = $http_response->body; |
245
|
|
|
if ($code >= 200 && $code < 300) { |
246
|
|
|
return json_decode($response_body); |
247
|
|
|
} elseif ($code == 401) { |
248
|
|
|
throw new Exceptions\UnautorizedException(); |
249
|
|
|
} elseif ($code >= 400 && $code <= 499) { |
250
|
|
|
$errors = Exceptions\Error::parseErrors($response_body); |
251
|
|
|
|
252
|
|
|
throw new Exceptions\ValidationException($code, $errors); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
throw new Exceptions\UnexpectedException(); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Find by path. |
260
|
|
|
* |
261
|
|
|
* @param string $path |
262
|
|
|
* |
263
|
|
|
* @return stdClass |
264
|
|
|
*/ |
265
|
|
|
public function getByPath($path) |
266
|
|
|
{ |
267
|
|
|
$response = $this->httpRequest($path, Requests::GET); |
268
|
|
|
|
269
|
|
|
return $this->populate($response); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* Find by path with no populate method. |
274
|
|
|
* |
275
|
|
|
* @param string $path |
276
|
|
|
* |
277
|
|
|
* @return stdClass |
278
|
|
|
*/ |
279
|
|
|
public function getByPathNoPopulate($path) |
280
|
|
|
{ |
281
|
|
|
return $this->httpRequest($path, Requests::GET); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Create a new item in Moip. |
286
|
|
|
* |
287
|
|
|
* @param string $path |
288
|
|
|
* |
289
|
|
|
* @return stdClass |
290
|
|
|
*/ |
291
|
|
|
public function createResource($path) |
292
|
|
|
{ |
293
|
|
|
$response = $this->httpRequest($path, Requests::POST, $this); |
294
|
|
|
|
295
|
|
|
return $this->populate($response); |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Delete a new item in Moip. |
300
|
|
|
* |
301
|
|
|
* @param $path |
302
|
|
|
* |
303
|
|
|
* @return mixed |
304
|
|
|
*/ |
305
|
|
|
public function deleteByPath($path) |
306
|
|
|
{ |
307
|
|
|
return $this->httpRequest($path, Requests::DELETE); |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
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.