diff --git a/composer.json b/composer.json index 8d88af1..989d781 100755 --- a/composer.json +++ b/composer.json @@ -48,6 +48,6 @@ } }, "scripts": { - "test": "vendor/bin/phpunit" + "test": "vendor/bin/phpunit --testdox" } } diff --git a/src/Client.php b/src/Client.php index 6ae293a..127b534 100755 --- a/src/Client.php +++ b/src/Client.php @@ -8,6 +8,7 @@ use GuzzleHttp\Psr7\Request; use GuzzleHttp\RequestOptions; use Mvdnbrk\DhlParcel\Endpoints\Authentication; +use Mvdnbrk\DhlParcel\Endpoints\Capabilities; use Mvdnbrk\DhlParcel\Endpoints\Labels; use Mvdnbrk\DhlParcel\Endpoints\ServicePoints; use Mvdnbrk\DhlParcel\Endpoints\Shipments; @@ -48,6 +49,9 @@ class Client /** @var \Mvdnbrk\DhlParcel\Endpoints\TrackTrace */ public $tracktrace; + /** @var Capabilities */ + public $capabilities; + public function __construct() { $this->httpClient = new HttpClient([ @@ -64,6 +68,7 @@ public function initializeEndpoints(): void $this->servicePoints = new ServicePoints($this); $this->shipments = new Shipments($this); $this->tracktrace = new TrackTrace($this); + $this->capabilities = new Capabilities($this); } /** diff --git a/src/Endpoints/BaseEndpoint.php b/src/Endpoints/BaseEndpoint.php index 40f584e..6f26894 100644 --- a/src/Endpoints/BaseEndpoint.php +++ b/src/Endpoints/BaseEndpoint.php @@ -60,6 +60,10 @@ protected function performApiCall(string $httpMethod, string $apiMethod, ?string return $response->getBody()->getContents(); } + if ($response->getStatusCode() == 401) { + throw new DhlParcelException('Authentication failed', 0, $response); + } + $body = $response->getBody()->getContents(); $object = @json_decode($body); diff --git a/src/Endpoints/Capabilities.php b/src/Endpoints/Capabilities.php new file mode 100755 index 0000000..83ad0c3 --- /dev/null +++ b/src/Endpoints/Capabilities.php @@ -0,0 +1,75 @@ +buildQueryString($filters); + + $response = $this->performApiCall( + 'GET', + 'capabilities/'.$senderType.$queryString + ); + + $capabilities = new Collection(); + + collect($response)->each(function ($capability) use ($capabilities) { + $capabilityResource = new CapabilityResource([ + 'rank' => $capability->rank, + 'fromCountryCode' => $capability->fromCountryCode, + 'toCountryCode' => $capability->toCountryCode, + ]); + + $capabilityResource->product = new Product([ + 'key' => $capability->product->key, + 'label' => $capability->product->label, + 'code' => $capability->product->code, + 'menuCode' => $capability->product->menuCode, + 'businessProduct' => $capability->product->businessProduct, + 'monoColloProduct' => $capability->product->monoColloProduct, + 'softwareCharacteristic' => $capability->product->softwareCharacteristic, + 'returnProduct' => $capability->product->returnProduct, + ]); + + $capabilityResource->parcelType = new ParcelType([ + 'key' => $capability->parcelType->key, + 'category' => $capability->parcelType->category, + 'minWeightKg' => $capability->parcelType->minWeightKg, + 'maxWeightKg' => $capability->parcelType->maxWeightKg, + 'defaultWeightKg' => $capability->parcelType->defaultWeightKg, + 'minWeightGrams' => $capability->parcelType->minWeightGrams, + 'maxWeightGrams' => $capability->parcelType->maxWeightGrams, + 'defaultWeightGrams' => $capability->parcelType->defaultWeightGrams, + ]); + + $capabilityResource->parcelType->dimensions = new Dimensions([ + 'maxLengthCm' => $capability->parcelType->dimensions->maxLengthCm, + 'maxWidthCm' => $capability->parcelType->dimensions->maxWidthCm, + 'maxHeightCm' => $capability->parcelType->dimensions->maxHeightCm, + ]); + + collect($capability->options)->each(function ($option) use ($capabilityResource) { + $capabilityResource->options->add(new Option([ + 'key' => $option->key, + 'description' => $option->description, + 'rank' => $option->rank, + 'code' => $option->code, + 'optionType' => $option->optionType, + ])); + }); + + $capabilities->add($capabilityResource); + }); + + return $capabilities; + } +} diff --git a/src/Resources/Capability.php b/src/Resources/Capability.php new file mode 100644 index 0000000..42ef22c --- /dev/null +++ b/src/Resources/Capability.php @@ -0,0 +1,33 @@ +options = new Collection; + + parent::__construct($attributes); + } +} diff --git a/src/Resources/Dimensions.php b/src/Resources/Dimensions.php new file mode 100644 index 0000000..f530ef5 --- /dev/null +++ b/src/Resources/Dimensions.php @@ -0,0 +1,15 @@ +options->setInsured($value); + + return $this; + } + /** * Set the shipment options for this parcel. * * @param \Mvdnbrk\DhlParcel\Resources\ShipmentOptions|array $value - * @return void + * @return void */ public function setOptionsAttribute($value): void { @@ -115,7 +128,7 @@ public function servicePoint(string $value): self * Set the amount for "Cash On Delivery" in EUR. * * @param int|float $value - * @return $this + * @return $this */ public function cashOnDelivery($value): self { diff --git a/src/Resources/ParcelType.php b/src/Resources/ParcelType.php new file mode 100644 index 0000000..ca61bac --- /dev/null +++ b/src/Resources/ParcelType.php @@ -0,0 +1,33 @@ +setDefaultOptions(); @@ -90,6 +93,17 @@ public function setCashOnDelivery($value): void $this->cash_on_delivery = $value; } + /** + * Set the amount for the option "INS" in EUR. + * + * @param int|float $value + * @return void + */ + public function setInsured($value): void + { + $this->insured = $value; + } + public function toArray(): array { return collect() @@ -136,6 +150,12 @@ public function toArray(): array 'key' => 'EVE', ]); }) + ->when($this->insured, function ($collection) { + return $collection->push([ + 'key' => 'INS', + 'input' => $this->insured, + ]); + }) ->all(); } } diff --git a/tests/Feature/Endpoints/CapabilitiesTest.php b/tests/Feature/Endpoints/CapabilitiesTest.php new file mode 100644 index 0000000..b311e36 --- /dev/null +++ b/tests/Feature/Endpoints/CapabilitiesTest.php @@ -0,0 +1,78 @@ +client->capabilities->get('business'); + + $this->assertGreaterThan(0, $capabilities->count()); + $this->assertInstanceOf(Capability::class, $capabilities->get(0)); + $this->assertInstanceOf(ParcelType::class, $capabilities->get(0)->parcelType); + $this->assertInstanceOf(Product::class, $capabilities->get(0)->product); + $this->assertInstanceOf(Option::class, $capabilities->get(0)->options->get(0)); + + $this->assertNotNull($capabilities->get(0)->rank); + $this->assertNotNull($capabilities->get(0)->fromCountryCode); + $this->assertNotNull($capabilities->get(0)->toCountryCode); + $this->assertNotNull($capabilities->get(0)->product); + $this->assertNotNull($capabilities->get(0)->parcelType); + $this->assertNotNull($capabilities->get(0)->options); + + $this->assertNotNull($capabilities->get(0)->parcelType->key); + $this->assertNotNull($capabilities->get(0)->parcelType->category); + $this->assertNotNull($capabilities->get(0)->parcelType->minWeightKg); + $this->assertNotNull($capabilities->get(0)->parcelType->maxWeightKg); + $this->assertNotNull($capabilities->get(0)->parcelType->defaultWeightKg); + $this->assertNotNull($capabilities->get(0)->parcelType->dimensions); + $this->assertNotNull($capabilities->get(0)->parcelType->minWeightGrams); + $this->assertNotNull($capabilities->get(0)->parcelType->maxWeightGrams); + $this->assertNotNull($capabilities->get(0)->parcelType->defaultWeightGrams); + + $this->assertNotNull($capabilities->get(0)->product->key); + $this->assertNotNull($capabilities->get(0)->product->label); + $this->assertNotNull($capabilities->get(0)->product->code); + $this->assertNotNull($capabilities->get(0)->product->menuCode); + $this->assertNotNull($capabilities->get(0)->product->businessProduct); + $this->assertNotNull($capabilities->get(0)->product->monoColloProduct); + $this->assertNotNull($capabilities->get(0)->product->softwareCharacteristic); + $this->assertNotNull($capabilities->get(0)->product->returnProduct); + + $this->assertNotNull($capabilities->get(0)->options->get(0)->key); + $this->assertNotNull($capabilities->get(0)->options->get(0)->description); + $this->assertNotNull($capabilities->get(0)->options->get(0)->rank); + $this->assertNotNull($capabilities->get(0)->options->get(0)->code); + $this->assertNotNull($capabilities->get(0)->options->get(0)->optionType); + } + + public function invalid_sender_type() + { + $this->expectException(DhlParcelException::class); + + $this->client->capabilities->get('somethingnonexisting'); + } + + public function test_specific_to_and_from_country() + { + $capabilities = $this->client->capabilities->get('business', [ + 'fromCountry' => 'NL', + 'toCountry' => 'BE', + ]); + + /** @var Capability $capability */ + $capability = $capabilities->get(0); + + $this->assertEquals('NL', $capability->fromCountryCode); + $this->assertEquals('BE', $capability->toCountryCode); + } +} diff --git a/tests/Unit/Resources/ShipmentOptionsTest.php b/tests/Unit/Resources/ShipmentOptionsTest.php index cd295c1..7458f0f 100644 --- a/tests/Unit/Resources/ShipmentOptionsTest.php +++ b/tests/Unit/Resources/ShipmentOptionsTest.php @@ -201,4 +201,26 @@ public function to_array_with_cash_on_delivery() ], ], $array); } + + /** @test */ + public function to_array_with_insured() + { + $options = new ShipmentOptions([ + 'insured' => 150, + ]); + + $array = $options->toArray(); + + $this->assertIsArray($array); + + $this->assertEquals([ + [ + 'key' => 'DOOR', + ], + [ + 'key' => 'INS', + 'input' => 150, + ], + ], $array); + } }