Skip to content

Commit eb59f02

Browse files
author
Vincent Chalnot
committed
Major update breaking back-compatibility with command pattern for API queries and fixing cache management
1 parent 1be501d commit eb59f02

23 files changed

Lines changed: 554 additions & 184 deletions

Action/RedirectUrlSetterAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22
/*
33
* This file is part of the CleverAge/OAuthApiBundle package.
44
*

CleverAgeOAuthApiBundle.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22
/*
33
* This file is part of the CleverAge/OAuthApiBundle package.
44
*

Client/ApiClient.php

Lines changed: 50 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22
/*
33
* This file is part of the CleverAge/OAuthApiBundle package.
44
*
@@ -12,12 +12,11 @@
1212

1313
use CleverAge\OAuthApiBundle\Exception\ApiDeserializationException;
1414
use CleverAge\OAuthApiBundle\Exception\ApiRequestException;
15+
use CleverAge\OAuthApiBundle\Request\ApiRequestInterface;
1516
use Http\Client\Exception as HttpException;
1617
use GuzzleHttp\Psr7\Request;
1718
use Http\Client\HttpClient;
18-
use Psr\Cache\InvalidArgumentException;
1919
use Psr\Log\LoggerInterface;
20-
use Symfony\Component\Cache\Adapter\AdapterInterface;
2120
use Symfony\Component\Serializer\SerializerInterface;
2221

2322
/**
@@ -39,160 +38,94 @@ class ApiClient implements ApiClientInterface
3938
/** @var LoggerInterface */
4039
protected $logger;
4140

42-
/** @var AdapterInterface|null */
43-
protected $cacheAdapter;
44-
45-
/** @var string|null */
46-
protected $errorClass;
47-
4841
/**
49-
* @param HttpClient $client
50-
* @param SerializerInterface $serializer
51-
* @param LoggerInterface $logger
52-
* @param string $baseUrl
53-
* @param AdapterInterface|null $cacheAdapter
54-
* @param string|null $errorClass
42+
* @param HttpClient $client
43+
* @param SerializerInterface $serializer
44+
* @param LoggerInterface $logger
45+
* @param string $baseUrl
5546
*/
5647
public function __construct(
5748
HttpClient $client,
5849
SerializerInterface $serializer,
5950
LoggerInterface $logger,
60-
string $baseUrl,
61-
AdapterInterface $cacheAdapter = null,
62-
string $errorClass = null
51+
string $baseUrl
6352
) {
6453
$this->client = $client;
6554
$this->serializer = $serializer;
6655
$this->logger = $logger;
6756
$this->baseUrl = $baseUrl;
68-
$this->cacheAdapter = $cacheAdapter;
69-
$this->errorClass = $errorClass;
7057
}
7158

7259
/**
7360
* {@inheritDoc}
7461
*/
75-
public function getRemoteObject(
76-
string $path,
77-
string $className,
78-
array $deserializationContext = [],
79-
int $ttl = 0,
80-
bool $private = false
81-
) {
82-
$uri = $this->baseUrl.$path;
83-
$request = new Request('GET', $uri);
84-
85-
return $this->fetchRemoteObject($request, $className, $deserializationContext, $ttl, $private);
86-
}
87-
88-
/**
89-
* {@inheritDoc}
90-
*/
91-
public function postRemoteObject(
92-
string $path,
93-
$content,
94-
string $className,
95-
array $serializationContext = [],
96-
array $deserializationContext = []
97-
) {
98-
$serializedData = $this->serializer->serialize($content, 'json', $serializationContext);
99-
// dump(\json_decode($serializedData)); // @todo remove me
100-
101-
$uri = $this->baseUrl.$path;
102-
$request = new Request(
103-
'POST',
104-
$uri,
105-
[
106-
'Content-Type' => 'application/json',
107-
],
108-
$serializedData
109-
);
62+
public function query(ApiRequestInterface $apiRequest)
63+
{
64+
$request = $this->getRequest($apiRequest);
65+
$normalizedData = $this->getResponseData($request);
11066

111-
return $this->fetchRemoteObject($request, $className, $deserializationContext);
67+
return $this->deserialize($apiRequest, $normalizedData);
11268
}
11369

11470
/**
115-
* @param Request $request
116-
* @param string $className
117-
* @param array $deserializationContext
118-
* @param int $ttl
119-
* @param bool $private
71+
* @param ApiRequestInterface $apiRequest
72+
* @param string|null $normalizedData
12073
*
12174
* @return object
12275
*/
123-
protected function fetchRemoteObject(
124-
Request $request,
125-
string $className,
126-
array $deserializationContext = [],
127-
int $ttl = 0,
128-
bool $private = false
129-
) {
130-
$normalizedData = $this->getResponseData($request, $ttl, $private);
131-
// dump(json_decode($normalizedData)); // @todo remove me
132-
76+
protected function deserialize(ApiRequestInterface $apiRequest, ?string $normalizedData)
77+
{
13378
try {
13479
return $this->serializer->deserialize(
13580
$normalizedData,
136-
$className,
81+
$apiRequest->getClassName(),
13782
'json',
138-
$deserializationContext
83+
$apiRequest->getDeserializationContext()
13984
);
14085
} catch (\Exception $e) {
141-
throw $this->handleError($e, $normalizedData, $className, $deserializationContext);
86+
throw $this->handleError(
87+
$e,
88+
$normalizedData,
89+
$apiRequest->getClassName(),
90+
$apiRequest->getDeserializationContext()
91+
);
14292
}
14393
}
14494

14595
/**
146-
* @param Request $request
147-
* @param int $ttl
96+
* @param ApiRequestInterface $apiRequest
14897
*
149-
* @param bool $private
150-
*
151-
* @return string|null
98+
* @return Request
15299
*/
153-
protected function getResponseData(
154-
Request $request,
155-
int $ttl = 0,
156-
bool $private = false
157-
): ?string {
158-
if (!$this->cacheAdapter || 0 === $ttl) {
159-
return $this->doGetResponseData($request);
160-
}
161-
162-
$cacheKey = $this->getCacheKey($request, $private);
163-
164-
$result = null;
165-
try {
166-
$result = $this->cacheAdapter->getItem($cacheKey);
167-
if ($result->isHit()) {
168-
$this->logger->info("Cache hit for request {$request->getUri()}");
169-
170-
return $result->get();
171-
}
172-
} catch (InvalidArgumentException $e) {
173-
$this->logger->alert(
174-
"Unable to access api cache: {$e->getMessage()}",
175-
[
176-
'exception' => $e,
177-
]
100+
protected function getRequest(ApiRequestInterface $apiRequest): Request
101+
{
102+
$serializedContent = null;
103+
if ($apiRequest->getContent()) {
104+
$serializedContent = $this->serializer->serialize(
105+
$apiRequest->getContent(),
106+
'json',
107+
$apiRequest->getSerializationContext()
178108
);
179109
}
180110

181-
$body = $this->doGetResponseData($request);
182-
$result->set($body);
183-
$result->expiresAfter($ttl);
184-
$this->cacheAdapter->save($result);
185-
186-
return $body;
111+
return new Request(
112+
$apiRequest->getMethod(),
113+
$this->baseUrl.$apiRequest->getPath(),
114+
[
115+
'Content-Type' => 'application/json',
116+
],
117+
$serializedContent
118+
);
187119
}
188120

189121
/**
190122
* @param Request $request
191123
*
192-
* @return string
124+
* @return string|null
193125
*/
194-
protected function doGetResponseData(Request $request): string
195-
{
126+
protected function getResponseData(
127+
Request $request
128+
): ?string {
196129
try {
197130
$response = $this->client->sendRequest($request);
198131
} catch (HttpException $e) {
@@ -202,28 +135,6 @@ protected function doGetResponseData(Request $request): string
202135
return (string) $response->getBody();
203136
}
204137

205-
/**
206-
* @param Request $request
207-
* @param bool $private
208-
*
209-
* @return string
210-
*/
211-
protected function getCacheKey(Request $request, bool $private): string
212-
{
213-
$subCacheKey = $request->getMethod().$request->getUri().$request->getBody();
214-
if ($private) {
215-
$client = $this->client;
216-
if ($client instanceof OAuthTokenAwareHttpClientInterface) {
217-
// Append authorization token to cache key if private
218-
$subCacheKey .= $client->getToken()->getAuthorization();
219-
} else {
220-
throw new \UnexpectedValueException('Unable to store private API cache, no private token available');
221-
}
222-
}
223-
224-
return sha1($subCacheKey);
225-
}
226-
227138
/**
228139
* @param \Exception $exception
229140
* @param string|null $normalizedData
@@ -239,15 +150,16 @@ protected function handleError(
239150
array $deserializationContext
240151
): ApiDeserializationException {
241152
$errorObject = null;
242-
if ($this->errorClass) {
153+
$errorClass = $deserializationContext['error_class'] ?? null;
154+
if ($errorClass) {
243155
try {
244156
$errorObject = $this->serializer->deserialize(
245157
$normalizedData,
246-
$this->errorClass,
158+
$errorClass,
247159
'json',
248160
$deserializationContext
249161
);
250-
} catch (\Exception $e) {
162+
} /** @noinspection BadExceptionsProcessingInspection */ catch (\Exception $e) {
251163
$errorObject = \json_decode($normalizedData, true);
252164
}
253165
} else {

Client/ApiClientInterface.php

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types=1);
22
/*
33
* This file is part of the CleverAge/OAuthApiBundle package.
44
*
@@ -10,44 +10,19 @@
1010

1111
namespace CleverAge\OAuthApiBundle\Client;
1212

13+
use CleverAge\OAuthApiBundle\Request\ApiRequestInterface;
14+
1315
/**
14-
* Base logic used to fetch remote objects
16+
* Base logic used to query a remote API
1517
*
1618
* @author Vincent Chalnot <vchalnot@clever-age.com>
1719
*/
1820
interface ApiClientInterface
1921
{
2022
/**
21-
* @param string $path
22-
* @param string $className
23-
* @param array $deserializationContext
24-
* @param int $ttl
25-
* @param bool $private
26-
*
27-
* @return object
28-
*/
29-
public function getRemoteObject(
30-
string $path,
31-
string $className,
32-
array $deserializationContext = [],
33-
int $ttl = 0,
34-
bool $private = false
35-
);
36-
37-
/**
38-
* @param string $path
39-
* @param array|object $content
40-
* @param string $className
41-
* @param array $serializationContext
42-
* @param array $deserializationContext
23+
* @param ApiRequestInterface $request
4324
*
4425
* @return object
4526
*/
46-
public function postRemoteObject(
47-
string $path,
48-
$content,
49-
string $className,
50-
array $serializationContext = [],
51-
array $deserializationContext = []
52-
);
27+
public function query(ApiRequestInterface $request);
5328
}

0 commit comments

Comments
 (0)