Skip to content

Commit

Permalink
Support for Italy PickupPoints
Browse files Browse the repository at this point in the history
  • Loading branch information
yekovalenkoa committed Feb 2, 2024
1 parent 86ff34b commit 554661b
Show file tree
Hide file tree
Showing 15 changed files with 398 additions and 95 deletions.
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
"ext-json": "*",
"guzzlehttp/guzzle": "^6.0",
"phpstan/phpstan-deprecation-rules": "^1.1",
"symfony/http-kernel": "^6.0",
"symfony/serializer": "^6.0",
"symfony/http-kernel": "^6.1",
"symfony/property-info": "^6.1",
"symfony/serializer": "^6.1",
"symfony/serializer-pack": "^1.3",
"webmozart/assert": "^1.11"
},
"require-dev": {
Expand All @@ -19,7 +21,7 @@
"phpstan/phpstan-webmozart-assert": "^1.2.4",
"phpunit/phpunit": "^10.5",
"roave/security-advisories": "dev-master",
"symfony/phpunit-bridge": "6.1.*"
"symfony/phpunit-bridge": "6.2.*"
},
"autoload": {
"psr-4": {
Expand Down
10 changes: 8 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,11 @@ parameters:
treatPhpDocTypesAsCertain: false
paths:
- %rootDir%/../../../src
excludePaths:
- tests/*
ignoreErrors:
-
message: '#.*NodeDefinition::children.*#'
path: ./src/DependencyInjection

-
message: '#.*Extension::processConfiguration.*#'
path: ./src/DependencyInjection
3 changes: 2 additions & 1 deletion src/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ class Client
private ClientInterface $client;

public function __construct(
private readonly ConfigProvider $configProvider,
?ClientInterface $client = null,
) {
$this->client = $client ?? new GuzzleClient(
[
'base_uri' => ConfigProvider::BASE_URL,
'base_uri' => $this->configProvider->baseUrl,
]
);
}
Expand Down
9 changes: 6 additions & 3 deletions src/Command/FindPoints.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ class FindPoints extends AbstractCommand
private Client $client;
private Serializer $serializer;

public function __construct(Client $client, Serializer $serializer)
{
public function __construct(
private readonly ConfigProvider $configProvider,
Client $client,
Serializer $serializer,
) {
$this->client = $client;
$this->serializer = $serializer;
}
Expand All @@ -27,7 +30,7 @@ public function findPoints(FindPointsRequest $request): FindPointsResponse
{
$httpRequest = new HttpRequest(
$request->getMethod(),
new Uri(ConfigProvider::API_VERSION . $request->getRequestUrl()),
new Uri($this->configProvider->apiVersion . $request->getRequestUrl()),
[
'Content-type' => 'application/json',
],
Expand Down
10 changes: 8 additions & 2 deletions src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

class ConfigProvider
{
public const BASE_URL = 'https://api-shipx-pl.easypack24.net/';
public const API_VERSION = 'v1';
private const BASE_URL = 'https://api-shipx-pl.easypack24.net/';
private const API_VERSION = 'v1';

public function __construct(
public readonly string $baseUrl = self::BASE_URL,
public readonly string $apiVersion = self::API_VERSION,
) {
}
}
33 changes: 32 additions & 1 deletion src/DependencyInjection/AnswearInpostExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,50 @@

namespace Answear\InpostBundle\DependencyInjection;

use Answear\InpostBundle\ConfigProvider;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class AnswearInpostExtension extends Extension
class AnswearInpostExtension extends Extension implements PrependExtensionInterface
{
private array $config;

public function prepend(ContainerBuilder $container): void
{
$configs = $container->getExtensionConfig($this->getAlias());
$this->setConfig($container, $configs);
}

/**
* @throws \Exception
*/
public function load(array $configs, ContainerBuilder $container): void
{
$loader = new YamlFileLoader(
$container,
new FileLocator(__DIR__ . '/../Resources/config')
);
$loader->load('services.yaml');

$this->setConfig($container, $configs);

$definition = $container->getDefinition(ConfigProvider::class);
$definition->setArguments([
$this->config['baseUrl'],
$this->config['apiVersion'],
]);
}

private function setConfig(ContainerBuilder $container, array $configs): void
{
if (isset($this->config)) {
return;
}

$configuration = $this->getConfiguration($configs, $container);
$this->config = $this->processConfiguration($configuration, $configs);
}
}
24 changes: 24 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Answear\InpostBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('answear_inpost');

$treeBuilder->getRootNode()
->children()
?->scalarNode('baseUrl')->defaultNull()->end()
?->scalarNode('apiVersion')->defaultNull()->end()
?->end();

return $treeBuilder;
}
}
1 change: 1 addition & 0 deletions src/Enum/PointType.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ enum PointType: string
case Pop = 'pop';
case ParcelLockerOnly = 'parcel_locker_only';
case ParcelLockerSuperpop = 'parcel_locker_superpop';
case Pok = 'pok';
}
3 changes: 3 additions & 0 deletions src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ services:
autoconfigure: true
public: false

Answear\InpostBundle\ConfigProvider: ~
Answear\InpostBundle\Client: ~

Answear\InpostBundle\:
resource: '../../../src/{Command,Client}'

6 changes: 6 additions & 0 deletions src/Response/Struct/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Item
public ?string $locationDescription2;
public ?int $distance;
public ?string $openingHours;
public ?ItemOperatingHours $operatingHoursExtended;
public ?ItemAddress $address;
public ?ItemAddressDetails $addressDetails;
public ?string $phoneNumber;
Expand All @@ -36,6 +37,7 @@ class Item
/** @var string[] */
public ?array $recommendedLowInterestBoxMachinesList;
public ?bool $location247;
public ?bool $easyAccessZone;

public static function fromArray(array $pointData): self
{
Expand All @@ -53,6 +55,9 @@ public static function fromArray(array $pointData): self
$point->locationDescription2 = $pointData['location_description_2'] ?? null;
$point->distance = $pointData['distance'] ?? null;
$point->openingHours = $pointData['opening_hours'] ?? null;
$point->operatingHoursExtended = !empty($pointData['operating_hours_extended'])
? ItemOperatingHours::fromArray($pointData['operating_hours_extended'])
: null;
$point->address = !empty($pointData['address']) ? ItemAddress::fromArray($pointData['address']) : null;
$point->addressDetails = !empty($pointData['address_details']) ? ItemAddressDetails::fromArray($pointData['address_details']) : null;
$point->phoneNumber = $pointData['phone_number'] ?? null;
Expand All @@ -65,6 +70,7 @@ public static function fromArray(array $pointData): self
$point->virtual = $pointData['virtual'] ?? null;
$point->recommendedLowInterestBoxMachinesList = $pointData['recommended_low_interest_box_machines_list'] ?? null;
$point->location247 = $pointData['location_247'] ?? null;
$point->easyAccessZone = $pointData['easyAccessZone'] ?? null;

return $point;
}
Expand Down
37 changes: 37 additions & 0 deletions src/Response/Struct/ItemOperatingHours.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Answear\InpostBundle\Response\Struct;

class ItemOperatingHours
{
public array $sunday = [];
public array $monday = [];
public array $tuesday = [];
public array $wednesday = [];
public array $thursday = [];
public array $friday = [];
public array $saturday = [];

public static function fromArray(array $operatingHours): self
{
$self = new self();

if (!isset($operatingHours['customer'])) {
return $self;
}

if (!is_array($operatingHours['customer'])) {
return $self;
}

foreach ($operatingHours['customer'] as $day => $hours) {
if (isset($self->{strtolower($day)})) {
$self->{strtolower($day)} = $hours;
}
}

return $self;
}
}
87 changes: 72 additions & 15 deletions tests/Integration/Command/FindPointsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use Answear\InpostBundle\Client\Client;
use Answear\InpostBundle\Client\Serializer;
use Answear\InpostBundle\Command\FindPoints;
use Answear\InpostBundle\ConfigProvider;
use Answear\InpostBundle\Enum\PointFunctionsType;
use Answear\InpostBundle\Enum\PointType;
use Answear\InpostBundle\Request\FindPointsRequest;
use Answear\InpostBundle\Response\FindPointsResponse;
use Answear\InpostBundle\Response\Struct\Item;
use Answear\InpostBundle\Response\Struct\ItemAddress;
use Answear\InpostBundle\Response\Struct\ItemAddressDetails;
use Answear\InpostBundle\Response\Struct\ItemLocation;
use Answear\InpostBundle\Response\Struct\ItemOperatingHours;
use Answear\InpostBundle\Tests\MockGuzzleTrait;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
Expand All @@ -24,31 +25,30 @@ class FindPointsTest extends TestCase
use MockGuzzleTrait;

private Client $client;
private ConfigProvider $configProvider;

private const POLAND = 'Poland';
private const ITALY = 'Italy';

public function setUp(): void
{
parent::setUp();

$this->client = new Client($this->setupGuzzleClient());
$this->configProvider = new ConfigProvider();
$this->client = new Client($this->configProvider, $this->setupGuzzleClient());
}

/**
* @test
*/
public function successfulFindPoints(): void
public function successfulFindPointsPoland(): void
{
$command = $this->getCommand();
$this->mockGuzzleResponse(new Response(200, [], $this->getSuccessfulBody()));
$this->mockGuzzleResponse(new Response(200, [], $this->getSuccessfulBody(self::POLAND)));

$response = $command->findPoints(new FindPointsRequest());
$response = $this->getCommand()->findPoints(new FindPointsRequest());

$this->assertCount(1, $response->getItems());
$this->assertSame(1, $response->getTotalItemsCount());
$this->assertPoint($response);
}

private function assertPoint(FindPointsResponse $response): void
{
/** @var Item $point */
$point = $response->getItems()->get(0);

Expand All @@ -66,7 +66,7 @@ private function assertPoint(FindPointsResponse $response): void
$this->assertNull($point->locationDescription2);
$this->assertNull($point->distance);
$this->assertSame($point->openingHours, '24/7');
$this->assertSame($point->openingHours, '24/7');
$this->assertInstanceOf(ItemOperatingHours::class, $point->operatingHoursExtended);
$this->assertInstanceOf(ItemAddress::class, $point->address);
$this->assertSame($point->address->line1, 'Kościuszki 27');
$this->assertSame($point->address->line2, '21-412 Adamów');
Expand All @@ -89,14 +89,71 @@ private function assertPoint(FindPointsResponse $response): void
$this->assertTrue($point->location247);
}

/**
* @test
*/
public function successfulFindPointsItaly(): void
{
$this->mockGuzzleResponse(new Response(200, [], $this->getSuccessfulBody(self::ITALY)));

$response = $this->getCommand()->findPoints(new FindPointsRequest());

$this->assertCount(1, $response->getItems());
$this->assertSame(1, $response->getTotalItemsCount());
/** @var Item $point */
$point = $response->getItems()->get(0);

$this->assertNotNull($point);
$this->assertSame($point->id, 'ITAAQ01570P');
$this->assertSame($point->name, 'ITAAQ01570P');
$this->assertSame($point->type, [PointType::Pok, PointType::Pop]);
$this->assertSame($point->status, 'Operating');
$this->assertInstanceOf(ItemLocation::class, $point->location);
$this->assertSame($point->location->longitude, 13.47289);
$this->assertSame($point->location->latitude, 42.35751);
$this->assertSame($point->locationType, 'Indoor');
$this->assertSame($point->locationDescription, 'presso Dottor Tech');
$this->assertNull($point->locationDescription1);
$this->assertNull($point->locationDescription2);
$this->assertNull($point->distance);
$this->assertSame($point->openingHours, 'Lun-Ven: 10:00 - 13:00 - 16:00 - 19:00 ');
$this->assertInstanceOf(ItemOperatingHours::class, $point->operatingHoursExtended);
$this->assertInstanceOf(ItemAddress::class, $point->address);
$this->assertSame($point->address->line1, 'Via Ten. Antonio Rossi Tascione in Str. Vicinale di Paganica 7');
$this->assertSame($point->address->line2, '67100 L\'Aquila');
$this->assertInstanceOf(ItemAddressDetails::class, $point->addressDetails);
$this->assertSame($point->addressDetails->city, 'L\'Aquila');
$this->assertSame($point->addressDetails->province, 'AQ');
$this->assertSame($point->addressDetails->postCode, '67100');
$this->assertSame($point->addressDetails->street, 'Via Ten. Antonio Rossi Tascione in Str. Vicinale di Paganica');
$this->assertSame($point->addressDetails->buildingNumber, '7');
$this->assertNull($point->addressDetails->flatNumber);
$this->assertNull($point->phoneNumber);
$this->assertSame($point->paymentPointDescr, '');
$this->assertSame($point->functions, [
PointFunctionsType::Parcel,
PointFunctionsType::ParcelCollect,
PointFunctionsType::ParcelReverseReturnSend,
PointFunctionsType::ParcelSend,
PointFunctionsType::StandardCourierSend,
]);
$this->assertSame($point->partnerId, 1);
$this->assertFalse($point->isNext);
$this->assertTrue($point->paymentAvailable);
$this->assertSame($point->paymentType, ['3' => 'Payment by cash and card']);
$this->assertSame($point->virtual, '3');
$this->assertNull($point->recommendedLowInterestBoxMachinesList);
$this->assertFalse($point->location247);
}

private function getCommand(): FindPoints
{
return new FindPoints($this->client, new Serializer());
return new FindPoints($this->configProvider, $this->client, new Serializer());
}

private function getSuccessfulBody(): string
private function getSuccessfulBody(string $country): string
{
$response = file_get_contents(__DIR__ . '/data/exampleResponse.json');
$response = file_get_contents(__DIR__ . sprintf('/data/exampleResponse_%s.json', $country));
if (false === $response) {
throw new \RuntimeException('Cannot read example response file');
}
Expand Down
Loading

0 comments on commit 554661b

Please sign in to comment.