|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Skobkin\Bundle\PointToolsBundle\Service; |
|
4
|
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
|
6
|
|
|
use Doctrine\ORM\EntityRepository; |
|
7
|
|
|
use GuzzleHttp\ClientInterface; |
|
8
|
|
|
use GuzzleHttp\Exception\RequestException; |
|
9
|
|
|
use JMS\Serializer\Serializer; |
|
10
|
|
|
use Psr\Log\LoggerInterface; |
|
11
|
|
|
use Skobkin\Bundle\PointToolsBundle\DTO\Api\Auth; |
|
12
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\User; |
|
13
|
|
|
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\ApiException; |
|
14
|
|
|
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\InvalidResponseException; |
|
15
|
|
|
use Skobkin\Bundle\PointToolsBundle\Service\Exceptions\UserNotFoundException; |
|
16
|
|
|
use Symfony\Component\HttpFoundation\Response; |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Basic Point.im user API functions from /api/user/* |
|
20
|
|
|
*/ |
|
21
|
|
|
class UserApi extends AbstractApi |
|
22
|
|
|
{ |
|
23
|
|
|
/** |
|
24
|
|
|
* @var EntityManager |
|
25
|
|
|
*/ |
|
26
|
|
|
protected $em; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @var EntityRepository |
|
30
|
|
|
*/ |
|
31
|
|
|
protected $userRepository; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* @var Serializer |
|
35
|
|
|
*/ |
|
36
|
|
|
private $serializer; |
|
37
|
|
|
|
|
38
|
|
|
public function __construct(ClientInterface $httpClient, LoggerInterface $logger, EntityManager $entityManager, Serializer $serializer) |
|
|
|
|
|
|
39
|
|
|
{ |
|
40
|
|
|
parent::__construct($httpClient, $logger); |
|
41
|
|
|
|
|
42
|
|
|
$this->em = $entityManager; |
|
43
|
|
|
$this->serializer = $serializer; |
|
44
|
|
|
// @todo refactor |
|
45
|
|
|
$this->userRepository = $this->em->getRepository('SkobkinPointToolsBundle:User'); |
|
46
|
|
|
} |
|
47
|
12 |
|
|
|
48
|
|
|
public function isAuthDataValid(string $login, string $password): bool |
|
49
|
12 |
|
{ |
|
50
|
|
|
$this->logger->info('Checking user auth data via point.im API'); |
|
51
|
12 |
|
|
|
52
|
12 |
|
$auth = $this->authenticate($login, $password); |
|
53
|
12 |
|
|
|
54
|
12 |
|
if (null === $auth->getError() && null !== $auth->getToken()) { |
|
55
|
|
|
$this->logger->debug('Authentication successfull. Logging out.'); |
|
56
|
|
|
|
|
57
|
|
|
$this->logout($auth); |
|
58
|
|
|
|
|
59
|
|
|
return true; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
return false; |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
public function authenticate(string $login, string $password): Auth |
|
66
|
|
|
{ |
|
67
|
|
|
$this->logger->debug('Trying to authenticate user via Point.im API', ['login' => $login]); |
|
68
|
|
|
|
|
69
|
|
|
try { |
|
70
|
|
|
$authData = $this->getPostRequestData( |
|
71
|
|
|
'/api/login', |
|
72
|
|
|
[ |
|
73
|
|
|
'login' => $login, |
|
74
|
|
|
'password' => $password, |
|
75
|
|
|
] |
|
76
|
|
|
); |
|
77
|
|
|
|
|
78
|
|
|
return $this->serializer->deserialize($authData, Auth::class, 'json'); |
|
|
|
|
|
|
79
|
|
|
} catch (RequestException $e) { |
|
80
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
81
|
|
|
throw new InvalidResponseException('API method not found', 0, $e); |
|
82
|
|
|
} else { |
|
83
|
|
|
throw $e; |
|
84
|
|
|
} |
|
85
|
|
|
} |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
public function logout(Auth $auth): bool |
|
89
|
|
|
{ |
|
90
|
|
|
$this->logger->debug('Trying to log user out via Point.im API'); |
|
91
|
|
|
|
|
92
|
|
|
try { |
|
93
|
|
|
$this->getPostRequestData('/api/logout', ['csrf_token' => $auth->getCsRfToken()]); |
|
94
|
|
|
|
|
95
|
|
|
return true; |
|
96
|
|
|
} catch (RequestException $e) { |
|
97
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
98
|
|
|
throw new InvalidResponseException('API method not found', 0, $e); |
|
99
|
|
|
} elseif (Response::HTTP_FORBIDDEN === $e->getResponse()->getStatusCode()) { |
|
100
|
|
|
return true; |
|
101
|
|
|
} else { |
|
102
|
|
|
throw $e; |
|
103
|
|
|
} |
|
104
|
|
|
} |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
/** |
|
108
|
|
|
* Get user subscribers by user login |
|
109
|
|
|
* |
|
110
|
|
|
* @param string $login |
|
111
|
|
|
* |
|
112
|
|
|
* @return User[] |
|
113
|
|
|
* |
|
114
|
|
|
* @throws ApiException |
|
115
|
|
|
* @throws InvalidResponseException |
|
116
|
|
|
* @throws UserNotFoundException |
|
117
|
|
|
*/ |
|
118
|
|
View Code Duplication |
public function getUserSubscribersByLogin(string $login): array |
|
|
|
|
|
|
119
|
|
|
{ |
|
120
|
|
|
$this->logger->debug('Trying to get user subscribers by login', ['login' => $login]); |
|
121
|
|
|
|
|
122
|
|
|
try { |
|
123
|
|
|
$usersList = $this->getGetRequestData('/api/user/'.urlencode($login).'/subscribers', [], true); |
|
124
|
|
|
} catch (RequestException $e) { |
|
125
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
126
|
|
|
throw new UserNotFoundException('User not found', 0, $e, null, $login); |
|
127
|
|
|
} else { |
|
128
|
|
|
throw $e; |
|
129
|
|
|
} |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
return $this->getUsersFromList($usersList); |
|
|
|
|
|
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
/** |
|
136
|
|
|
* Get user subscribers by user id |
|
137
|
|
|
* |
|
138
|
|
|
* @param int $id |
|
139
|
|
|
* |
|
140
|
|
|
* @return User[] |
|
141
|
|
|
* |
|
142
|
|
|
* @throws ApiException |
|
143
|
|
|
* @throws InvalidResponseException |
|
144
|
|
|
* @throws UserNotFoundException |
|
145
|
|
|
*/ |
|
146
|
|
View Code Duplication |
public function getUserSubscribersById(int $id): array |
|
|
|
|
|
|
147
|
|
|
{ |
|
148
|
|
|
$this->logger->debug('Trying to get user subscribers by id', ['id' => $id]); |
|
149
|
|
|
|
|
150
|
|
|
try { |
|
151
|
|
|
$usersList = $this->getGetRequestData('/api/user/id/'.(int) $id.'/subscribers', [], true); |
|
152
|
|
|
} catch (RequestException $e) { |
|
153
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
154
|
|
|
throw new UserNotFoundException('User not found', 0, $e, $id); |
|
155
|
|
|
} else { |
|
156
|
|
|
throw $e; |
|
157
|
|
|
} |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
return $this->getUsersFromList($usersList); |
|
|
|
|
|
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Get user subscriptions by user login |
|
165
|
|
|
* |
|
166
|
|
|
* @param string $login |
|
167
|
|
|
* |
|
168
|
|
|
* @return User[] |
|
169
|
|
|
* |
|
170
|
|
|
* @throws ApiException |
|
171
|
|
|
* @throws InvalidResponseException |
|
172
|
|
|
* @throws UserNotFoundException |
|
173
|
|
|
*/ |
|
174
|
|
View Code Duplication |
public function getUserSubscriptionsByLogin(string $login): array |
|
|
|
|
|
|
175
|
|
|
{ |
|
176
|
|
|
$this->logger->debug('Trying to get user subscriptions by login', ['login' => $login]); |
|
177
|
|
|
|
|
178
|
|
|
try { |
|
179
|
|
|
$usersList = $this->getGetRequestData('/api/user/'.urlencode($login).'/subscriptions', [], true); |
|
180
|
|
|
} catch (RequestException $e) { |
|
181
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
182
|
|
|
throw new UserNotFoundException('User not found', 0, $e, null, $login); |
|
183
|
|
|
} else { |
|
184
|
|
|
throw $e; |
|
185
|
|
|
} |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
return $this->getUsersFromList($usersList); |
|
|
|
|
|
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* Get user subscriptions by user id |
|
193
|
|
|
* |
|
194
|
|
|
* @param int $id |
|
195
|
|
|
* |
|
196
|
|
|
* @return User[] |
|
197
|
|
|
* |
|
198
|
|
|
* @throws ApiException |
|
199
|
|
|
* @throws InvalidResponseException |
|
200
|
|
|
* @throws UserNotFoundException |
|
201
|
|
|
*/ |
|
202
|
|
View Code Duplication |
public function getUserSubscriptionsById(int $id): array |
|
|
|
|
|
|
203
|
|
|
{ |
|
204
|
|
|
$this->logger->debug('Trying to get user subscriptions by id', ['id' => $id]); |
|
205
|
|
|
|
|
206
|
|
|
try { |
|
207
|
|
|
$usersList = $this->getGetRequestData('/api/user/id/'.(int) $id.'/subscriptions', [], true); |
|
208
|
|
|
} catch (RequestException $e) { |
|
209
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
210
|
|
|
throw new UserNotFoundException('User not found', 0, $e, $id); |
|
211
|
|
|
} else { |
|
212
|
|
|
throw $e; |
|
213
|
|
|
} |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
return $this->getUsersFromList($usersList); |
|
|
|
|
|
|
217
|
|
|
} |
|
218
|
|
|
|
|
219
|
|
|
/** |
|
220
|
|
|
* Get single user by login |
|
221
|
|
|
* |
|
222
|
|
|
* @param string $login |
|
223
|
|
|
* |
|
224
|
|
|
* @return User |
|
225
|
|
|
* |
|
226
|
|
|
* @throws UserNotFoundException |
|
227
|
|
|
* @throws RequestException |
|
228
|
|
|
*/ |
|
229
|
|
View Code Duplication |
public function getUserByLogin(string $login): User |
|
|
|
|
|
|
230
|
|
|
{ |
|
231
|
|
|
$this->logger->debug('Trying to get user by login', ['login' => $login]); |
|
232
|
|
|
|
|
233
|
|
|
try { |
|
234
|
|
|
$userInfo = $this->getGetRequestData('/api/user/login/'.urlencode($login), [], true); |
|
235
|
|
|
} catch (RequestException $e) { |
|
236
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
237
|
|
|
throw new UserNotFoundException('User not found', 0, $e, null, $login); |
|
238
|
|
|
} else { |
|
239
|
|
|
throw $e; |
|
240
|
|
|
} |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
return $this->getUserFromUserInfo($userInfo); |
|
|
|
|
|
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* Get single user by id |
|
248
|
|
|
* |
|
249
|
|
|
* @param int $id |
|
250
|
|
|
* |
|
251
|
|
|
* @return User |
|
252
|
|
|
* |
|
253
|
|
|
* @throws UserNotFoundException |
|
254
|
|
|
* @throws RequestException |
|
255
|
|
|
*/ |
|
256
|
|
View Code Duplication |
public function getUserById(int $id): User |
|
|
|
|
|
|
257
|
|
|
{ |
|
258
|
|
|
$this->logger->debug('Trying to get user by id', ['id' => $id]); |
|
259
|
|
|
|
|
260
|
|
|
try { |
|
261
|
|
|
$userInfo = $this->getGetRequestData('/api/user/id/'.$id, [], true); |
|
262
|
|
|
} catch (RequestException $e) { |
|
263
|
|
|
if (Response::HTTP_NOT_FOUND === $e->getResponse()->getStatusCode()) { |
|
264
|
|
|
throw new UserNotFoundException('User not found', 0, $e, $id); |
|
265
|
|
|
} else { |
|
266
|
|
|
throw $e; |
|
267
|
|
|
} |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
return $this->getUserFromUserInfo($userInfo); |
|
|
|
|
|
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Finds and updates or create new user from API response data |
|
275
|
|
|
* |
|
276
|
|
|
* @param array $userInfo |
|
277
|
|
|
* |
|
278
|
|
|
* @return User |
|
279
|
|
|
* |
|
280
|
|
|
* @throws ApiException |
|
281
|
|
|
* @throws InvalidResponseException |
|
282
|
|
|
*/ |
|
283
|
|
|
public function getUserFromUserInfo(array $userInfo): User |
|
284
|
|
|
{ |
|
285
|
|
|
$this->logger->debug('Trying to create user from array', ['array' => $userInfo]); |
|
286
|
|
|
|
|
287
|
|
|
// @todo Refactor to UserFactory->createFromArray() |
|
288
|
|
|
if (array_key_exists('id', $userInfo) && array_key_exists('login', $userInfo) && array_key_exists('name', $userInfo) && is_numeric($userInfo['id'])) { |
|
289
|
|
|
/** @var User $user */ |
|
290
|
|
View Code Duplication |
if (null === ($user = $this->userRepository->find($userInfo['id']))) { |
|
|
|
|
|
|
291
|
|
|
// Creating new user |
|
292
|
|
|
$user = new User($userInfo['id']); |
|
293
|
|
|
$this->em->persist($user); |
|
294
|
|
|
} |
|
295
|
|
|
|
|
296
|
|
|
// Updating data |
|
297
|
|
|
$user |
|
298
|
|
|
->setLogin($userInfo['login']) |
|
299
|
|
|
->setName($userInfo['name']) |
|
300
|
|
|
; |
|
301
|
|
|
|
|
302
|
|
|
return $user; |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
throw new InvalidResponseException('Invalid API response. Mandatory fields do not exist.'); |
|
306
|
|
|
} |
|
307
|
|
|
|
|
308
|
|
|
/** |
|
309
|
|
|
* Get array of User objects from API response containing user list |
|
310
|
|
|
* |
|
311
|
|
|
* @todo refactor |
|
312
|
|
|
* |
|
313
|
|
|
* @param array $users |
|
314
|
|
|
* |
|
315
|
|
|
* @return User[] |
|
316
|
|
|
* |
|
317
|
|
|
* @throws ApiException |
|
318
|
|
|
* @throws InvalidResponseException |
|
319
|
|
|
*/ |
|
320
|
|
|
private function getUsersFromList(array $users = []): array |
|
321
|
|
|
{ |
|
322
|
|
|
$this->logger->debug('Trying to create multiple users from array', ['array' => $users]); |
|
323
|
|
|
|
|
324
|
|
|
/** @var User[] $resultUsers */ |
|
325
|
|
|
$resultUsers = []; |
|
326
|
|
|
|
|
327
|
|
|
foreach ($users as $userInfo) { |
|
328
|
|
|
if (array_key_exists('id', $userInfo) && array_key_exists('login', $userInfo) && array_key_exists('name', $userInfo) && is_numeric($userInfo['id'])) { |
|
329
|
|
|
|
|
330
|
|
|
// @todo Optimize with prehashed id's list |
|
331
|
|
View Code Duplication |
if (null === ($user = $this->userRepository->find($userInfo['id']))) { |
|
|
|
|
|
|
332
|
|
|
$user = new User((int) $userInfo['id']); |
|
333
|
|
|
$this->em->persist($user); |
|
334
|
|
|
} |
|
335
|
|
|
|
|
336
|
|
|
// Updating data |
|
337
|
|
|
$user |
|
338
|
|
|
->setLogin($userInfo['login']) |
|
339
|
|
|
->setName($userInfo['name']) |
|
340
|
|
|
; |
|
341
|
|
|
|
|
342
|
|
|
$resultUsers[] = $user; |
|
343
|
|
|
} else { |
|
344
|
|
|
throw new InvalidResponseException('Invalid API response. Mandatory fields do not exist.'); |
|
345
|
|
|
} |
|
346
|
|
|
} |
|
347
|
|
|
|
|
348
|
|
|
return $resultUsers; |
|
349
|
|
|
} |
|
350
|
|
|
} |
|
351
|
|
|
|
The
EntityManagermight become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManageris closed. Any other code which depends on the same instance of theEntityManagerduring this request will fail.On the other hand, if you instead inject the
ManagerRegistry, thegetManager()method guarantees that you will always get a usable manager instance.