Passed
Push — main ( 717dd1...e6a32b )
by Vasil
04:17
created

Speedy   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 454
Duplicated Lines 0 %

Test Coverage

Coverage 90.68%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 231
c 5
b 0
f 0
dl 0
loc 454
ccs 107
cts 118
cp 0.9068
rs 10
wmc 17

17 Methods

Rating   Name   Duplication   Size   Complexity  
A createPayload() 0 5 1
A print() 0 3 1
A findStreet() 0 13 1
A getContents() 0 5 1
A getContractClient() 0 14 1
A findSite() 0 13 1
A findOffice() 0 13 1
A createRequest() 0 9 1
A __construct() 0 8 1
A cancelShipment() 0 3 1
A findState() 0 14 1
A createShipment() 0 14 1
A findComplex() 0 13 1
A findCountry() 0 14 1
A destination() 0 13 1
A track() 0 13 1
A calculation() 0 13 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace VasilDakov\Speedy;
6
7
use Fig\Http\Message\RequestMethodInterface;
8
use Psr\Http\Client\ClientExceptionInterface;
9
use Psr\Http\Client\ClientInterface;
10
use Psr\Http\Message\RequestFactoryInterface;
11
use Psr\Http\Message\RequestInterface;
12
use Throwable;
13
use VasilDakov\Speedy\Service\Calculation\CalculationRequest;
14
use VasilDakov\Speedy\Service\Calculation\CalculationResponse;
15
use VasilDakov\Speedy\Service\Calculation\CalculationResponseFactory;
16
use VasilDakov\Speedy\Service\Client\GetContractClientsRequest;
17
use VasilDakov\Speedy\Service\Client\GetContractClientsResponse;
18
use VasilDakov\Speedy\Service\Client\GetContractClientsResponseFactory;
19
use VasilDakov\Speedy\Service\Location;
20
use VasilDakov\Speedy\Service\Location\Complex\FindComplexRequest;
21
use VasilDakov\Speedy\Service\Location\Complex\FindComplexResponse;
22
use VasilDakov\Speedy\Service\Location\Office\FindOfficeRequest;
23
use VasilDakov\Speedy\Service\Location\Office\FindOfficeResponse;
24
use VasilDakov\Speedy\Service\Location\Site\FindSiteResponse;
25
use VasilDakov\Speedy\Service\Printing\PrintRequest;
26
use VasilDakov\Speedy\Service\Printing\PrintResponse;
27
use VasilDakov\Speedy\Service\Service\DestinationServicesRequest;
28
use VasilDakov\Speedy\Service\Service\DestinationServicesResponse;
29
use VasilDakov\Speedy\Service\Service\DestinationServicesResponseFactory;
30
use VasilDakov\Speedy\Service\Shipment\CancelShipmentRequest;
31
use VasilDakov\Speedy\Service\Shipment\CancelShipmentResponse;
32
use VasilDakov\Speedy\Service\Shipment\CreateShipmentRequest;
33
use VasilDakov\Speedy\Service\Shipment\CreateShipmentResponse;
34
use VasilDakov\Speedy\Service\Shipment\CreateShipmentResponseFactory;
35
use VasilDakov\Speedy\Service\Track\TrackRequest;
36
use VasilDakov\Speedy\Service\Track\TrackResponse;
37
38
use VasilDakov\Speedy\Service\Track\TrackResponseFactory;
39
40
use function Amp\Promise\rethrow;
41
use function array_merge;
42
use function json_encode;
43
44
/**
45
 * Class Speedy
46
 *
47
 * @author    Vasil Dakov <[email protected]>
48
 * @copyright 2009-2022 Neutrino.bg
49
 * @version   1.0
50
 */
51
final class Speedy
52
{
53
    public const API_URL = 'https://api.speedy.bg/v1';
54
    public const USER_NAME = 'userName';
55
    public const PASSWORD  = 'password';
56
    public const LANGUAGE  = 'language';
57
    public const CLIENT_SYSTEM_ID = 'clientSystemId';
58
    public const SENDER = 'sender';
59
    public const CLIENT_ID = 'clientId';
60
    public const PRIVATE_PERSON = 'privatePerson';
61
    public const DROP_OFF_OFFICE_ID = 'dropoffOfficeId';
62
    public const PICKUP_OFFICE_ID = 'pickupOfficeId';
63
    public const ADDRESS_LOCATION = 'addressLocation';
64
    public const COUNTRY_ID = 'countryId';
65
    public const STATE_ID = 'stateId';
66
    public const SITE_ID = 'siteId';
67
    public const SITE_TYPE = 'siteType';
68
    public const SITE_NAME = 'siteName';
69
    public const POST_CODE = 'postCode';
70
    public const RECIPIENT = 'recipient';
71
    public const SERVICE = 'service';
72
    public const PICKUP_DATE = 'pickupDate';
73
    public const AUTO_ADJUST_PICKUP_DATE = 'autoAdjustPickupDate';
74
    public const SERVICE_IDS = 'serviceIds';
75
    public const DEFERRED_DAYS = 'deferredDays';
76
    public const SATURDAY_DELIVERY = 'saturdayDelivery';
77
    public const ADDITIONAL_SERVICES = 'additionalServices';
78
    public const FIXED_TIME_DELIVERY = 'fixedTimeDelivery';
79
    public const SPECIAL_DELIVERY_ID = 'specialDeliveryId';
80
    public const DELIVERY_TO_FLOOR = 'deliveryToFloor';
81
    public const COD = 'cod';
82
    public const AMOUNT = 'amount';
83
    public const CURRENCY_CODE = 'currencyCode';
84
    public const PROCESSING_TYPE = 'processingType';
85
    public const PAYOUT_TO_THIRD_PARTY = 'payoutToThirdParty';
86
    public const INCLUDE_SHIPPING_PRICE = 'includeShippingPrice';
87
    public const OBP_DETAILS = 'obpDetails';
88
    public const OPTION = 'option';
89
    public const RETURN_SHIPMENT_SERVICE_ID = 'returnShipmentServiceId';
90
    public const RETURN_SHIPMENT_PAYER = 'returnShipmentPayer';
91
    public const DECLARED_VALUE = 'declaredValue';
92
    public const FRAGILE = 'fragile';
93
    public const IGNORE_IF_NOT_APPLICABLE = 'ignoreIfNotApplicable';
94
    public const RETURNS = 'returns';
95
    public const ROD = 'rod';
96
    public const ENABLED = 'enabled';
97
    public const COMMENT = 'comment';
98
    public const RETURN_TO_CLIENT_ID = 'returnToClientId';
99
    public const RETURN_TO_OFFICE_ID = 'returnToOfficeId';
100
    public const THIRD_PARTY_PAYER = 'thirdPartyPayer';
101
    public const RETURN_RECEIPT = 'returnReceipt';
102
    public const SWAP = 'swap';
103
    public const SERVICE_ID = 'serviceId';
104
    public const PARCELS_COUNT = 'parcelsCount';
105
    public const ROP = 'rop';
106
    public const PALLETS = 'pallets';
107
    public const RETURN_VOUCHER = 'returnVoucher';
108
    public const PAYER = 'payer';
109
    public const CONTENT = 'content';
110
    public const TOTAL_WEIGHT = 'totalWeight';
111
    public const DOCUMENTS = 'documents';
112
    public const PALLETIZED = 'palletized';
113
    public const PARCELS = 'parcels';
114
    public const ID = 'id';
115
    public const SEQ_NO = 'seqNo';
116
    public const PACKAGE_UNIQUE_NUMBER = 'packageUniqueNumber';
117
    public const WEIGHT = 'weight';
118
    public const EXTERNAL_CARRIER_PARCEL_NUMBER = 'externalCarrierParcelNumber';
119
    public const SIZE = 'size';
120
    public const WIDTH = 'width';
121
    public const DEPTH = 'depth';
122
    public const HEIGHT = 'height';
123
    public const PAYMENT = 'payment';
124
    public const COURIER_SERVICE_PAYER = 'courierServicePayer';
125
    public const DECLARED_VALUE_PAYER = 'declaredValuePayer';
126
    public const PACKAGE_PAYER = 'packagePayer';
127
    public const THIRD_PARTY_CLIENT_ID = 'thirdPartyClientId';
128
    public const DISCOUNT_CARD_ID = 'discountCardId';
129
    public const CONTRACT_ID = 'contractId';
130
    public const CARD_ID = 'cardId';
131
    public const NAME = 'name';
132
    public const TYPE = 'type';
133
    public const MUNICIPALITY = 'municipality';
134
    public const REGION = 'region';
135
    public const LIMIT = 'limit';
136
    public const ISO_ALPHA_3 = 'isoAlpha3';
137
    public const ISO_ALPHA_2 = 'isoAlpha2';
138
    public const ADDRESS = 'address';
139
    public const STREET_ID = 'streetId';
140
    public const STREET_TYPE = 'streetType';
141
    public const STREET_NAME = 'streetName';
142
    public const STREET_NO = 'streetNo';
143
    public const COMPLEX_ID = 'complexId';
144
    public const COMPLEX_TYPE = 'complexType';
145
    public const COMPLEX_NAME = 'complexName';
146
    public const BLOCK_NO = 'blockNo';
147
    public const ENTRANCE_NO = 'entranceNo';
148
    public const FLOOR_NO = 'floorNo';
149
    public const APARTMENT_NO = 'apartmentNo';
150
    public const POI_ID = 'poiId';
151
    public const ADDRESS_NOTE = 'addressNote';
152
    public const ADDRESS_LINE_1 = 'addressLine1';
153
    public const ADDRESS_LINE_2 = 'addressLine2';
154
    public const X = 'x';
155
    public const Y = 'y';
156
    public const SHIPMENT_NOTE = 'shipmentNote';
157
    public const REF_1 = 'ref1';
158
    public const REF_2 = 'ref2';
159
    public const PHONE_1 = 'phone1';
160
    public const PHONE_2 = 'phone2';
161
    public const PHONE_3 = 'phone3';
162
    public const NUMBER = 'number';
163
    public const EXTENSION = 'extension';
164
    public const CLIENT_NAME = 'clientName';
165
    public const CONTACT_NAME = 'contactName';
166
    public const EMAIL = 'email';
167
    public const OBJECT_NAME = 'objectName';
168
    public const CONTENTS = 'contents';
169
    public const PACKAGE = 'package';
170
    public const PENDING_PARCELS = 'pendingParcels';
171
    public const STARTING_DATE = 'startingDate';
172
    public const SENDER_HAS_PAYMENT = 'senderHasPayment';
173
    public const SHIPMENT_ID = 'shipmentId';
174
    public const FORMAT = 'format';
175
    public const PAPER_SIZE = 'paperSize';
176
    public const PRINTER_NAME = 'printerName';
177
    public const DPI = 'dpi';
178
    public const PARCEL = 'parcel';
179
    public const ADDITIONAL_BARCODE = 'additionalBarcode';
180
    public const VALUE = 'value';
181
    public const LABEL = 'label';
182
    public const SHIPMENT_IDS = 'shipmentIds';
183
    public const LAST_OPERATION_ONLY = 'lastOperationOnly';
184
    public const CONSOLIDATION_REF = 'consolidationRef';
185
    public const REQUIRE_UNSUCCESSFUL_DELIVERY_STICKER_IMAGE = 'requireUnsuccessfulDeliveryStickerImage';
186
    public const EXCISE_GOODS = 'exciseGoods';
187
    public const SENDER_BANK_ACCOUNT = 'senderBankAccount';
188
    public const IBAN = 'iban';
189
    public const ACCOUNT_HOLDER = 'accountHolder';
190
191
    /**
192
     * @var Configuration
193
     */
194
    private Configuration $configuration;
195
196
    /**
197
     * PSR-18: HTTP Client
198
     * @var ClientInterface
199
     */
200
    private ClientInterface $client;
201
202
    /**
203
     * PSR-17: HTTP Factories
204
     * @var RequestFactoryInterface
205
     */
206
    private RequestFactoryInterface $factory;
207
208
    /**
209
     * @param Configuration $configuration
210
     * @param ClientInterface $client
211
     * @param RequestFactoryInterface $factory
212
     */
213 12
    public function __construct(
214
        Configuration $configuration,
215
        ClientInterface $client,
216
        RequestFactoryInterface $factory
217
    ) {
218 12
        $this->configuration = $configuration;
219 12
        $this->client  = $client;
220 12
        $this->factory = $factory;
221
    }
222
223
    /**
224
     * @param string $method
225
     * @param string $uri
226
     * @param array $data
227
     * @return RequestInterface
228
     */
229 10
    private function createRequest(string $method, string $uri, array $data): RequestInterface
230
    {
231 10
        $request = $this->factory->createRequest($method, $uri);
232
233 10
        $request = $request->withAddedHeader('Content-Type', 'application/json');
234
235 10
        $request->getBody()->write(json_encode($data));
236
237 10
        return $request;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $request returns the type Psr\Http\Message\MessageInterface which includes types incompatible with the type-hinted return Psr\Http\Message\RequestInterface.
Loading history...
238
    }
239
240
    /**
241
     * @param array $data
242
     * @return array
243
     */
244 10
    private function createPayload(array $data): array
245
    {
246 10
        $config = $this->configuration->toArray();
247
248 10
        return array_merge($config, $data);
249
    }
250
251
    /**
252
     * @param RequestInterface $request
253
     * @return string
254
     * @throws ClientExceptionInterface
255
     */
256 10
    private function getContents(RequestInterface $request): string
257
    {
258 10
        $response = $this->client->sendRequest($request);
259
260 10
        return $response->getBody()->getContents();
261
    }
262
263
264
    /**
265
     * @param GetContractClientsRequest $object
266
     * @return GetContractClientsResponse
267
     * @throws ClientExceptionInterface
268
     * @throws Throwable
269
     */
270 1
    public function getContractClient(
271
        GetContractClientsRequest $object
272
    ): GetContractClientsResponse {
273 1
        $payload = $this->createPayload($object->toArray());
274
275 1
        $request = $this->createRequest(
276 1
            RequestMethodInterface::METHOD_POST,
277 1
            self::API_URL . '/client/contract',
278 1
            $payload
279 1
        );
280
281 1
        $json = $this->getContents($request);
282
283 1
        return (new GetContractClientsResponseFactory())($json);
284
    }
285
286
    /**
287
     * @param Location\Country\FindCountryRequest $object
288
     * @return Location\Country\FindCountryResponse
289
     * @throws ClientExceptionInterface
290
     */
291 1
    public function findCountry(
292
        Location\Country\FindCountryRequest $object
293
    ): Location\Country\FindCountryResponse {
294 1
        $payload = $this->createPayload($object->toArray());
295
296 1
        $request = $this->createRequest(
297 1
            RequestMethodInterface::METHOD_POST,
298 1
            self::API_URL . '/location/country',
299 1
            $payload
300 1
        );
301
302 1
        $json = $this->getContents($request);
303
304 1
        return (new Location\Country\FindCountryResponseFactory())($json);
305
    }
306
307
    /**
308
     * @param Location\State\FindStateRequest $request
309
     * @return Location\State\FindStateResponse
310
     * @throws ClientExceptionInterface
311
     */
312 1
    public function findState(
313
        Location\State\FindStateRequest $request
314
    ): Location\State\FindStateResponse {
315 1
        $payload = $this->createPayload($request->toArray());
316
317 1
        $request = $this->createRequest(
318 1
            RequestMethodInterface::METHOD_POST,
319 1
            self::API_URL . '/location/state',
320 1
            $payload
321 1
        );
322
323 1
        $json = $this->getContents($request);
324
325 1
        return (new Location\State\FindStateResponseFactory())($json);
326
    }
327
328
329
    /**
330
     * @param Location\Site\FindSiteRequest $object
331
     * @return FindSiteResponse
332
     * @throws ClientExceptionInterface
333
     */
334 1
    public function findSite(Location\Site\FindSiteRequest $object): Location\Site\FindSiteResponse
335
    {
336 1
        $payload = $this->createPayload($object->toArray());
337
338 1
        $request = $this->createRequest(
339 1
            RequestMethodInterface::METHOD_POST,
340 1
            self::API_URL . '/location/site',
341 1
            $payload
342 1
        );
343
344 1
        $json = $this->getContents($request);
345
346 1
        return (new Location\Site\FindSiteResponseFactory())($json);
347
    }
348
349
350
    /**
351
     * @param FindOfficeRequest $object
352
     * @return FindOfficeResponse
353
     * @throws ClientExceptionInterface
354
     */
355 1
    public function findOffice(Location\Office\FindOfficeRequest $object): FindOfficeResponse
356
    {
357 1
        $payload = $this->createPayload($object->toArray());
358
359 1
        $request = $this->createRequest(
360 1
            RequestMethodInterface::METHOD_POST,
361 1
            self::API_URL . '/location/office',
362 1
            $payload
363 1
        );
364
365 1
        $json = $this->getContents($request);
366
367 1
        return (new Location\Office\FindOfficeResponseFactory())($json);
368
    }
369
370
371
    /**
372
     * @param FindComplexRequest $object
373
     * @return FindComplexResponse
374
     * @throws ClientExceptionInterface
375
     */
376 1
    public function findComplex(Location\Complex\FindComplexRequest $object): Location\Complex\FindComplexResponse
377
    {
378 1
        $payload = $this->createPayload($object->toArray());
379
380 1
        $request = $this->createRequest(
381 1
            RequestMethodInterface::METHOD_POST,
382 1
            self::API_URL . '/location/complex',
383 1
            $payload
384 1
        );
385
386 1
        $json = $this->getContents($request);
387
388 1
        return (new Location\Complex\FindComplexResponseFactory())($json);
389
    }
390
391
    /**
392
     * @param Location\Street\FindStreetRequest $object
393
     * @return Location\Street\FindStreetResponse
394
     * @throws ClientExceptionInterface
395
     */
396 1
    public function findStreet(Location\Street\FindStreetRequest $object): Location\Street\FindStreetResponse
397
    {
398 1
        $payload = $this->createPayload($object->toArray());
399
400 1
        $request = $this->createRequest(
401 1
            RequestMethodInterface::METHOD_POST,
402 1
            self::API_URL . '/location/street',
403 1
            $payload
404 1
        );
405
406 1
        $json = $this->getContents($request);
407
408 1
        return (new Location\Street\FindStreetResponseFactory())($json);
409
    }
410
411
    /**
412
     * @param CalculationRequest $object
413
     * @return CalculationResponse
414
     * @throws ClientExceptionInterface
415
     */
416 1
    public function calculation(CalculationRequest $object): CalculationResponse
417
    {
418 1
        $payload = $this->createPayload($object->toArray());
419
420 1
        $request = $this->createRequest(
421 1
            RequestMethodInterface::METHOD_POST,
422 1
            self::API_URL . '/calculate',
423 1
            $payload
424 1
        );
425
426 1
        $json = $this->getContents($request);
427
428 1
        return (new CalculationResponseFactory())($json);
429
    }
430
431
    /**
432
     * @param TrackRequest $request
433
     * @return TrackResponse
434
     */
435 1
    public function track(TrackRequest $object): TrackResponse
436
    {
437 1
        $payload = $this->createPayload($object->toArray());
438
439 1
        $request = $this->createRequest(
440 1
            RequestMethodInterface::METHOD_POST,
441 1
            self::API_URL . '/track',
442 1
            $payload
443 1
        );
444
445 1
        $json = $this->getContents($request);
446
447 1
        return (new TrackResponseFactory())($json);
448
    }
449
450
    /**
451
     * @param PrintRequest $request
452
     * @return PrintResponse
453
     */
454 1
    public function print(PrintRequest $request): PrintResponse
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

454
    public function print(/** @scrutinizer ignore-unused */ PrintRequest $request): PrintResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
455
    {
456 1
        return new PrintResponse();
457
    }
458
459
    /**
460
     * @param CreateShipmentRequest $object
461
     * @return CreateShipmentResponse
462
     * @throws ClientExceptionInterface
463
     */
464 1
    public function createShipment(CreateShipmentRequest $object): CreateShipmentResponse
465
    {
466 1
        $payload = $this->createPayload($object->toArray());
467
468
469 1
        $request = $this->createRequest(
470 1
            RequestMethodInterface::METHOD_POST,
471 1
            self::API_URL . '/shipment',
472 1
            $payload
473 1
        );
474
475 1
        $json = $this->getContents($request);
476
477 1
        return (new CreateShipmentResponseFactory())($json);
478
    }
479
480
    /**
481
     * @param CancelShipmentRequest $object
482
     * @return CancelShipmentResponse
483
     */
484
    public function cancelShipment(CancelShipmentRequest $object): CancelShipmentResponse
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

484
    public function cancelShipment(/** @scrutinizer ignore-unused */ CancelShipmentRequest $object): CancelShipmentResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
485
    {
486
        return new CancelShipmentResponse();
487
    }
488
489
    /**
490
     * @throws ClientExceptionInterface
491
     */
492
    public function destination(DestinationServicesRequest $object): DestinationServicesResponse
493
    {
494
        $payload = $this->createPayload($object->toArray());
495
496
        $request = $this->createRequest(
497
            RequestMethodInterface::METHOD_POST,
498
            self::API_URL . '/services/destination',
499
            $payload
500
        );
501
502
        $json = $this->getContents($request);
503
504
        return (new DestinationServicesResponseFactory())($json);
505
    }
506
}
507