Skip to content

Commit a3120d3

Browse files
authored
Merge pull request #28 from AlexisPPLIN/feature/add-service-points
Adding service point support
2 parents 49893c6 + 0535cd9 commit a3120d3

File tree

3 files changed

+399
-2
lines changed

3 files changed

+399
-2
lines changed

src/Client.php

+132-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use JouwWeb\Sendcloud\Model\ShippingMethod;
1818
use JouwWeb\Sendcloud\Model\User;
1919
use JouwWeb\Sendcloud\Model\WebhookEvent;
20+
use JouwWeb\Sendcloud\Model\ServicePoint;
2021
use Psr\Http\Message\RequestInterface;
2122

2223
/**
@@ -226,7 +227,7 @@ public function createMultiParcel(
226227
?ShippingMethod $shippingMethod = null,
227228
?string $errors = null,
228229
int $quantity = 1
229-
) : array {
230+
): array {
230231
$parcelData = $this->getParcelData(
231232
null,
232233
$shippingAddress,
@@ -521,6 +522,135 @@ public function getReturnPortalUrl(Parcel|int $parcel): ?string
521522
}
522523
}
523524

525+
/**
526+
* Summary of searchServicePoints
527+
*
528+
* @see https://api.sendcloud.dev/docs/sendcloud-public-api/service-points%2Foperations%2Flist-service-points
529+
* @param string $country A country ISO 2 code (Example : 'NL')
530+
* @param string|null $address Address of the destination address. Can accept postal code instead of the street and the house number. (Example : 'Stadhuisplein 10')
531+
* @param string|null $carrier A comma-separated list of carrier codes (stringified) (Example : 'postnl,dpd')
532+
* @param string|null $city City of the destination address. (Example : 'Eindhoven')
533+
* @param string|null $houseNumber House number of the destination address. (Example : '10')
534+
* @param string|null $latitude Used as a reference point to calculate the distance of the service point to the provided location.
535+
* @param string|null $longitude Used as a reference point to calculate the distance of the service point to the provided location.
536+
* @param string|null $neLatitude Latitude of the northeast corner of the bounding box.
537+
* @param string|null $neLongitude Longitude of the northeast corner of the bounding box.
538+
* @param string|null $postalCode Postal code of the destination address. Using postal_code will return you service points located around that particular postal code. (Example : '5611 EM')
539+
* @param string|null $pudoId DPD-specific query parameter. (<= 7 characters)
540+
* @param int|null $radius Radius (in meter) of a bounding circle. Can be used instead of the ne_latitude, ne_longitude, sw_latitude, and sw_longitude parameters to define a bounding box. By default, it’s 100 meters. Minimum value: 100 meters. Maximum value: 50 000 meters.
541+
* @param string|null $shopType Filters results by their shop type.
542+
* @param string|null $swLatitude Latitude of the southwest corner of the bounding box.
543+
* @param string|null $swLongitude Longitude of the southwest corner of the bounding box.
544+
* @param float|null $weight Weight (in kg.) of the parcel to be shipped to the service points. Certain carriers impose limits for certain service points that cannot accept parcels above a certain weight limit.
545+
* @return ServicePoint[]
546+
*/
547+
public function searchServicePoints(
548+
string $country,
549+
?string $address = null,
550+
?string $carrier = null,
551+
?string $city = null,
552+
?string $houseNumber = null,
553+
?string $latitude = null,
554+
?string $longitude = null,
555+
?string $neLatitude = null,
556+
?string $neLongitude = null,
557+
?string $postalCode = null,
558+
?string $pudoId = null,
559+
?int $radius = null,
560+
?string $shopType = null,
561+
?string $swLatitude = null,
562+
?string $swLongitude = null,
563+
?float $weight = null
564+
): array {
565+
try {
566+
// Construct query array
567+
$query = [];
568+
$query['country_id'] = $country;
569+
570+
if (isset($address)) {
571+
$query['address'] = $address;
572+
}
573+
if (isset($carrier)) {
574+
$query['carrier'] = $carrier;
575+
}
576+
if (isset($city)) {
577+
$query['city'] = $city;
578+
}
579+
if (isset($houseNumber)) {
580+
$query['house_number'] = $houseNumber;
581+
}
582+
if (isset($latitude)) {
583+
$query['latitude'] = $latitude;
584+
}
585+
if (isset($longitude)) {
586+
$query['longitude'] = $longitude;
587+
}
588+
if (isset($neLatitude)) {
589+
$query['ne_latitude'] = $neLatitude;
590+
}
591+
if (isset($neLongitude)) {
592+
$query['ne_longitude'] = $neLongitude;
593+
}
594+
if (isset($postalCode)) {
595+
$query['postal_code'] = $postalCode;
596+
}
597+
if (isset($pudoId)) {
598+
$query['pudo_id'] = $pudoId;
599+
}
600+
if (isset($radius)) {
601+
$query['radius'] = $radius;
602+
}
603+
if (isset($shopType)) {
604+
$query['shop_type'] = $shopType;
605+
}
606+
if (isset($swLatitude)) {
607+
$query['sw_latitude'] = $swLatitude;
608+
}
609+
if (isset($swLongitude)) {
610+
$query['sw_longitude'] = $swLongitude;
611+
}
612+
if (isset($weight)) {
613+
$query['weight'] = $weight;
614+
}
615+
616+
// Send request
617+
$response = $this->guzzleClient->get('service-point', [
618+
'query' => $query,
619+
]);
620+
621+
// Decode and create ServicePoint objects
622+
$json = json_decode((string)$response->getBody(), true);
623+
624+
$servicePoints = [];
625+
foreach ($json as $obj) {
626+
$servicePoints[] = ServicePoint::fromData($obj);
627+
}
628+
629+
return $servicePoints;
630+
} catch (TransferException $exception) {
631+
throw $this->parseGuzzleException($exception, 'Could not retrieve service point.');
632+
}
633+
}
634+
635+
/**
636+
* Returns service point by ID.
637+
*
638+
* @see https://api.sendcloud.dev/docs/sendcloud-public-api/service-points%2Foperations%2Fget-a-service-point
639+
* @return ServicePoint
640+
* @throws SendcloudRequestException
641+
*/
642+
public function getServicePoint(ServicePoint|int $servicePoint): ServicePoint
643+
{
644+
$servicePointId = $servicePoint instanceof ServicePoint ? $servicePoint->getId() : $servicePoint;
645+
646+
try {
647+
$response = $this->guzzleClient->get('service-point/' . $servicePointId);
648+
return ServicePoint::fromData(json_decode((string)$response->getBody(), true));
649+
} catch (TransferException $exception) {
650+
throw $this->parseGuzzleException($exception, 'Could not retrieve service point.');
651+
}
652+
}
653+
524654
/**
525655
* Returns the given arguments as data in Sendcloud parcel format.
526656
*
@@ -719,6 +849,7 @@ protected function parseGuzzleException(
719849
return new SendcloudRequestException($message, $code, $exception, $responseCode, $responseMessage);
720850
}
721851

852+
// TODO: Remove parseParcelArgument() now we use native unions.
722853
protected function parseParcelArgument(Parcel|int $parcel): int
723854
{
724855
if (is_int($parcel)) {

src/Model/ServicePoint.php

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
<?php
2+
3+
namespace JouwWeb\Sendcloud\Model;
4+
5+
/**
6+
* Implementation of Sendcloud service point object.
7+
*
8+
* @see https://api.sendcloud.dev/docs/sendcloud-public-api/service-points%2Foperations%2Fget-a-service-point
9+
*/
10+
class ServicePoint
11+
{
12+
public static function fromData(array $data): self
13+
{
14+
return new self(
15+
(int)$data['id'],
16+
(string)$data['code'],
17+
(bool)$data['is_active'],
18+
isset($data['shop_type']) ? (string)$data['shop_type'] : null,
19+
(array)$data['extra_data'],
20+
(string)$data['name'],
21+
(string)$data['street'],
22+
(string)$data['house_number'],
23+
(string)$data['postal_code'],
24+
(string)$data['city'],
25+
(string)$data['latitude'],
26+
(string)$data['longitude'],
27+
(string)$data['email'],
28+
(string)$data['phone'],
29+
(string)$data['homepage'],
30+
(string)$data['carrier'],
31+
(string)$data['country'],
32+
(array)$data['formatted_opening_times'],
33+
(bool)$data['open_tomorrow'],
34+
(bool)$data['open_upcoming_week'],
35+
(int)$data['distance']
36+
);
37+
}
38+
39+
/**
40+
* @param array<string, string> $extraData Can contain carrier specific data
41+
* @param array<int, string[]> $formattedOpeningTimes
42+
* @param int $distance Distance between the reference point and the service point in meters.
43+
*/
44+
public function __construct(
45+
protected int $id,
46+
protected string $code,
47+
protected bool $isActive,
48+
protected ?string $shopType,
49+
protected array $extraData,
50+
protected string $name,
51+
protected string $street,
52+
protected string $houseNumber,
53+
protected string $postalCode,
54+
protected string $city,
55+
protected string $latitude,
56+
protected string $longitude,
57+
protected string $email,
58+
protected string $phone,
59+
protected string $homepage,
60+
protected string $carrier,
61+
protected string $country,
62+
protected array $formattedOpeningTimes,
63+
protected bool $openTomorrow,
64+
protected bool $openUpcomingWeek,
65+
protected int $distance,
66+
) {
67+
}
68+
69+
public function getId(): int
70+
{
71+
return $this->id;
72+
}
73+
74+
public function getCode(): string
75+
{
76+
return $this->code;
77+
}
78+
79+
public function isActive(): bool
80+
{
81+
return $this->isActive;
82+
}
83+
84+
public function getShopType(): ?string
85+
{
86+
return $this->shopType;
87+
}
88+
89+
/**
90+
* Can contain carrier specific data.
91+
*
92+
* @return array<string, string>
93+
*/
94+
public function getExtraData(): array
95+
{
96+
return $this->extraData;
97+
}
98+
99+
public function getName(): string
100+
{
101+
return $this->name;
102+
}
103+
104+
public function getStreet(): string
105+
{
106+
return $this->street;
107+
}
108+
109+
public function getHouseNumber(): string
110+
{
111+
return $this->houseNumber;
112+
}
113+
114+
public function getPostalCode(): string
115+
{
116+
return $this->postalCode;
117+
}
118+
119+
public function getCity(): string
120+
{
121+
return $this->city;
122+
}
123+
124+
public function getLatitude(): string
125+
{
126+
return $this->latitude;
127+
}
128+
129+
public function getLongitude(): string
130+
{
131+
return $this->longitude;
132+
}
133+
134+
public function getEmail(): string
135+
{
136+
return $this->email;
137+
}
138+
139+
public function getPhone(): string
140+
{
141+
return $this->phone;
142+
}
143+
144+
public function getHomepage(): string
145+
{
146+
return $this->homepage;
147+
}
148+
149+
public function getCarrier(): string
150+
{
151+
return $this->carrier;
152+
}
153+
154+
public function getCountry(): string
155+
{
156+
return $this->country;
157+
}
158+
159+
/**
160+
* @return array<int, string[]>
161+
*/
162+
public function getFormattedOpeningTimes(): array
163+
{
164+
return $this->formattedOpeningTimes;
165+
}
166+
167+
public function isOpenTomorrow(): bool
168+
{
169+
return $this->openTomorrow;
170+
}
171+
172+
public function isOpenUpcomingWeek(): bool
173+
{
174+
return $this->openUpcomingWeek;
175+
}
176+
177+
/**
178+
* Distance between the reference point and the service point in meters.
179+
*/
180+
public function getDistance(): int
181+
{
182+
return $this->distance;
183+
}
184+
}

0 commit comments

Comments
 (0)