Completed
Pull Request — master (#151)
by
unknown
02:02
created

MoipResource::generateListPath()   B

Complexity

Conditions 6
Paths 20

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 12
nc 20
nop 3
dl 0
loc 24
rs 8.5125
c 0
b 0
f 0
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
    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
    protected function getIfSetDateTime($key, stdClass $data = null)
133
    {
134
        return $this->getIfSetDateFmt($key, \DateTime::ATOM, $data);
135
    }
136
137
    /**
138
     * Specify data which should be serialized to JSON.
139
     *
140
     * @return \stdClass
141
     */
142
    public function jsonSerialize()
143
    {
144
        return $this->data;
145
    }
146
147
    /**
148
     * Generate URL to request.
149
     *
150
     * @param $action
151
     * @param $id
152
     *
153
     * @return string
154
     */
155
    public function generatePath($action, $id = null)
156
    {
157
        if (!is_null($id)) {
158
            return sprintf('%s/%s/%s/%s', self::VERSION, static::PATH, $action, $id);
159
        }
160
161
        return sprintf('%s/%s/%s', self::VERSION, static::PATH, $action);
162
    }
163
164
    /**
165
     * Generate URL to request a get list.
166
     *
167
     * @param Pagination $pagination
168
     * @param Filters    $filters
169
     * @param string     $qParam     Query a specific value.
170
     *
171
     * @return string
172
     */
173
    public function generateListPath(Pagination $pagination = null, Filters $filters = null, $qParam = '')
174
    {
175
        $queryParams = [];
176
177
        if (!is_null($pagination)) {
178
            if ($pagination->getLimit() != 0) {
179
                $queryParams['limit'] = $pagination->getLimit();
180
            }
181
182
            if ($pagination->getOffset() >= 0) {
183
                $queryParams['offset'] = $pagination->getOffset();
184
            }
185
        }
186
187
        if (!is_null($filters)) {
188
            $queryParams['filters'] = $filters->__toString();
189
        }
190
191
        if (!empty($qParam)) {
192
            $queryParams['q'] = $qParam;
193
        }
194
195
        return sprintf('/%s/%s?%s', self::VERSION, static::PATH, http_build_query($queryParams));
196
    }
197
198
    /**
199
     * Execute a http request. If payload == null no body will be sent. Empty body ('{}') is supported by sending a
200
     * empty stdClass.
201
     *
202
     * @param string     $path
203
     * @param string     $method
204
     * @param mixed|null $payload
205
     *
206
     * @throws Exceptions\ValidationException  if the API returns a 4xx http status code. Usually means invalid data was sent.
207
     * @throws Exceptions\UnautorizedException if the API returns a 401 http status code. Check API token and key.
208
     * @throws Exceptions\UnexpectedException  if the API returns a 500 http status code or something unexpected happens (ie.: Network error).
209
     *
210
     * @return stdClass
211
     */
212
    protected function httpRequest($path, $method, $payload = null)
213
    {
214
        $http_sess = $this->moip->getSession();
215
        $headers = [];
216
        $body = null;
217
        if ($payload !== null) {
218
            $body = json_encode($payload, JSON_UNESCAPED_SLASHES);
219
            if ($body) {// if it's json serializable
220
                $headers['Content-Type'] = 'application/json';
221
            } else {
222
                $body = null;
223
            }
224
        }
225
226
        try {
227
            $http_response = $http_sess->request($path, $headers, $body, $method);
228
        } catch (Requests_Exception $e) {
229
            throw new Exceptions\UnexpectedException($e);
230
        }
231
232
        $code = $http_response->status_code;
233
        $response_body = $http_response->body;
234
        if ($code >= 200 && $code < 300) {
235
            return json_decode($response_body);
236
        } elseif ($code == 401) {
237
            throw new Exceptions\UnautorizedException();
238
        } elseif ($code >= 400 && $code <= 499) {
239
            $errors = Exceptions\Error::parseErrors($response_body);
240
            throw new Exceptions\ValidationException($code, $errors);
241
        }
242
        throw new Exceptions\UnexpectedException();
243
    }
244
245
    /**
246
     * Find by path.
247
     *
248
     * @param string $path
249
     *
250
     * @return stdClass
251
     */
252
    public function getByPath($path)
253
    {
254
        $response = $this->httpRequest($path, Requests::GET);
255
256
        return $this->populate($response);
257
    }
258
259
    /**
260
     * Create a new item in Moip.
261
     *
262
     * @param string $path
263
     *
264
     * @return stdClass
265
     */
266
    public function createResource($path)
267
    {
268
        $response = $this->httpRequest($path, Requests::POST, $this);
269
270
        return $this->populate($response);
271
    }
272
273
    /**
274
     * Delete a new item in Moip.
275
     *
276
     * @param $path
277
     *
278
     * @return mixed
279
     */
280
    public function deleteByPath($path)
281
    {
282
        return $this->httpRequest($path, Requests::DELETE);
283
    }
284
}
285