Completed
Push — master ( a1acf8...e83a08 )
by Tomáš
03:23
created

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