Skip to content

Commit

Permalink
Merge pull request #5 from answear/change-endpoint
Browse files Browse the repository at this point in the history
Change endpoint
  • Loading branch information
yekovalenkoa authored Sep 20, 2024
2 parents 958b982 + fb47e89 commit 3a1e152
Show file tree
Hide file tree
Showing 27 changed files with 408 additions and 170 deletions.
2 changes: 1 addition & 1 deletion .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
'strict_param' => false,
'array_syntax' => ['syntax' => 'short'],
'concat_space' => ['spacing' => 'one'],
'phpdoc_align' => [],
'phpdoc_align' => ['align' => 'left'],
'phpdoc_summary' => false,
'void_return' => false,
'phpdoc_var_without_name' => false,
Expand Down
31 changes: 28 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# FanCourier bundle

FanCourier integration for Symfony.
Documentation of the API can be found here: https://github.com/FAN-Courier/API-Docs
Documentation of the API can be found here: https://www.fancourier.ro/wp-content/uploads/2023/07/EN_FANCourier_API-2.0-160523.pdf

## Installation

Expand All @@ -19,17 +19,42 @@ should be added automatically to your `config/bundles.php` file by Symfony Flex.
```yaml
# config/packages/answear_fancourier.yaml
answear_fan_courier:
clientId: yourClientId
username: yourUsername
password: yourPassword
apiUrl: apiUrl
logger: customLogger #default: null
```
Logger service must implement Psr\Log\LoggerInterface interface.
## Usage
### TODO
### Get pickup points
```php
namespace App\Service\PickupPointsImporter;

use Answear\FanCourierBundle\Service\PickupPointService;

class FanCourierImport
{
public function __construct(
private PickupPointService $pickupPointService,
) {
}

/**
* @return PickupPointDTO[]
*/
public function getPickupPoints(): array
{
return $this->pickupPointService->getAll();
}
}

```

Above `getPickupPoints` method will return an array of `Answear\FanCourierBundle\DTO\PickupPointDTO` objects.

Final notes
------------
Expand Down
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
"webmozart/assert": "^1.3"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.4",
"matthiasnoback/symfony-config-test": "^5.0.0",
"phpro/grumphp": "^1.5.0",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-webmozart-assert": "^1.2",
"phpunit/phpunit": "10.4.*",
"friendsofphp/php-cs-fixer": "^3.63.2",
"matthiasnoback/symfony-config-test": "^5.2",
"phpro/grumphp": "^2.7.0",
"phpstan/phpstan": "^1.12",
"phpstan/phpstan-webmozart-assert": "^1.2.10",
"phpunit/phpunit": "^10.5.30",
"roave/security-advisories": "dev-master",
"symfony/phpunit-bridge": "6.3.*"
"symfony/phpunit-bridge": "6.4.*"
},
"autoload": {
"psr-4": {
Expand Down
29 changes: 28 additions & 1 deletion src/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace Answear\FanCourierBundle\Client;

use Answear\FanCourierBundle\ConfigProvider;
use Answear\FanCourierBundle\Exception\RequestException;
use Answear\FanCourierBundle\Exception\ResponseException;
use Answear\FanCourierBundle\Logger\FanCourierLogger;
use Answear\FanCourierBundle\Request\LoginRequest;
use Answear\FanCourierBundle\Request\RequestInterface;
use Answear\FanCourierBundle\Response\LoginResponse;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
Expand All @@ -15,21 +18,45 @@ class Client
{
private const CONNECTION_TIMEOUT = 10;
private const TIMEOUT = 30;


private ?string $token = null;

public function __construct(
private readonly RequestTransformerInterface $requestTransformer,
private readonly FanCourierLogger $logger,
private readonly ConfigProvider $configProvider,
private ?ClientInterface $client = null,
) {
$this->client ??= new GuzzleClient(['timeout' => self::TIMEOUT, 'connect_timeout' => self::CONNECTION_TIMEOUT]);
}

public function login(): void
{
$loginRequest = new LoginRequest(
$this->configProvider->username,
$this->configProvider->password,
);

$response = $this->request($loginRequest);

$loginResponse = LoginResponse::fromArray(
\json_decode($response->getBody()->getContents(), true),
);

$this->token = $loginResponse->token;
}

public function request(RequestInterface $request): ResponseInterface
{
$this->logger->setRequestId(uniqid('FANCOURIER-', more_entropy: true));

try {
$psrRequest = $this->requestTransformer->transform($request);

if ($this->token) {
$psrRequest = $psrRequest->withHeader('Authorization', 'Bearer ' . $this->token);
}

$this->logger->logRequest($request->getEndpoint(), $psrRequest);

$response = $this->client->send($psrRequest);
Expand Down
14 changes: 7 additions & 7 deletions src/Client/RequestTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Answear\FanCourierBundle\ConfigProvider;
use Answear\FanCourierBundle\Request\RequestInterface;
use Answear\FanCourierBundle\Serializer\Serializer;
use GuzzleHttp\Psr7\Request as HttpRequest;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface as PsrRequestInterface;
Expand All @@ -14,24 +15,23 @@ class RequestTransformer implements RequestTransformerInterface
{
public function __construct(
private readonly ConfigProvider $configProvider,
private Serializer $serializer,
) {
}

public function transform(RequestInterface $request): PsrRequestInterface
{
$url = $this->configProvider->apiUrl . $request->getEndpoint();

$formParams = [
'username' => $this->configProvider->username,
'client_id' => $this->configProvider->clientId,
'user_pass' => $this->configProvider->password,
];
if (!empty($request->getQueryParams())) {
$url .= '?' . http_build_query($request->getQueryParams());
}

return new HttpRequest(
$request->getMethod(),
new Uri($url),
['Content-Type' => 'application/x-www-form-urlencoded'],
http_build_query(array_merge($formParams, $request->getOptions()))
['Content-Type' => 'application/json'],
'GET' === $request->getMethod() ? null : $this->serializer->serialize($request),
);
}
}
1 change: 0 additions & 1 deletion src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
class ConfigProvider
{
public function __construct(
public readonly string $clientId,
public readonly string $username,
public readonly string $password,
public readonly string $apiUrl,
Expand Down
43 changes: 43 additions & 0 deletions src/DTO/AddressDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Answear\FanCourierBundle\DTO;

use Webmozart\Assert\Assert;

class AddressDTO
{
public function __construct(
public readonly string $locality,
public readonly string $county,
public readonly string $street,
public readonly string $streetNo,
public readonly string $zipCode,
public readonly string $floor,
public readonly string $reference,
) {
}

/**
* @param array{locality: string, county: string, street: string, streetNo: string, zipCode: string, floor: string, reference: string} $addressArray
*/
public static function fromArray(array $addressArray): self
{
Assert::stringNotEmpty($addressArray['locality']);
Assert::stringNotEmpty($addressArray['county']);
Assert::stringNotEmpty($addressArray['street']);
Assert::stringNotEmpty($addressArray['streetNo']);
Assert::stringNotEmpty($addressArray['zipCode']);

return new self(
$addressArray['locality'],
$addressArray['county'],
$addressArray['street'],
$addressArray['streetNo'],
$addressArray['zipCode'],
$addressArray['floor'],
$addressArray['reference'],
);
}
}
4 changes: 2 additions & 2 deletions src/DTO/DrawerCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ class DrawerCollection
* @param DrawerDTO[] $drawers
*/
public function __construct(
public readonly array $drawers = []
public readonly array $drawers = [],
) {
}

/**
* @param array<array{number: int, type: string}> $drawerArray
* @param array<array{type: string, number: int}> $drawerArray
*/
public static function fromArray(array $drawerArray): self
{
Expand Down
2 changes: 1 addition & 1 deletion src/DTO/DrawerDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class DrawerDTO
{
public function __construct(
public readonly int $number,
public readonly string $type
public readonly string $type,
) {
}
}
56 changes: 23 additions & 33 deletions src/DTO/PickupPointDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,42 @@ class PickupPointDTO
{
public function __construct(
public readonly string $id,
public readonly string $code,
public readonly string $name,
public readonly string $routingLocation,
public readonly string $description,
public readonly string $county,
public readonly string $locality,
public readonly string $address,
public readonly string $zipCode,
public readonly string $locationReference,
public readonly AddressDTO $address,
public readonly float $latitude,
public readonly float $longitude,
public readonly ScheduleCollection $schedule,
public readonly DrawerCollection $drawer
public readonly DrawerCollection $drawer,
) {
}

public static function fromArray(array $pickupPoint): self
{
Assert::stringNotEmpty($pickupPoint['Id']);
Assert::stringNotEmpty($pickupPoint['Name']);
Assert::stringNotEmpty($pickupPoint['RoutingLocation']);
Assert::stringNotEmpty($pickupPoint['Description']);
Assert::stringNotEmpty($pickupPoint['County']);
Assert::stringNotEmpty($pickupPoint['Locality']);
Assert::stringNotEmpty($pickupPoint['Address']);
Assert::stringNotEmpty($pickupPoint['ZipCode']);
Assert::stringNotEmpty($pickupPoint['LocationReference']);
Assert::float($pickupPoint['Latitude']);
Assert::float($pickupPoint['Longitude']);
Assert::range($pickupPoint['Latitude'], -90, 90);
Assert::range($pickupPoint['Longitude'], -180, 180);
Assert::count($pickupPoint['Schedule'], 7);
Assert::stringNotEmpty($pickupPoint['id']);
Assert::stringNotEmpty($pickupPoint['name']);
Assert::stringNotEmpty($pickupPoint['routingLocation']);
Assert::stringNotEmpty($pickupPoint['description']);
Assert::notEmpty($pickupPoint['address']);
Assert::stringNotEmpty($pickupPoint['latitude']);
Assert::stringNotEmpty($pickupPoint['longitude']);
Assert::range((float) $pickupPoint['latitude'], -90, 90);
Assert::range((float) $pickupPoint['longitude'], -180, 180);
Assert::count($pickupPoint['schedule'], 7);

return new self(
$pickupPoint['Id'],
$pickupPoint['Name'],
$pickupPoint['RoutingLocation'],
$pickupPoint['Description'],
$pickupPoint['County'],
$pickupPoint['Locality'],
$pickupPoint['Address'],
$pickupPoint['ZipCode'],
$pickupPoint['LocationReference'],
$pickupPoint['Latitude'],
$pickupPoint['Longitude'],
ScheduleCollection::fromArray($pickupPoint['Schedule']),
DrawerCollection::fromArray($pickupPoint['Drawer'])
$pickupPoint['id'],
$pickupPoint['code'],
$pickupPoint['name'],
$pickupPoint['routingLocation'],
$pickupPoint['description'],
AddressDTO::fromArray($pickupPoint['address']),
(float) $pickupPoint['latitude'],
(float) $pickupPoint['longitude'],
ScheduleCollection::fromArray($pickupPoint['schedule']),
DrawerCollection::fromArray($pickupPoint['drawer']),
);
}
}
10 changes: 5 additions & 5 deletions src/DTO/ScheduleCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ class ScheduleCollection
* @param ScheduleDTO[] $schedules
*/
public function __construct(
public readonly array $schedules = []
public readonly array $schedules = [],
) {
}

/**
* @param array<array{startHour: string, stopHour: string}> $scheduleArray
* @param array<array{firstHour: string, secondHour: string}> $scheduleArray
*/
public static function fromArray(array $scheduleArray): self
{
$schedules = [];
foreach ($scheduleArray as $schedule) {
Assert::stringNotEmpty($schedule['startHour']);
Assert::stringNotEmpty($schedule['stopHour']);
$schedules[] = new ScheduleDTO($schedule['startHour'], $schedule['stopHour']);
Assert::stringNotEmpty($schedule['firstHour']);
Assert::stringNotEmpty($schedule['secondHour']);
$schedules[] = new ScheduleDTO($schedule['firstHour'], $schedule['secondHour']);
}

return new self($schedules);
Expand Down
4 changes: 2 additions & 2 deletions src/DTO/ScheduleDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
class ScheduleDTO
{
public function __construct(
public readonly string $startHour,
public readonly string $stopHour
public readonly string $firstHour,
public readonly string $secondHour,
) {
}
}
1 change: 0 additions & 1 deletion src/DependencyInjection/AnswearFanCourierExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public function load(array $configs, ContainerBuilder $container): void

$definition = $container->getDefinition(ConfigProvider::class);
$definition->setArguments([
$this->config['clientId'],
$this->config['username'],
$this->config['password'],
$this->config['apiUrl'],
Expand Down
3 changes: 1 addition & 2 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ public function getConfigTreeBuilder(): TreeBuilder

$treeBuilder->getRootNode()
->children()
->scalarNode('clientId')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('username')->isRequired()->cannotBeEmpty()->end()
->scalarNode('username')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('password')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('apiUrl')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('logger')->defaultNull()->end()
Expand Down
Loading

0 comments on commit 3a1e152

Please sign in to comment.