PluginProbe
PostNL for WooCommerce / 4.4.1
PostNL for WooCommerce v4.4.1
5.9.12 5.9.11 5.9.10 5.9.9 5.9.8 5.9.7 5.9.6 trunk 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 3.1.4 3.1.5 3.1.6 3.1.7 4.0.0 4.0.1 4.0.2 4.3.2 4.3.3 4.4.0 4.4.1 All 72 releases
woo-postnl / vendor / myparcelnl / sdk / src / Model / MyParcelRequest.php

MyParcelRequest.php in PostNL for WooCommerce 4.4.1, at vendor/myparcelnl/sdk/src/Model/MyParcelRequest.php

384 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php declare(strict_types=1);
2 /** @noinspection PhpInternalEntityUsedInspection */
3
4 /**
5 * This model represents one request
6 *
7 * If you want to add improvements, please create a fork in our GitHub:
8 * https://github.com/myparcelnl
9 *
10 * @author Reindert Vetter <[email protected]>
11 * @copyright 2010-2020 MyParcel
12 * @license http://creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.en_US CC BY-NC-ND 3.0 NL
13 * @link https://github.com/myparcelnl/sdk
14 * @since File available since Release v0.1.0
15 */
16
17 namespace MyParcelNL\Sdk\src\Model;
18
19 use MyParcelNL\Sdk\src\Exception\AccountNotActiveException;
20 use MyParcelNL\Sdk\src\Exception\ApiException;
21 use MyParcelNL\Sdk\src\Exception\MissingFieldException;
22 use MyParcelNL\Sdk\src\Helper\MyParcelCollection;
23 use MyParcelNL\Sdk\src\Helper\MyParcelCurl;
24 use MyParcelNL\Sdk\src\Helper\RequestError;
25 use MyParcelNL\Sdk\src\Model\Consignment\AbstractConsignment;
26 use MyParcelNL\Sdk\src\Support\Arr;
27
28 class MyParcelRequest
29 {
30 /**
31 * API URL
32 */
33 const REQUEST_URL = 'https://api.myparcel.nl';
34
35 /**
36 * Supported request types.
37 */
38 const REQUEST_TYPE_SHIPMENTS = 'shipments';
39 const REQUEST_TYPE_RETRIEVE_LABEL = 'shipment_labels';
40 const REQUEST_TYPE_RETRIEVE_PREPARED_LABEL = 'v2/shipment_labels';
41
42 const SHIPMENT_LABEL_PREPARE_ACTIVE_FROM = 25;
43
44 /**
45 * API headers
46 */
47 const REQUEST_HEADER_SHIPMENT = 'Content-Type: application/vnd.shipment+json;charset=utf-8;version=1.1';
48 const REQUEST_HEADER_RETRIEVE_SHIPMENT = 'Accept: application/json; charset=utf8';
49 const REQUEST_HEADER_RETRIEVE_LABEL_LINK = 'Accept: application/json; charset=utf8';
50 const REQUEST_HEADER_RETRIEVE_LABEL_PDF = 'Accept: application/pdf';
51 const REQUEST_HEADER_RETURN = 'Content-Type: application/vnd.return_shipment+json; charset=utf-8';
52 const REQUEST_HEADER_DELETE = 'Accept: application/json; charset=utf8';
53
54 /**
55 * Error codes
56 */
57 const ERROR_CODE_ACCOUNT_NOT_ACTIVATED = 3716;
58
59 /**
60 * @var string
61 */
62 private $api_key = '';
63 private $header = [];
64
65 /**
66 * @var string|null
67 */
68 private $body = '';
69 private $error = null;
70 private $errorCodes = [];
71 private $result = null;
72 private $userAgent = null;
73
74 /**
75 * @var array|null
76 */
77 private $query;
78
79 /**
80 * Get an item from tje result using "dot" notation.
81 *
82 * @param string $key
83 * @param string $pluck
84 *
85 * @return mixed
86 */
87 public function getResult($key = null, $pluck = null)
88 {
89 if (null === $key) {
90 return $this->result;
91 }
92
93 $result = Arr::get($this->result, $key);
94 if ($pluck) {
95 $result = Arr::pluck($result, $pluck);
96 }
97
98 return $result;
99 }
100
101 /**
102 * @return string
103 */
104 public function getError()
105 {
106 return $this->error;
107 }
108
109 /**
110 * Sets the parameters for an API call based on a string with all required request parameters and the requested API
111 * method.
112 *
113 * @param string $apiKey
114 * @param string|null $body
115 * @param string $requestHeader
116 *
117 * @return $this
118 */
119 public function setRequestParameters(string $apiKey, ?string $body, string $requestHeader): MyParcelRequest
120 {
121 $this->api_key = $apiKey;
122 $this->body = $body;
123
124 $header[] = $requestHeader;
125 $header[] = 'Authorization: basic ' . base64_encode($this->api_key);
126 $header[] = 'User-Agent: ' . $this->getUserAgent();
127 $this->header = $header;
128
129 return $this;
130 }
131
132 /**
133 * @param array $parameters
134 *
135 * @return \MyParcelNL\Sdk\src\Model\MyParcelRequest
136 */
137 public function setQuery(array $parameters)
138 {
139 $this->query = $parameters;
140
141 return $this;
142 }
143
144 /**
145 * send the created request to MyParcel
146 *
147 * @param string $method
148 * @param string $uri
149 *
150 * @return MyParcelRequest|array|false|string
151 * @throws ApiException
152 * @throws MissingFieldException
153 */
154 public function sendRequest($method = 'POST', $uri = self::REQUEST_TYPE_SHIPMENTS)
155 {
156 if (! $this->checkConfigForRequest()) {
157 return false;
158 }
159
160 $request = $this->instantiateCurl();
161
162 $this->setUserAgent();
163
164 $header = $this->header;
165 $url = $this->getRequestUrl($uri);
166 if ($method !== 'POST' && $this->body) {
167 $url .= '/' . $this->body;
168 }
169
170 if ($this->query) {
171 $url .= '?' . http_build_query($this->query);
172 }
173
174 $request->write($method, $url, $header, $this->body);
175 $this->setResult($request);
176 $request->close();
177
178 if ($this->getError()) {
179 switch (Arr::first($this->errorCodes)) {
180 case self::ERROR_CODE_ACCOUNT_NOT_ACTIVATED:
181 throw new AccountNotActiveException('Error ' . Arr::first($this->errorCodes) . ' Your account needs to be activated by MyParcel.');
182 default:
183 throw new ApiException('Error in MyParcel API request: ' . $this->getError() . ' Url: ' . $url . ' Request: ' . $this->body);
184 }
185 }
186
187 return $this;
188 }
189
190 /**
191 * @return string
192 */
193 public function getUserAgent()
194 {
195 return $this->userAgent;
196 }
197
198 /**
199 * @param string $userAgent
200 *
201 * @return $this
202 */
203 public function setUserAgent($userAgent = null)
204 {
205 if ($userAgent) {
206 $this->userAgent = $userAgent;
207 }
208 if ($this->getUserAgent() == null && $this->getUserAgentFromComposer() !== null) {
209 $this->userAgent = trim($this->getUserAgent() . ' ' . $this->getUserAgentFromComposer());
210 }
211
212 return $this;
213 }
214
215 /**
216 * Get version of SDK from composer file
217 */
218 public function getUserAgentFromComposer()
219 {
220 $composerData = $this->getComposerContents();
221
222 if ($composerData && ! empty($composerData['name'])
223 && $composerData['name'] == 'myparcelnl/sdk'
224 && ! empty($composerData['version'])
225 ) {
226 $version = str_replace('v', '', $composerData['version']);
227 } else {
228 $version = 'unknown';
229 }
230
231 return 'MyParcelNL-SDK/' . $version;
232 }
233
234 /**
235 * @param $size
236 * @param MyParcelCollection $collection
237 * @param $key
238 *
239 * @return string|null
240 */
241 public function getLatestDataParams($size, $collection, &$key)
242 {
243 $params = null;
244 $consignmentIds = $collection->getConsignmentIds($key);
245
246 if ($consignmentIds !== null) {
247 $params = implode(';', $consignmentIds) . '?size=' . $size;
248 } else {
249 $referenceIds = $this->getConsignmentReferenceIds($collection, $key);
250 if (! empty($referenceIds)) {
251 $params = '?reference_identifier=' . implode(';', $referenceIds) . '&size=' . $size;
252 }
253 }
254
255 return $params;
256 }
257
258 /**
259 * Check if MyParcel gives an error
260 *
261 * @return $this|void
262 */
263 private function checkMyParcelErrors()
264 {
265 if (! is_array($this->result) || empty($this->result['errors'])) {
266 return;
267 }
268
269 $error = reset($this->result['errors']);
270 $this->errorCodes = array_keys($error);
271 if ((int) key($error) > 0) {
272 $error = current($error);
273 }
274 $this->error = RequestError::getTotalMessage($error, $this->result);
275 }
276
277 /**
278 * Get request url
279 *
280 * @param string $uri
281 *
282 * @return string
283 */
284 private function getRequestUrl($uri)
285 {
286 $url = self::REQUEST_URL . '/' . $uri;
287
288 return $url;
289 }
290
291 /**
292 * Checks if all the requirements are set to send a request to MyParcel
293 *
294 * @return bool
295 * @throws MissingFieldException
296 */
297 private function checkConfigForRequest()
298 {
299 if (empty($this->api_key)) {
300 throw new MissingFieldException('api_key not found');
301 }
302
303 return true;
304 }
305
306 /**
307 * Get composer.json
308 *
309 * @return string|null
310 */
311 private function getComposerContents()
312 {
313 $composer_locations = [
314 'vendor/myparcelnl/sdk/composer.json',
315 './composer.json'
316 ];
317
318 foreach ($composer_locations as $composerFile) {
319 if (file_exists($composerFile)) {
320 return json_decode(file_get_contents($composerFile), true);
321 }
322 }
323
324 return null;
325 }
326
327 /**
328 * Get all consignment ids
329 *
330 * @param MyParcelCollection|AbstractConsignment[] $consignments
331 * @param $key
332 *
333 * @return array
334 */
335 private function getConsignmentReferenceIds($consignments, &$key)
336 {
337 $referenceIds = [];
338 foreach ($consignments as $consignment) {
339 if ($consignment->getReferenceId()) {
340 $referenceIds[] = $consignment->getReferenceId();
341 $key = $consignment->getApiKey();
342 }
343 }
344
345 return $referenceIds;
346 }
347
348 /**
349 * @param MyParcelCurl $request
350 */
351 private function setResult($request)
352 {
353 $response = $request->read();
354 if (preg_match("/^%PDF-1./", $response)) {
355 $this->result = $response;
356 } else {
357 $this->result = json_decode($response, true);
358
359 if ($response === false) {
360 $this->error = $request->getError();
361 }
362 $this
363 ->checkMyParcelErrors();
364 }
365 }
366
367 /**
368 * @return MyParcelCurl
369 */
370 private function instantiateCurl()
371 {
372 return (new MyParcelCurl())
373 ->setConfig([
374 'header' => 0,
375 'timeout' => 60,
376 ])
377 ->addOptions([
378 CURLOPT_POST => true,
379 CURLOPT_FOLLOWLOCATION => true,
380 CURLOPT_AUTOREFERER => true,
381 ]);
382 }
383 }
384