-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathEsiResponse.php
298 lines (242 loc) · 7.17 KB
/
EsiResponse.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
<?php
/*
* This file is part of SeAT
*
* Copyright (C) 2015 to 2022 Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
namespace Seat\Eseye\Containers;
use ArrayObject;
use Carbon\Carbon;
/**
* Class EsiResponse.
*
* @package Seat\Eseye\Containers
*/
class EsiResponse extends ArrayObject
{
/**
* @var string
*/
public $raw;
/**
* @var array
*/
public $headers;
/**
* @var array
*/
public $raw_headers;
/**
* @var int
*/
public $error_limit;
/**
* @var int
*/
public $pages;
/**
* @var array
*/
protected $expires_at;
/**
* @var string
*/
protected $response_code;
/**
* @var mixed
*/
protected $error_message;
/**
* @var mixed
*/
protected $optional_return;
/**
* @var bool
*/
protected $cached_load = false;
/**
* EsiResponse constructor.
*
* @param string $data
* @param array $headers
* @param string $expires
* @param int $response_code
*/
public function __construct(
string $data, array $headers, string $expires, int $response_code)
{
// set the raw data to the raw property
$this->raw = $data;
// Normalize and parse the response headers
$this->parseHeaders($headers);
// decode and create an object from the data
$data = json_decode($data);
// Ensure that the value for 'expires' is longer than
// 2 characters. The shortest expected value is 'now'. If it
// is not longer than 2 characters it might be empty.
$this->expires_at = strlen($expires) > 2 ? $expires : 'now';
$this->response_code = $response_code;
if (is_object($data)) {
// If there is an error, set that.
if (property_exists($data, 'error'))
$this->error_message = $data->error;
// If there is an error description, set that.
if (property_exists($data, 'error_description'))
$this->error_message .= ': ' . $data->error_description;
}
// If the query failed to contact the ESI endpoint
if ($this->response_code === 502)
$this->error_message = 'Bad gateway';
// Run the parent constructor
parent::__construct(is_array($data) ? (array) $data : (object) $data, ArrayObject::ARRAY_AS_PROPS);
}
/**
* Parse an array of header key value pairs.
*
* Interesting header values such as X-Esi-Error-Limit-Remain
* and X-Pages are automatically mapped to properties in this
* object.
*
* @param array $headers
*/
private function parseHeaders(array $headers)
{
// Set the raw headers as we got from the constructor.
$this->raw_headers = $headers;
// flatten the headers array so that values are not arrays themselves
// but rather simple key value pairs.
$headers = array_map(function ($value) {
if (! is_array($value))
return $value;
return implode(';', $value);
}, $headers);
// Set the parsed headers.
$this->headers = $headers;
// Check for some header values that might be interesting
// such as the current error limit and number of pages
// available.
$this->hasHeader('X-Esi-Error-Limit-Remain') ?
$this->error_limit = (int) $this->getHeader('X-Esi-Error-Limit-Remain') : null;
$this->hasHeader('X-Pages') ? $this->pages = (int) $this->getHeader('X-Pages') : null;
}
/**
* A helper method when a key might not exist within the
* response object.
*
* @param string $index
* @return mixed
*/
public function optional(string $index)
{
if (! $this->offsetExists($index))
return null;
return $this->$index;
}
/**
* Determine if this containers data should be considered
* expired.
*
* Expiry is calculated by taking the expiry time and comparing
* that to the local time. Before comparison though, the local
* time is converted to the timezone in which the expiry time
* is recorded. The resultant local time is then checked to
* ensure that the expiry is not less than local time.
*
* @return bool
*/
public function expired(): bool
{
if ($this->expires()->lte(
carbon()->now($this->expires()->timezoneName))
)
return true;
return false;
}
/**
* @return \Carbon\Carbon
*/
public function expires(): Carbon
{
return carbon($this->expires_at);
}
/**
* @return null|string
*/
public function error()
{
return $this->error_message;
}
/**
* @return int
*/
public function getErrorCode(): int
{
return $this->response_code;
}
/**
* @return bool
*/
public function setIsCachedLoad(): bool
{
return $this->cached_load = true;
}
/**
* @return bool
*/
public function isCachedLoad(): bool
{
return $this->cached_load;
}
/**
* @param string $name
* @return bool
*/
public function hasHeader(string $name)
{
// turn headers into case insensitive array
$key_map = array_change_key_case($this->headers, CASE_LOWER);
// track for the requested header name
return array_key_exists(strtolower($name), $key_map);
}
/**
* @param string $name
* @return mixed|null
*/
public function getHeader(string $name)
{
// turn header name into case insensitive
$insensitive_key = strtolower($name);
// turn headers into case insensitive array
$key_map = array_change_key_case($this->headers, CASE_LOWER);
// track for the requested header name and return its value if exists
if (array_key_exists($insensitive_key, $key_map))
return $key_map[$insensitive_key];
return null;
}
/**
* @param \Carbon\Carbon $date
*/
public function setExpires(Carbon $date)
{
// turn headers into case insensitive array
$key_map = array_change_key_case($this->headers, CASE_LOWER);
// update expires header with provided date
$key_map['expires'] = $date->toRfc7231String();
$this->expires_at = strlen($key_map['expires']) > 2 ? $key_map['expires'] : 'now';
$this->headers = $key_map;
}
}