Completed
Push — master ( 0512a1...7c8694 )
by Tomáš
03:46
created

Client::getBranchesForLocation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
ccs 11
cts 11
cp 1
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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