Skip to content

Commit d85fa0b

Browse files
authored
Merge pull request #2 from BitBagCommerce/feature/UC-3-api-client
[UC-3] Api client
2 parents 62a1275 + 9d14e2a commit d85fa0b

27 files changed

Lines changed: 713 additions & 4 deletions

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@
1616
# Symfony CLI https://symfony.com/doc/current/setup/symfony_server.html#different-php-settings-per-project
1717
/.php-version
1818
/php.ini
19+
20+
###> friendsofphp/php-cs-fixer ###
21+
/.php-cs-fixer.php
22+
/.php-cs-fixer.cache
23+
###< friendsofphp/php-cs-fixer ###

composer.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"license": "MIT",
77
"require": {
88
"php": "^8.1",
9+
"bitbag/coding-standard": "^3.0",
910
"sylius/sylius": "~1.13.0",
1011
"symfony/webpack-encore-bundle": "^1.15"
1112
},
@@ -59,11 +60,16 @@
5960
},
6061
"autoload": {
6162
"psr-4": {
62-
"BitBag\\SyliusUserComPlugin\\": "src/",
63-
"Tests\\BitBag\\SyliusUserComPlugin\\": "tests/"
63+
"BitBag\\SyliusUserComPlugin\\": "src/"
6464
}
6565
},
6666
"autoload-dev": {
67+
"psr-4": {
68+
"Tests\\BitBag\\SyliusUserComPlugin\\": [
69+
"tests/Application/src",
70+
"tests"
71+
]
72+
},
6773
"classmap": [
6874
"tests/Application/Kernel.php"
6975
]

config/services.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22

33
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
4-
<services>
5-
</services>
4+
<imports>
5+
<import resource="services/*"/>
6+
</imports>
67
</container>

config/services/api.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
4+
<services>
5+
<defaults autowire="false" autoconfigure="false"/>
6+
<service id="bit_bag.sylius_user_com_plugin.api.user_api" class="BitBag\SyliusUserComPlugin\Api\UserApi">
7+
<argument type="service" id="http_client"/>
8+
<argument type="service" id="monolog.logger"/>
9+
</service>
10+
11+
<service id="bit_bag.sylius_user_com_plugin.api.deal_api" class="BitBag\SyliusUserComPlugin\Api\DealApi">
12+
<argument type="service" id="http_client"/>
13+
<argument type="service" id="monolog.logger"/>
14+
</service>
15+
16+
<service id="bit_bag.sylius_user_com_plugin.api.product_api" class="BitBag\SyliusUserComPlugin\Api\ProductApi">
17+
<argument type="service" id="http_client"/>
18+
<argument type="service" id="monolog.logger"/>
19+
</service>
20+
</services>
21+
</container>

src/Api/AbstractClient.php

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
/*
4+
* This file has been created by developers from BitBag.
5+
* Feel free to contact us once you face any issues or want to start
6+
* You can find more information about us on https://bitbag.io and write us
7+
* an email on hello@bitbag.io.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace BitBag\SyliusUserComPlugin\Api;
13+
14+
use BitBag\SyliusUserComPlugin\Trait\UserComApiAwareInterface;
15+
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Contracts\HttpClient\HttpClientInterface;
18+
use Symfony\Contracts\HttpClient\ResponseInterface;
19+
20+
abstract class AbstractClient
21+
{
22+
private const API_ENDPOINT_PREFIX = '/api/public/';
23+
24+
public function __construct(
25+
private readonly HttpClientInterface $client,
26+
private readonly LoggerInterface $logger,
27+
) {
28+
}
29+
30+
protected function request(
31+
string $path,
32+
string $method,
33+
array $options,
34+
): ?array {
35+
try {
36+
/** @var ResponseInterface $response */
37+
$response = $this->client->request(
38+
$method,
39+
$path,
40+
$options,
41+
);
42+
43+
$status = $response->getStatusCode();
44+
if ($status >= Response::HTTP_OK && $status < Response::HTTP_MULTIPLE_CHOICES) {
45+
return $response->toArray();
46+
}
47+
48+
throw new \Exception(
49+
sprintf(
50+
'Response status code : %s, response : %s',
51+
$status,
52+
$response->getContent(false),
53+
),
54+
);
55+
} catch (\Exception $e) {
56+
$this->logger->critical(sprintf(
57+
'User.com API request failed: %s',
58+
$e->getMessage(),
59+
), [
60+
'path' => $path,
61+
'method' => $method,
62+
'options' => $options,
63+
]);
64+
65+
return null;
66+
}
67+
}
68+
69+
protected function getApiEndpointUrl(
70+
UserComApiAwareInterface $resource,
71+
string $endpoint,
72+
string $query = null,
73+
): string {
74+
if (null === $resource->getUserComUrl()) {
75+
throw new \InvalidArgumentException('User.com API key is missing.');
76+
}
77+
78+
$url = sprintf(
79+
'%s/%s/%s/',
80+
trim($resource->getUserComUrl(), '/'),
81+
trim(self::API_ENDPOINT_PREFIX, '/'),
82+
trim($endpoint, '/'),
83+
);
84+
85+
if (null === $query) {
86+
return $url;
87+
}
88+
89+
return sprintf('%s%s/', $url, $query);
90+
}
91+
92+
protected function buildOptions(
93+
UserComApiAwareInterface $resource,
94+
array $options = [],
95+
): array {
96+
$options['headers']['Accept'] = ' */*; version=2';
97+
$options['headers']['Authorization'] = $this->authorizeRequest($resource);
98+
99+
return $options;
100+
}
101+
102+
protected function authorizeRequest(
103+
UserComApiAwareInterface $resource,
104+
): string {
105+
if (null === $resource->getUserComApiKey()) {
106+
throw new \InvalidArgumentException('User.com API key is missing.');
107+
}
108+
109+
return sprintf(
110+
'Token %s',
111+
$resource->getUserComApiKey(),
112+
);
113+
}
114+
}

src/Api/DealApi.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* This file has been created by developers from BitBag.
5+
* Feel free to contact us once you face any issues or want to start
6+
* You can find more information about us on https://bitbag.io and write us
7+
* an email on hello@bitbag.io.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace BitBag\SyliusUserComPlugin\Api;
13+
14+
use BitBag\SyliusUserComPlugin\Trait\UserComApiAwareInterface;
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
final class DealApi extends AbstractClient implements DealApiInterface
18+
{
19+
public function updateDealByCustomId(UserComApiAwareInterface $resource, string $customId, array $data): ?array
20+
{
21+
$url = $this->getApiEndpointUrl($resource, sprintf(self::UPDATE_DEAL_ENDPOINT, $customId));
22+
23+
return $this->request(
24+
$url,
25+
Request::METHOD_PUT,
26+
$this->buildOptions($resource, ['json' => $data]),
27+
);
28+
}
29+
30+
public function createDeal(UserComApiAwareInterface $resource, array $data): ?array
31+
{
32+
return $this->request(
33+
$this->getApiEndpointUrl($resource, self::CREATE_DEAL_ENDPOINT),
34+
Request::METHOD_POST,
35+
$this->buildOptions($resource, [
36+
'json' => $data,
37+
'headers' => [
38+
'Content-Type' => 'application/json',
39+
],
40+
]),
41+
);
42+
}
43+
44+
public function updateOrCreateDeal(UserComApiAwareInterface $resource, array $data): ?array
45+
{
46+
return $this->request(
47+
$this->getApiEndpointUrl($resource, self::CREATE_OR_UPDATE_DEAL_ENDPOINT),
48+
Request::METHOD_POST,
49+
$this->buildOptions($resource, [
50+
'json' => $data,
51+
'headers' => [
52+
'Content-Type' => 'application/json',
53+
],
54+
]),
55+
);
56+
}
57+
}

src/Api/DealApiInterface.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file has been created by developers from BitBag.
5+
* Feel free to contact us once you face any issues or want to start
6+
* You can find more information about us on https://bitbag.io and write us
7+
* an email on hello@bitbag.io.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace BitBag\SyliusUserComPlugin\Api;
13+
14+
use BitBag\SyliusUserComPlugin\Trait\UserComApiAwareInterface;
15+
16+
interface DealApiInterface
17+
{
18+
public const CREATE_DEAL_ENDPOINT = '/deals/';
19+
20+
public const UPDATE_DEAL_ENDPOINT = '/deals-by-id/%s/';
21+
22+
public const CREATE_OR_UPDATE_DEAL_ENDPOINT = '/deals/update_or_create/';
23+
24+
public function updateDealByCustomId(UserComApiAwareInterface $resource, string $customId, array $data): ?array;
25+
26+
public function createDeal(UserComApiAwareInterface $resource, array $data): ?array;
27+
28+
public function updateOrCreateDeal(UserComApiAwareInterface $resource, array $data): ?array;
29+
}

src/Api/ProductApi.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file has been created by developers from BitBag.
5+
* Feel free to contact us once you face any issues or want to start
6+
* You can find more information about us on https://bitbag.io and write us
7+
* an email on hello@bitbag.io.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace BitBag\SyliusUserComPlugin\Api;
13+
14+
use BitBag\SyliusUserComPlugin\Trait\UserComApiAwareInterface;
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
final class ProductApi extends AbstractClient implements ProductApiInterface
18+
{
19+
public function getProductByCustomId(UserComApiAwareInterface $resource, int $productId): ?array
20+
{
21+
$url = $this->getApiEndpointUrl($resource, sprintf(self::GET_PRODUCT_BY_CUSTOM_ID_ENDPOINT, $productId));
22+
23+
return $this->request(
24+
$url,
25+
Request::METHOD_GET,
26+
$this->buildOptions($resource),
27+
);
28+
}
29+
}

src/Api/ProductApiInterface.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file has been created by developers from BitBag.
5+
* Feel free to contact us once you face any issues or want to start
6+
* You can find more information about us on https://bitbag.io and write us
7+
* an email on hello@bitbag.io.
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace BitBag\SyliusUserComPlugin\Api;
13+
14+
use BitBag\SyliusUserComPlugin\Trait\UserComApiAwareInterface;
15+
16+
interface ProductApiInterface
17+
{
18+
public const GET_PRODUCT_BY_CUSTOM_ID_ENDPOINT = '/products-by-id/%s/product_event/';
19+
20+
public function getProductByCustomId(UserComApiAwareInterface $resource, int $productId): ?array;
21+
}

0 commit comments

Comments
 (0)