Completed
Push — master ( c19848...6bc0c5 )
by Tomáš
03:30
created

Client::getB2AServices()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
ccs 4
cts 4
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Inspirum\Balikobot\Services;
4
5
use DateTime;
6
use Inspirum\Balikobot\Contracts\RequesterInterface;
7
use Inspirum\Balikobot\Definitions\API;
8
use Inspirum\Balikobot\Definitions\Request;
9
use Inspirum\Balikobot\Exceptions\BadRequestException;
10
11
class Client
12
{
13
    /**
14
     * API requester
15
     *
16
     * @var \Inspirum\Balikobot\Contracts\RequesterInterface
17
     */
18
    private $requester;
19
20
    /**
21
     * Balikobot API client
22
     *
23
     * @param \Inspirum\Balikobot\Contracts\RequesterInterface $requester
24
     */
25 234
    public function __construct(RequesterInterface $requester)
26
    {
27 234
        $this->requester = $requester;
28 234
    }
29
30
    /**
31
     * Add package(s) to the Balikobot
32
     *
33
     * @param string                     $shipper
34
     * @param array<array<string,mixed>> $packages
35
     * @param string                     $version
36
     *
37
     * @return array<array<string,mixed>>
38
     *
39
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
40
     */
41 21
    public function addPackages(string $shipper, array $packages, string $version = API::V1): array
42
    {
43 21
        $response = $this->requester->call($version, $shipper, Request::ADD, $packages);
44
45 12
        if (isset($response[0]['package_id']) === false) {
46 1
            throw new BadRequestException($response);
47
        }
48
49 11
        unset($response['labels_url']);
50 11
        unset($response['status']);
51
52 11
        return $response;
53
    }
54
55
    /**
56
     * Drops a package from the Balikobot – the package must be not ordered
57
     *
58
     * @param string $shipper
59
     * @param int    $packageId
60
     *
61
     * @return void
62
     *
63
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
64
     */
65 2
    public function dropPackage(string $shipper, int $packageId): void
66
    {
67 2
        $this->dropPackages($shipper, [$packageId]);
68 2
    }
69
70
    /**
71
     * Drops a package from the Balikobot – the package must be not ordered
72
     *
73
     * @param string     $shipper
74
     * @param array<int> $packageIds
75
     *
76
     * @return void
77
     *
78
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
79
     */
80 7
    public function dropPackages(string $shipper, array $packageIds): void
81
    {
82 7
        $data = $this->encapsulateIds($packageIds);
83
84 7
        if (count($data) === 0) {
85 1
            return;
86
        }
87
88 6
        $this->requester->call(API::V1, $shipper, Request::DROP, $data);
89 3
    }
90
91
    /**
92
     * Tracks a package
93
     *
94
     * @param string $shipper
95
     * @param string $carrierId
96
     *
97
     * @return array<array<string,int|string>>
98
     *
99
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
100
     */
101 6
    public function trackPackage(string $shipper, string $carrierId): array
102
    {
103 6
        $response = $this->trackPackages($shipper, [$carrierId]);
104
105 3
        return $response[0];
106
    }
107
108
    /**
109
     * Tracks a packages
110
     *
111
     * @param string        $shipper
112
     * @param array<string> $carrierIds
113
     *
114
     * @return array<array<array<string,int|string>>>
115
     *
116
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
117
     */
118 16
    public function trackPackages(string $shipper, array $carrierIds): array
119
    {
120 16
        $data = $this->encapsulateIds($carrierIds);
121
122 16
        $response = $this->requester->call(API::V2, $shipper, Request::TRACK, $data, false);
123
124 12
        if (empty($response[0])) {
125 2
            throw new BadRequestException($response);
126
        }
127
128 10
        unset($response['status']);
129
130 10
        if (count($response) !== count($carrierIds)) {
131 1
            throw new BadRequestException($response);
132
        }
133
134 9
        return $response;
135
    }
136
137
    /**
138
     * Tracks a package, get the last info
139
     *
140
     * @param string $shipper
141
     * @param string $carrierId
142
     *
143
     * @return array<string,int|string>
144
     *
145
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
146
     */
147 7
    public function trackPackageLastStatus(string $shipper, string $carrierId): array
148
    {
149 7
        $response = $this->trackPackagesLastStatus($shipper, [$carrierId]);
150
151 3
        return $response[0];
152
    }
153
154
    /**
155
     * Tracks a package, get the last info
156
     *
157
     * @param string        $shipper
158
     * @param array<string> $carrierIds
159
     *
160
     * @return array<array<string,int|string|null>>
161
     *
162
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
163
     */
164 19
    public function trackPackagesLastStatus(string $shipper, array $carrierIds): array
165
    {
166 19
        $data = $this->encapsulateIds($carrierIds);
167
168 19
        $response = $this->requester->call(API::V1, $shipper, Request::TRACK_STATUS, $data, false);
169
170 15
        unset($response['status']);
171
172 15
        if (count($response) !== count($carrierIds)) {
173 3
            throw new BadRequestException($response);
174
        }
175
176 12
        $formatedStatuses = [];
177
178 12
        foreach ($response as $responseItem) {
179 12
            $this->validateStatus($responseItem, $response);
180
181 11
            $formatedStatuses[] = [
182 11
                'name'      => $responseItem['status_text'],
183 11
                'status_id' => $responseItem['status_id'],
184
                'date'      => null,
185
            ];
186
        }
187
188 10
        return $formatedStatuses;
189
    }
190
191
    /**
192
     * Returns packages from the front (not ordered) for given shipper
193
     *
194
     * @param string $shipper
195
     *
196
     * @return array<array<string,int|string>>
197
     *
198
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
199
     */
200 6
    public function getOverview(string $shipper): array
201
    {
202 6
        $response = $this->requester->call(API::V1, $shipper, Request::OVERVIEW, [], false);
203
204 4
        return $response;
205
    }
206
207
    /**
208
     * Gets labels
209
     *
210
     * @param string     $shipper
211
     * @param array<int> $packageIds
212
     *
213
     * @return string
214
     *
215
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
216
     */
217 7
    public function getLabels(string $shipper, array $packageIds): string
218
    {
219
        $data = [
220 7
            'package_ids' => $packageIds,
221
        ];
222
223 7
        $response = $this->requester->call(API::V1, $shipper, Request::LABELS, $data);
224
225 4
        $formattedResponse = $response['labels_url'];
226
227 4
        return $formattedResponse;
228
    }
229
230
    /**
231
     * Gets complete information about a package
232
     *
233
     * @param string $shipper
234
     * @param int    $packageId
235
     *
236
     * @return array<string,int|string>
237
     *
238
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
239
     */
240 6
    public function getPackageInfo(string $shipper, int $packageId): array
241
    {
242 6
        $response = $this->requester->call(API::V1, $shipper, Request::PACKAGE . '/' . $packageId, [], false);
243
244 4
        return $response;
245
    }
246
247
    /**
248
     * Order shipment for packages
249
     *
250
     * @param string         $shipper
251
     * @param array<int>     $packageIds
252
     * @param \DateTime|null $date
253
     * @param string|null    $note
254
     *
255
     * @return array<string,int|string>
256
     *
257
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
258
     */
259 7
    public function orderShipment(string $shipper, array $packageIds, DateTime $date = null, string $note = null): array
260
    {
261
        $data = [
262 7
            'package_ids' => $packageIds,
263 7
            'date'        => $date ? $date->format('Y-m-d') : null,
264 7
            'note'        => $note,
265
        ];
266
267 7
        $response = $this->requester->call(API::V1, $shipper, Request::ORDER, $data);
268
269 4
        unset($response['status']);
270
271 4
        return $response;
272
    }
273
274
    /**
275
     * Get order details
276
     *
277
     * @param string $shipper
278
     * @param int    $orderId
279
     *
280
     * @return array<string,int|string|array>
281
     *
282
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
283
     */
284 7
    public function getOrder(string $shipper, int $orderId): array
285
    {
286 7
        $response = $this->requester->call(API::V1, $shipper, Request::ORDER_VIEW . '/' . $orderId, [], false);
287
288 5
        unset($response['status']);
289
290 5
        return $response;
291
    }
292
293
    /**
294
     * Order pickup for packages
295
     *
296
     * @param string      $shipper
297
     * @param \DateTime   $dateFrom
298
     * @param \DateTime   $dateTo
299
     * @param float       $weight
300
     * @param int         $packageCount
301
     * @param string|null $message
302
     *
303
     * @return void
304
     *
305
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
306
     */
307 4
    public function orderPickup(
308
        string $shipper,
309
        DateTime $dateFrom,
310
        DateTime $dateTo,
311
        float $weight,
312
        int $packageCount,
313
        string $message = null
314
    ): void {
315
        $data = [
316 4
            'date'          => $dateFrom->format('Y-m-d'),
317 4
            'time_from'     => $dateFrom->format('H:s'),
318 4
            'time_to'       => $dateTo->format('H:s'),
319 4
            'weight'        => $weight,
320 4
            'package_count' => $packageCount,
321 4
            'message'       => $message,
322
        ];
323
324 4
        $this->requester->call(API::V1, $shipper, Request::ORDER_PICKUP, $data);
325 1
    }
326
327
    /**
328
     * Returns available services for the given shipper
329
     *
330
     * @param string $shipper
331
     *
332
     * @return array<string,string>
333
     *
334
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
335
     */
336 12
    public function getServices(string $shipper): array
337
    {
338 12
        $response = $this->requester->call(API::V1, $shipper, Request::SERVICES);
339
340 8
        $formattedResponse = $response['service_types'] ?? [];
341
342 8
        return $formattedResponse;
343
    }
344
345
    /**
346
     * Returns available B2A services for the given shipper
347
     *
348
     * @param string $shipper
349
     *
350
     * @return array<string,string>
351
     *
352
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
353
     */
354 8
    public function getB2AServices(string $shipper): array
355
    {
356 8
        $response = $this->requester->call(API::V1, $shipper, Request::B2A . '/' . Request::SERVICES);
357
358 5
        $formattedResponse = $response['service_types'] ?? [];
359
360 5
        return $formattedResponse;
361
    }
362
363
    /**
364
     * Returns available manipulation units for the given shipper
365
     *
366
     * @param string $shipper
367
     *
368
     * @return array<string,string>
369
     *
370
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
371
     */
372 8
    public function getManipulationUnits(string $shipper): array
373
    {
374 8
        $response = $this->requester->call(API::V1, $shipper, Request::MANIPULATION_UNITS);
375
376 5
        $formattedResponse = $this->normalizeResponseItems($response['units'] ?? [], 'code', 'name');
377
378 5
        return $formattedResponse;
379
    }
380
381
    /**
382
     * Returns available branches for the given shipper and its service
383
     * Full branches instead branches request
384
     *
385
     * @param string      $shipper
386
     * @param string|null $service
387
     * @param bool        $fullBranchRequest
388
     * @param string|null $country
389
     *
390
     * @return array<array<string,mixed>>
391
     *
392
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
393
     */
394 15
    public function getBranches(
395
        string $shipper,
396
        ?string $service,
397
        bool $fullBranchRequest = false,
398
        string $country = null
399
    ): array {
400 15
        $usedRequest = $fullBranchRequest ? Request::FULL_BRANCHES : Request::BRANCHES;
401
402 15
        $response = $this->requester->call(API::V1, $shipper, $usedRequest . '/' . $service . '/' . $country);
403
404 12
        $formattedResponse = $response['branches'] ?? [];
405
406 12
        return $formattedResponse;
407
    }
408
409
    /**
410
     * Returns available branches for the given shipper in given location
411
     *
412
     * @param string      $shipper
413
     * @param string      $country
414
     * @param string      $city
415
     * @param string|null $postcode
416
     * @param string|null $street
417
     * @param int|null    $maxResults
418
     * @param float|null  $radius
419
     * @param string|null $type
420
     *
421
     * @return array<array<string,mixed>>
422
     *
423
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
424
     */
425 9
    public function getBranchesForLocation(
426
        string $shipper,
427
        string $country,
428
        string $city,
429
        string $postcode = null,
430
        string $street = null,
431
        int $maxResults = null,
432
        float $radius = null,
433
        string $type = null
434
    ): array {
435
        $data = [
436 9
            'country'     => $country,
437 9
            'city'        => $city,
438 9
            'zip'         => $postcode,
439 9
            'street'      => $street,
440 9
            'max_results' => $maxResults,
441 9
            'radius'      => $radius,
442 9
            'type'        => $type,
443
        ];
444
445 9
        $response = $this->requester->call(API::V1, $shipper, Request::BRANCH_LOCATOR, array_filter($data));
446
447 6
        $formattedResponse = $response['branches'] ?? [];
448
449 6
        return $formattedResponse;
450
    }
451
452
    /**
453
     * Returns list of countries where service with cash-on-delivery payment type is available in
454
     *
455
     * @param string $shipper
456
     *
457
     * @return array<array<int|string,array<string,array>>>
458
     *
459
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
460
     */
461 8
    public function getCodCountries(string $shipper): array
462
    {
463 8
        $response = $this->requester->call(API::V1, $shipper, Request::CASH_ON_DELIVERY_COUNTRIES);
464
465 5
        $formattedResponse = $this->normalizeResponseItems(
466 5
            $response['service_types'] ?? [],
467 5
            'service_type',
468 5
            'cod_countries'
469
        );
470
471 5
        return $formattedResponse;
472
    }
473
474
    /**
475
     * Returns list of countries where service is available in
476
     *
477
     * @param string $shipper
478
     *
479
     * @return array<array<int|string,string>>
480
     *
481
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
482
     */
483 8
    public function getCountries(string $shipper): array
484
    {
485 8
        $response = $this->requester->call(API::V1, $shipper, Request::COUNTRIES);
486
487 5
        $formattedResponse = $this->normalizeResponseItems(
488 5
            $response['service_types'] ?? [],
489 5
            'service_type',
490 5
            'countries'
491
        );
492
493 5
        return $formattedResponse;
494
    }
495
496
    /**
497
     * Returns available branches for the given shipper and its service
498
     *
499
     * @param string      $shipper
500
     * @param string      $service
501
     * @param string|null $country
502
     *
503
     * @return array<array<string,mixed>>
504
     *
505
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
506
     */
507 12
    public function getPostCodes(string $shipper, string $service, string $country = null): array
508
    {
509 12
        $response = $this->requester->call(API::V1, $shipper, Request::ZIP_CODES . '/' . $service . '/' . $country);
510
511 9
        $country = $response['country'] ?? $country;
512
513 9
        $formattedResponse = [];
514
515 9
        foreach ($response['zip_codes'] ?? [] as $responseItem) {
516 5
            $formattedResponse[] = [
517 5
                'postcode'     => $responseItem['zip'] ?? ($responseItem['zip_start'] ?? null),
518 5
                'postcode_end' => $responseItem['zip_end'] ?? null,
519 5
                'city'         => $responseItem['city'] ?? null,
520 5
                'country'      => $responseItem['country'] ?? $country,
521 5
                '1B'           => (bool) ($responseItem['1B'] ?? false),
522
            ];
523
        }
524
525 9
        return $formattedResponse;
526
    }
527
528
    /**
529
     * Check package(s) data
530
     *
531
     * @param string               $shipper
532
     * @param array<array<string>> $packages
533
     *
534
     * @return void
535
     *
536
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
537
     */
538 5
    public function checkPackages(string $shipper, array $packages): void
539
    {
540 5
        $this->requester->call(API::V1, $shipper, Request::CHECK, $packages);
541 2
    }
542
543
    /**
544
     * Returns available manipulation units for the given shipper
545
     *
546
     * @param string $shipper
547
     *
548
     * @return array<string>
549
     *
550
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
551
     */
552 8
    public function getAdrUnits(string $shipper): array
553
    {
554 8
        $response = $this->requester->call(API::V1, $shipper, Request::ADR_UNITS);
555
556 5
        $formattedResponse = $this->normalizeResponseItems($response['units'] ?? [], 'code', 'name');
557
558 5
        return $formattedResponse;
559
    }
560
561
    /**
562
     * Returns available activated services for the given shipper
563
     *
564
     * @param string $shipper
565
     *
566
     * @return array<string,mixed>
567
     *
568
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
569
     */
570 6
    public function getActivatedServices(string $shipper): array
571
    {
572 6
        $response = $this->requester->call(API::V1, $shipper, Request::ACTIVATEDSERVICES);
573
574 4
        unset($response['status']);
575
576 4
        return $response;
577
    }
578
579
    /**
580
     * Order shipments from place B (typically supplier / previous consignee) to place A (shipping point)
581
     *
582
     * @param string                     $shipper
583
     * @param array<array<string,mixed>> $packages
584
     *
585
     * @return array<array<string,mixed>>
586
     *
587
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
588
     */
589 9
    public function orderB2AShipment(string $shipper, array $packages): array
590
    {
591 9
        $response = $this->requester->call(API::V1, $shipper, Request::B2A, $packages);
592
593 6
        if (isset($response[0]['package_id']) === false) {
594 1
            throw new BadRequestException($response);
595
        }
596
597 5
        unset($response['status']);
598
599 5
        return $response;
600
    }
601
602
    /**
603
     * Get PDF link with signed consignment delivery document by the recipient
604
     *
605
     * @param string $shipper
606
     * @param string $carrierId
607
     *
608
     * @return string
609
     *
610
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
611
     */
612 7
    public function getProofOfDelivery(string $shipper, string $carrierId): string
613
    {
614 7
        $response = $this->getProofOfDeliveries($shipper, [$carrierId]);
615
616 3
        return $response[0];
617
    }
618
619
    /**
620
     * Get array of PDF links with signed consignment delivery document by the recipient
621
     *
622
     * @param string        $shipper
623
     * @param array<string> $carrierIds
624
     *
625
     * @return array<string>
626
     *
627
     * @throws \Inspirum\Balikobot\Contracts\ExceptionInterface
628
     */
629 19
    public function getProofOfDeliveries(string $shipper, array $carrierIds): array
630
    {
631 19
        $data = $this->encapsulateIds($carrierIds);
632
633 19
        $response = $this->requester->call(API::V1, $shipper, Request::PROOF_OF_DELIVERY, $data, false);
634
635 15
        unset($response['status']);
636
637 15
        if (count($response) !== count($carrierIds)) {
638 3
            throw new BadRequestException($response);
639
        }
640
641 12
        $formatedLinks = [];
642
643 12
        foreach ($response as $responseItem) {
644 12
            $this->validateStatus($responseItem, $response);
645
646 11
            $formatedLinks[] = $responseItem['file_url'];
647
        }
648
649 10
        return $formatedLinks;
650
    }
651
652
    /**
653
     * Validate response item status
654
     *
655
     * @param array<mixed,mixed> $responseItem
656
     * @param array<mixed,mixed> $response
657
     *
658
     * @return void
659
     */
660 24
    private function validateStatus(array $responseItem, array $response): void
661
    {
662 24
        if (isset($responseItem['status']) && ((int) $responseItem['status']) !== 200) {
663 4
            throw new BadRequestException($response);
664
        }
665 22
    }
666
667
    /**
668
     * Normalize response items
669
     *
670
     * @param array<array<string,string>> $items
671
     * @param string                      $keyName
672
     * @param string                      $valueName
673
     *
674
     * @return array<string,mixed>
675
     */
676 20
    private function normalizeResponseItems(array $items, string $keyName, string $valueName): array
677
    {
678 20
        $formattedResponse = [];
679
680 20
        foreach ($items as $item) {
681 8
            $formattedResponse[$item[$keyName]] = $item[$valueName];
682
        }
683
684 20
        return $formattedResponse;
685
    }
686
687
    /**
688
     * Encapsulate ids
689
     *
690
     * @param array<int|string> $ids
691
     *
692
     * @return array<array<int|string>>
693
     */
694 61
    private function encapsulateIds(array $ids): array
695
    {
696
        return array_map(function ($carrierId) {
697
            return [
698 60
                'id' => $carrierId,
699
            ];
700 61
        }, $ids);
701
    }
702
}
703