Skip to content

Commit

Permalink
Merge pull request #2 from answear/dev-release-v1.0
Browse files Browse the repository at this point in the history
Connection to BoxNow
  • Loading branch information
olekans authored Jun 19, 2023
2 parents 86efc65 + 262b5e7 commit 317b181
Show file tree
Hide file tree
Showing 39 changed files with 1,729 additions and 30 deletions.
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Documentation of the API can be found here: https://boxnow.gr/en/partner-api
* install with Composer

```
composer require git@github.com:answear/boxnow-bundle.git
composer require answear/boxnow-bundle
```

`Answear\BoxNowBundle\AnswearBoxNowBundle::class => ['all' => true],`
Expand All @@ -20,15 +20,35 @@ should be added automatically to your `config/bundles.php` file by Symfony Flex.

```yaml
# config/packages/answear_boxnow.yaml
answear_boxnow:
environment: test|prod
apiKey: yourApiKey
logger: yourCustomLoggerService #default: null
answear_box_now:
clientId: yourClientId
clientSecret: yourClientSecret
apiUrl: apiUrl #default: 'https://api-stage.boxnow.gr'
logger: customLogger #default: null
```
Logger service must implement Psr\Log\LoggerInterface interface.
## Usage
### TODO
### Authorization
```php
/** @var \Answear\BoxNowBundle\Service\AuthorizationService $authorizationService **/
$auth = $authorizationService->authorize();

$auth->getAccessToken();
$auth->getExpiresIn();
$auth->getTokenType();
```
will return `\Answear\BoxNowBundle\Response\AuthorizationResponse`.


### Pickup points
```php
/** @var \Answear\BoxNowBundle\Service\PickupPointService $pickupPoints **/
$pickupPoints->getAll(token: 'accessToken');
```
will return `\Answear\BoxNowBundle\DTO\PickupPointDTO[]`.

Final notes
------------
Expand Down
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
"type": "symfony-bundle",
"license": "MIT",
"require": {
"php": "8.*",
"php": ">=8.1",
"ext-json": "*",
"guzzlehttp/guzzle": "^7.7",
"guzzlehttp/guzzle": "^6.0 || ^7.0",
"psr/log": "^1.1",
"symfony/http-kernel": "^6.3",
"symfony/property-info": "^6.3",
"symfony/serializer": "^6.3",
"symfony/http-kernel": "^6.1",
"symfony/property-info": "^6.1",
"symfony/serializer": "^6.1",
"symfony/serializer-pack": "^1.3",
"webmozart/assert": "^1.3"
},
"require-dev": {
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ parameters:
level: 5
paths:
- %rootDir%/../../../src
ignoreErrors:
-
message: '#.*NodeDefinition::children.*#'
path: ./src/DependencyInjection
52 changes: 52 additions & 0 deletions src/Client/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Answear\BoxNowBundle\Client;

use Answear\BoxNowBundle\Exception\RequestException;
use Answear\BoxNowBundle\Logger\BoxNowLogger;
use Answear\BoxNowBundle\Request\RequestInterface;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;

class Client
{
public function __construct(
private readonly RequestTransformerInterface $requestTransformer,
private readonly BoxNowLogger $logger,
private ?ClientInterface $client = null,
) {
$this->client ??= new GuzzleClient();
}

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

try {
$psrRequest = $this->requestTransformer->transform($request);
$this->logger->logRequest($request->getEndpoint(), $psrRequest);

$response = $this->client->send($psrRequest);

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

if ($response->getBody()->isSeekable()) {
$response->getBody()->rewind();
}
} catch (GuzzleException $exception) {
$this->logger->logError($request->getEndpoint(), $exception);

throw new RequestException($exception->getMessage(), $exception->getCode(), $exception);
} catch (\Throwable $throwable) {
$this->logger->logError($request->getEndpoint(), $throwable);

throw $throwable;
} finally {
$this->logger->clearRequestId();
}

return $response;
}
}
39 changes: 39 additions & 0 deletions src/Client/RequestTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Answear\BoxNowBundle\Client;

use Answear\BoxNowBundle\ConfigProvider;
use Answear\BoxNowBundle\Request\RequestInterface;
use Answear\BoxNowBundle\Serializer\Serializer;
use GuzzleHttp\Psr7\Request as HttpRequest;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface as PsrRequestInterface;

class RequestTransformer implements RequestTransformerInterface
{
public function __construct(
private readonly Serializer $serializer,
private readonly ConfigProvider $configProvider,
) {
}

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

if (!is_null($request->getUrlQuery())) {
$url .= '?' . $request->getUrlQuery();
}

$body = 'GET' === $request->getMethod() ? null : $this->serializer->serialize($request);

return new HttpRequest(
$request->getMethod(),
new Uri($url),
['Content-Type' => 'application/json'] + $request->getHeaders(),
$body
);
}
}
11 changes: 11 additions & 0 deletions src/Client/RequestTransformerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Answear\BoxNowBundle\Client;

use Answear\BoxNowBundle\Request\RequestInterface;
use Psr\Http\Message\RequestInterface as PsrRequestInterface;

interface RequestTransformerInterface
{
public function transform(RequestInterface $request): PsrRequestInterface;
}
8 changes: 8 additions & 0 deletions src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@

class ConfigProvider
{
private const API_URL = 'https://api-stage.boxnow.gr';

public function __construct(
public readonly string $clientId,
public readonly string $clientSecret,
public readonly string $apiUrl = self::API_URL,
) {
}
}
29 changes: 29 additions & 0 deletions src/DTO/PickupPointDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Answear\BoxNowBundle\DTO;

class PickupPointDTO
{
public function __construct(
public readonly string $id,
public readonly string $type,
public readonly string $name,
public readonly string $address,
public readonly ?string $title = null,
public readonly ?string $image = null,
public readonly ?float $latitude = null,
public readonly ?float $longitude = null,
public readonly ?string $postalCode = null,
public readonly ?string $country = null,
public readonly ?string $note = null,
public readonly ?string $additionalAddress = null,
public readonly ?string $expectedDeliveryTime = null,
public readonly ?string $region = null,
) {
}

public function getFullAddress(string $separator = ' '): string
{
return $this->address . $separator . $this->additionalAddress;
}
}
51 changes: 51 additions & 0 deletions src/DependencyInjection/AnswearBoxNowExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,68 @@

namespace Answear\BoxNowBundle\DependencyInjection;

use Answear\BoxNowBundle\ConfigProvider;
use Answear\BoxNowBundle\Logger\BoxNowLogger;
use Psr\Log\NullLogger;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class AnswearBoxNowExtension extends Extension implements PrependExtensionInterface
{
private ?Definition $loggerDefinition;
private array $config;

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

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['clientId'],
$this->config['clientSecret'],
$this->config['apiUrl'],
]);

$this->setLogger($container);
}

private function setLogger(ContainerBuilder $container): void
{
$definition = $container->getDefinition(BoxNowLogger::class);

$definition->setArguments([
$this->loggerDefinition ?? new NullLogger(),
]);
}

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

$configuration = $this->getConfiguration($configs, $container);
$this->config = $this->processConfiguration($configuration, $configs);

if (isset($this->config['logger'])) {
$this->loggerDefinition = $container->getDefinition($this->config['logger']);
}
}
}
12 changes: 11 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
return new TreeBuilder('answear_boxnow');
$treeBuilder = new TreeBuilder('answear_box_now');

$treeBuilder->getRootNode()
->children()
->scalarNode('clientId')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('clientSecret')->isRequired()->cannotBeEmpty()->end()
?->scalarNode('apiUrl')->defaultNull()->end()
?->scalarNode('logger')->defaultNull()->end()
?->end();

return $treeBuilder;
}
}
7 changes: 7 additions & 0 deletions src/Exception/CoreException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Answear\BoxNowBundle\Exception;

class CoreException extends \RuntimeException
{
}
7 changes: 7 additions & 0 deletions src/Exception/RequestException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Answear\BoxNowBundle\Exception;

class RequestException extends CoreException
{
}
Loading

0 comments on commit 317b181

Please sign in to comment.