1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Skobkin\Bundle\PointToolsBundle\Service\Api; |
4
|
|
|
|
5
|
|
|
use GuzzleHttp\ClientInterface; |
6
|
|
|
use GuzzleHttp\Exception\TransferException; |
7
|
|
|
use JMS\Serializer\DeserializationContext; |
8
|
|
|
use JMS\Serializer\Serializer; |
9
|
|
|
use Psr\Http\Message\ResponseInterface; |
10
|
|
|
use Psr\Http\Message\StreamInterface; |
11
|
|
|
use Psr\Log\LoggerInterface; |
12
|
|
|
use Skobkin\Bundle\PointToolsBundle\Exception\Api\ForbiddenException; |
13
|
|
|
use Skobkin\Bundle\PointToolsBundle\Exception\Api\NetworkException; |
14
|
|
|
use Skobkin\Bundle\PointToolsBundle\Exception\Api\NotFoundException; |
15
|
|
|
use Skobkin\Bundle\PointToolsBundle\Exception\Api\ServerProblemException; |
16
|
|
|
use Skobkin\Bundle\PointToolsBundle\Exception\Api\UnauthorizedException; |
17
|
|
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse; |
18
|
|
|
|
19
|
|
|
class AbstractApi |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* @var ClientInterface HTTP-client from Guzzle |
23
|
|
|
*/ |
24
|
|
|
protected $client; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var Serializer |
28
|
|
|
*/ |
29
|
|
|
protected $serializer; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var LoggerInterface |
33
|
|
|
*/ |
34
|
|
|
protected $logger; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var string Authentication token for API |
38
|
|
|
*/ |
39
|
|
|
protected $authToken; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var string CSRF-token for API |
43
|
|
|
*/ |
44
|
|
|
protected $csRfToken; |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
public function __construct(ClientInterface $httpClient, Serializer $serializer, LoggerInterface $logger) |
48
|
|
|
{ |
49
|
|
|
$this->client = $httpClient; |
50
|
|
|
$this->serializer = $serializer; |
51
|
|
|
$this->logger = $logger; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param string $path Request path |
56
|
|
|
* @param array $parameters Key => Value array of query parameters |
57
|
|
|
* |
58
|
|
|
* @return ResponseInterface |
59
|
|
|
* |
60
|
|
|
* @throws NetworkException |
61
|
|
|
*/ |
62
|
|
View Code Duplication |
public function sendGetRequest(string $path, array $parameters = []): ResponseInterface |
|
|
|
|
63
|
|
|
{ |
64
|
|
|
$this->logger->debug('Sending GET request', ['path' => $path, 'parameters' => $parameters]); |
65
|
|
|
|
66
|
|
|
try { |
67
|
|
|
return $this->client->request('GET', $path, ['query' => $parameters]); |
68
|
|
|
} catch (TransferException $e) { |
69
|
|
|
throw new NetworkException('Request error', $e->getCode(), $e); |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @param string $path Request path |
75
|
|
|
* @param array $parameters Key => Value array of request data |
76
|
|
|
* |
77
|
|
|
* @return ResponseInterface |
78
|
|
|
* |
79
|
|
|
* @throws NetworkException |
80
|
|
|
*/ |
81
|
|
View Code Duplication |
public function sendPostRequest(string $path, array $parameters = []): ResponseInterface |
|
|
|
|
82
|
|
|
{ |
83
|
|
|
$this->logger->debug('Sending POST request', ['path' => $path, 'parameters' => $parameters]); |
84
|
|
|
|
85
|
|
|
try { |
86
|
|
|
return $this->client->request('POST', $path, ['form_params' => $parameters]); |
87
|
|
|
} catch (TransferException $e) { |
88
|
|
|
throw new NetworkException('Request error', $e->getCode(), $e); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Make GET request and return response body |
94
|
|
|
*/ |
95
|
|
|
public function getGetResponseBody($path, array $parameters = []): StreamInterface |
96
|
|
|
{ |
97
|
|
|
$response = $this->sendGetRequest($path, $parameters); |
98
|
|
|
|
99
|
|
|
$this->checkResponse($response); |
100
|
|
|
|
101
|
|
|
return $response->getBody(); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Make POST request and return response body |
106
|
|
|
*/ |
107
|
|
|
public function getPostResponseBody(string $path, array $parameters = []): StreamInterface |
108
|
|
|
{ |
109
|
|
|
$response = $this->sendPostRequest($path, $parameters); |
110
|
|
|
|
111
|
|
|
$this->checkResponse($response); |
112
|
|
|
|
113
|
|
|
return $response->getBody(); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Make GET request and return DTO objects |
118
|
|
|
* |
119
|
|
|
* @return array|object |
120
|
|
|
*/ |
121
|
|
|
public function getGetJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null) |
122
|
|
|
{ |
123
|
|
|
return $this->serializer->deserialize( |
124
|
|
|
$this->getGetResponseBody($path, $parameters), |
125
|
|
|
$type, |
126
|
|
|
'json', |
127
|
|
|
$context |
128
|
|
|
); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Make POST request and return DTO objects |
133
|
|
|
* |
134
|
|
|
* @return array|object |
135
|
|
|
*/ |
136
|
|
|
public function getPostJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null) |
137
|
|
|
{ |
138
|
|
|
return $this->serializer->deserialize( |
139
|
|
|
$this->getPostResponseBody($path, $parameters), |
140
|
|
|
$type, |
141
|
|
|
'json', |
142
|
|
|
$context |
143
|
|
|
); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @throws ForbiddenException |
148
|
|
|
* @throws NotFoundException |
149
|
|
|
* @throws ServerProblemException |
150
|
|
|
* @throws UnauthorizedException |
151
|
|
|
*/ |
152
|
|
|
private function checkResponse(ResponseInterface $response): void |
153
|
|
|
{ |
154
|
|
|
$code = $response->getStatusCode(); |
155
|
|
|
$reason = $response->getReasonPhrase(); |
156
|
|
|
|
157
|
|
|
switch ($code) { |
158
|
|
|
case SymfonyResponse::HTTP_UNAUTHORIZED: |
159
|
|
|
throw new UnauthorizedException($reason, $code); |
160
|
|
|
break; |
|
|
|
|
161
|
|
|
case SymfonyResponse::HTTP_FORBIDDEN: |
162
|
|
|
throw new ForbiddenException($reason, $code); |
163
|
|
|
break; |
|
|
|
|
164
|
|
|
case SymfonyResponse::HTTP_NOT_FOUND: |
165
|
|
|
throw new NotFoundException($reason, $code); |
166
|
|
|
break; |
|
|
|
|
167
|
|
|
case SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR: |
168
|
|
|
case SymfonyResponse::HTTP_NOT_IMPLEMENTED: |
169
|
|
|
case SymfonyResponse::HTTP_BAD_GATEWAY: |
170
|
|
|
case SymfonyResponse::HTTP_SERVICE_UNAVAILABLE: |
171
|
|
|
case SymfonyResponse::HTTP_GATEWAY_TIMEOUT: |
172
|
|
|
throw new ServerProblemException($reason, $code); |
173
|
|
|
break; |
|
|
|
|
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.