diff --git a/src/Request/Enum/Portfolio.php b/src/Request/Enum/Portfolio.php new file mode 100644 index 0000000..20d67ce --- /dev/null +++ b/src/Request/Enum/Portfolio.php @@ -0,0 +1,10 @@ + ['KPN', 'Tele2']] + + /** + * @return string|null + */ + public function getPortfolio(): ?string + { + return $this->portfolio; + } + + /** + * @param Portfolio|string|null $portfolio + */ + public function setPortfolio(Portfolio|string|null $portfolio): self + { + if ($portfolio instanceof Portfolio) { + $this->portfolio = $portfolio->value; + } else { + $this->portfolio = $portfolio; + } + + return $this; + } + + /** + * @return string|null + */ + public function getZipCode(): ?string + { + return $this->zipCode; + } + + /** + * @param string|null $zipCode + * + * @return $this + */ + public function setZipCode(?string $zipCode): self + { + $this->zipCode = $zipCode; + + return $this; + } + + /** + * @return int|null + */ + public function getHouseNr(): ?int + { + return $this->houseNr; + } + + /** + * @param int|null $houseNr + * + * @return $this + */ + public function setHouseNr(?int $houseNr): self + { + $this->houseNr = $houseNr; + + return $this; + } + + /** + * @return string|null + */ + public function getHouseNrExtension(): ?string + { + return $this->houseNrExtension; + } + + /** + * @param string|null $houseNrExtension + * + * @return $this + */ + public function setHouseNrExtension(?string $houseNrExtension): self + { + $this->houseNrExtension = $houseNrExtension; + + return $this; + } + + /** + * @return string|null + */ + public function getServiceId(): ?string + { + return $this->serviceId; + } + + /** + * @param string|null $serviceId + * + * @return $this + */ + public function setServiceId(?string $serviceId): self + { + $this->serviceId = $serviceId; + + return $this; + } + + /** + * @return string|null + */ + public function getRoomNumber(): ?string + { + return $this->roomNumber; + } + + /** + * @param string|null $roomNumber + * + * @return $this + */ + public function setRoomNumber(?string $roomNumber): self + { + $this->roomNumber = $roomNumber; + + return $this; + } + + /** + * @return bool|null + */ + public function getIsRoomNumberKnown(): ?bool + { + return $this->isRoomNumberKnown; + } + + /** + * @param bool|null $isRoomNumberKnown + * + * @return $this + */ + public function setIsRoomNumberKnown(?bool $isRoomNumberKnown): self + { + $this->isRoomNumberKnown = $isRoomNumberKnown; + + return $this; + } + + /** + * @return array>|null + */ + public function getSuppliers(): ?array + { + return $this->suppliers; // ✅ return the nested structure + } + + /** + * @param array|null $suppliers + */ + public function setSuppliers(?array $suppliers): self + { + if ($suppliers === null) { + $this->suppliers = null; + return $this; + } + + $normalized = []; + + foreach ($suppliers as $supplier) { + if ($supplier instanceof Supplier) { + $normalized[] = $supplier->value; + } elseif ($supplier !== null) { + $normalized[] = (string) $supplier; + } + } + + // This shape matches ArrayOfString → ... + $this->suppliers = [ + 'string' => $normalized, + ]; + + return $this; + } +} diff --git a/src/Response/AvailableSpeed.php b/src/Response/AvailableSpeed.php new file mode 100644 index 0000000..7f8595d --- /dev/null +++ b/src/Response/AvailableSpeed.php @@ -0,0 +1,285 @@ +availability; + } + + /** + * @param string|null $availability + * + * @return $this + */ + public function setAvailability(?string $availability): self + { + $this->availability = $availability; + + return $this; + } + + /** + * @return string|null + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @param string|null $description + * + * @return $this + */ + public function setDescription(?string $description): self + { + $this->description = $description; + + return $this; + } + + /** + * @return NlsType|null + */ + public function getNlsTypeEnum(): ?NlsType + { + return NlsType::fromNullable($this->getNlsTypeRaw()); + } + + /** + * @return string|null + */ + public function getNlsTypeRaw(): ?string + { + return is_string($this->nlsType) && $this->nlsType !== '' + ? $this->nlsType + : null; + } + + /** + * @param mixed $value + * + * @return $this + */ + public function setNlsType(mixed $value): self + { + // Possible shapes: + // - 'Nls6' + // - 'Nls1' + // - null + // - '' + // - array with nil metadata (for p6:nil="true") + // We only keep it if it's a non-empty string. + if (is_string($value) && $value !== '') { + $this->nlsType = $value; + } else { + $this->nlsType = null; + } + + return $this; + } + + /** + * Always return a flat list of non-empty strings. + * + * @return string[] + */ + public function getRemarks(): array + { + $raw = $this->remarks; + + if ($raw === null || $raw === '') { + return []; + } + + // Single scalar → one remark (if non-empty) + if (is_scalar($raw) || $raw instanceof \Stringable) { + $s = trim((string) $raw); + return $s === '' ? [] : [$s]; + } + + // Traversable → turn into array + if ($raw instanceof \Traversable) { + $raw = iterator_to_array($raw); + } + + // Any array shape → flatten all scalar values + if (is_array($raw)) { + $out = []; + + $it = new \RecursiveIteratorIterator( + new \RecursiveArrayIterator($raw) + ); + + foreach ($it as $v) { + if (is_scalar($v) || $v instanceof \Stringable) { + $s = trim((string) $v); + if ($s !== '') { + $out[] = $s; + } + } + } + + return $out; + } + + // Anything else → no remarks + return []; + } + + /** + * @param mixed $remarks + */ + public function setRemarks(mixed $remarks): self + { + // Possible shapes: + // - null + // - '' + // - 'some text' + // - ['string' => ['Nls6', 'Bestel de ...']] + // - ['string' => 'Nls6'] + // - [] + $this->remarks = $remarks; + return $this; + } + + /** + * @return string|null + */ + public function getTechnology(): ?string + { + return $this->technology; + } + + /** + * @param string|null $technology + * + * @return $this + */ + public function setTechnology(?string $technology): self + { + $this->technology = $technology; + + return $this; + } + + /** + * @return string|null + */ + public function getTariffCluster(): ?string + { + return $this->tariffCluster; + } + + /** + * @param string|null $tariffCluster + * + * @return $this + */ + public function setTariffCluster(?string $tariffCluster): self + { + $this->tariffCluster = $tariffCluster; + + return $this; + } + + /** + * @return DateTimeInterface|null + */ + public function getPlanDate(): ?DateTimeInterface + { + return $this->planDate; + } + + /** + * @param mixed $planDate + * + * @return $this + */ + public function setPlanDate(mixed $planDate): self + { + // Case 1: explicit null or empty string + if ($planDate === null || $planDate === '') { + $this->planDate = null; + return $this; + } + + // Case 2: XML decoder gave an array for xsi:nil / attributes + if (is_array($planDate)) { + $flat = array_change_key_case($planDate, CASE_LOWER); + + // Try to detect any kind of nil="true" + $nil = + $flat['@xsi:nil'] ?? + $flat['@nil'] ?? + $flat['nil'] ?? + null; + + if ($nil === 'true' || $nil === true || $nil === '1') { + $this->planDate = null; + return $this; + } + + // Unknown array shape → be safe and treat as null + $this->planDate = null; + return $this; + } + + // Case 3: normal date string "2024-02-15T13:45:00" + if (is_string($planDate)) { + try { + $this->planDate = new DateTimeImmutable($planDate); + } catch (\Throwable $e) { + // Invalid date format → store null, don't kill deserialization + $this->planDate = null; + } + + return $this; + } + + // Case 4: Already a DateTimeInterface (unlikely, but fine) + if ($planDate instanceof DateTimeInterface) { + $this->planDate = $planDate; + return $this; + } + + // Fallback: unknown type → null + $this->planDate = null; + return $this; + } +} diff --git a/src/Response/AvailableSupplier.php b/src/Response/AvailableSupplier.php new file mode 100644 index 0000000..02792b0 --- /dev/null +++ b/src/Response/AvailableSupplier.php @@ -0,0 +1,105 @@ +name; + } + + /** + * @param string|null $name + * + * @return $this + */ + public function setName(?string $name): self + { + $this->name = $name; + + return $this; + } + + /** + * @return string|null + */ + public function getErrorMessage(): ?string + { + return $this->errorMessage; + } + + /** + * @param string|null $errorMessage + * + * @return $this + */ + public function setErrorMessage(?string $errorMessage): self + { + $this->errorMessage = $errorMessage; + + return $this; + } + + /** + * @return string|null + */ + public function getLocationInfo(): ?string + { + return $this->locationInfo; + } + + /** + * @param string|null $locationInfo + * + * @return $this + */ + public function setLocationInfo(?string $locationInfo): self + { + $this->locationInfo = $locationInfo; + + return $this; + } + + /** + * @param AvailableSpeed[] $availableSpeed + * + * @return $this + */ + public function setAvailableSpeed(array $availableSpeed): self + { + $this->availableSpeed = $availableSpeed; + + return $this; + } + + /** + * @return AvailableSpeed[]|null + */ + public function getAvailableSpeed(): ?array + { + return $this->availableSpeed; + } +} diff --git a/src/Response/Enum/NlsType.php b/src/Response/Enum/NlsType.php new file mode 100644 index 0000000..c5f9d37 --- /dev/null +++ b/src/Response/Enum/NlsType.php @@ -0,0 +1,31 @@ +availableSupplier = $availableSupplier; + + return $this; + } + + /** + * @return AvailableSupplier[]|null + */ + public function getAvailableSupplier(): ?array + { + return $this->availableSupplier; + } +} diff --git a/src/RoutITAPIClient.php b/src/RoutITAPIClient.php index b5b15aa..fb3e77e 100644 --- a/src/RoutITAPIClient.php +++ b/src/RoutITAPIClient.php @@ -9,9 +9,11 @@ use Inserve\RoutITAPI\Request\OrderSummaryRequest; use Inserve\RoutITAPI\Request\ProductPriceDetailsRequest; use Inserve\RoutITAPI\Request\RoutITRequestInterface; +use Inserve\RoutITAPI\Request\ZipCodeCheckRequest; use Inserve\RoutITAPI\Response\CustomerDataResponse; use Inserve\RoutITAPI\Response\OrderSummaryResponse; use Inserve\RoutITAPI\Response\ProductPriceDetailsResponse; +use Inserve\RoutITAPI\Response\ZipCodeCheckResponse; use Psr\Log\LoggerInterface; use SensitiveParameter; @@ -89,6 +91,19 @@ public function getProductPriceDetails(): ?ProductPriceDetailsResponse /** @var ProductPriceDetailsResponse|null */ return $this->apiCall(new ProductPriceDetailsRequest(), ProductPriceDetailsResponse::class); } + + /** + * @param ZipCodeCheckRequest|null $request + * + * @return ZipCodeCheckResponse|null + * @throws RoutITAPIException + */ + public function zipCodeCheck(?ZipCodeCheckRequest $request = null): ?ZipCodeCheckResponse + { + /** @var ZipCodeCheckResponse|null */ + return $this->apiCall($request ?? new ZipCodeCheckRequest(), ZipCodeCheckResponse::class); + } + /** * @param RoutITRequestInterface $request * @param string $responseClass