Completed
Push — master ( cb1d4b...ee462c )
by Tomáš
03:34
created

Client::getAdrUnits()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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