This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Wonnova\SDK\Connection; |
||
3 | |||
4 | use Doctrine\Common\Cache\Cache; |
||
5 | use Doctrine\Common\Cache\FilesystemCache; |
||
6 | use Doctrine\Common\Collections\ArrayCollection; |
||
7 | use Doctrine\Common\Collections\Collection; |
||
8 | use JMS\Serializer\Serializer; |
||
9 | use Wonnova\SDK\Auth\CredentialsInterface; |
||
10 | use Wonnova\SDK\Auth\Token; |
||
11 | use Wonnova\SDK\Auth\TokenInterface; |
||
12 | use Wonnova\SDK\Common\Headers; |
||
13 | use Wonnova\SDK\Common\ResponseCodes; |
||
14 | use Wonnova\SDK\Exception\InvalidArgumentException; |
||
15 | use Wonnova\SDK\Exception\InvalidRequestException; |
||
16 | use Wonnova\SDK\Exception\NotFoundException; |
||
17 | use Wonnova\SDK\Exception\RuntimeException; |
||
18 | use Wonnova\SDK\Exception\UnauthorizedException; |
||
19 | use Wonnova\SDK\Exception\ServerException; |
||
20 | use Wonnova\SDK\Http\Route; |
||
21 | use Wonnova\SDK\Model\Achievement; |
||
22 | use Wonnova\SDK\Model\Action; |
||
23 | use Wonnova\SDK\Model\Badge; |
||
24 | use Wonnova\SDK\Model\Item; |
||
25 | use Wonnova\SDK\Model\Level; |
||
26 | use Wonnova\SDK\Model\Notification; |
||
27 | use Wonnova\SDK\Model\Quest; |
||
28 | use Wonnova\SDK\Model\QuestStep; |
||
29 | use Wonnova\SDK\Model\Team; |
||
30 | use Wonnova\SDK\Model\Update; |
||
31 | use Wonnova\SDK\Model\User; |
||
32 | use GuzzleHttp\Client as GuzzleClient; |
||
33 | use Wonnova\SDK\Serializer\SerializerFactory; |
||
34 | |||
35 | /** |
||
36 | * Class Client |
||
37 | * @author Wonnova |
||
38 | * @link http://www.wonnova.com |
||
39 | */ |
||
40 | class Client extends GuzzleClient implements ClientInterface |
||
41 | { |
||
42 | const USER_AGENT = 'wonnova-php-sdk'; |
||
43 | const TOKEN_KEY = 'wonnova_auth_token'; |
||
44 | |||
45 | /** |
||
46 | * @var CredentialsInterface |
||
47 | */ |
||
48 | protected $credentials; |
||
49 | /** |
||
50 | * @var string |
||
51 | */ |
||
52 | protected $language; |
||
53 | /** |
||
54 | * @var Cache |
||
55 | */ |
||
56 | protected $cache; |
||
57 | /** |
||
58 | * @var Serializer |
||
59 | */ |
||
60 | protected $serializer; |
||
61 | /** |
||
62 | * @var TokenInterface |
||
63 | */ |
||
64 | protected $token; |
||
65 | /** |
||
66 | * @var string |
||
67 | */ |
||
68 | protected $tokenCacheKey; |
||
69 | |||
70 | /** |
||
71 | * @param CredentialsInterface $credentials |
||
72 | * @param string $language |
||
73 | * @param Cache $cache |
||
74 | * @param null $baseUrl |
||
75 | */ |
||
76 | 43 | public function __construct( |
|
77 | CredentialsInterface $credentials, |
||
78 | 1 | $language = 'es', |
|
79 | Cache $cache = null, |
||
80 | $baseUrl = null |
||
81 | ) { |
||
82 | 43 | parent::__construct([ |
|
83 | 43 | 'base_url' => $baseUrl ?: self::HOST, |
|
84 | 'defaults' => [ |
||
85 | 'headers' => [ |
||
86 | 'User-Agent' => self::USER_AGENT |
||
87 | 43 | ], |
|
88 | 1 | 'exceptions' => false |
|
89 | 43 | ] |
|
90 | 43 | ]); |
|
91 | |||
92 | 43 | $this->serializer = SerializerFactory::create(); |
|
93 | 43 | $this->credentials = $credentials; |
|
94 | 43 | $this->language = $language; |
|
95 | 43 | $this->cache = $cache ?: new FilesystemCache(sys_get_temp_dir()); |
|
96 | |||
97 | // Initialize the token if it exists in cache |
||
98 | 43 | $this->tokenCacheKey = sprintf('%s_%s', self::TOKEN_KEY, $credentials->getKey()); |
|
99 | 43 | if ($this->cache->contains($this->tokenCacheKey)) { |
|
100 | 1 | $this->token = new Token(); |
|
101 | 1 | $this->token->setAccessToken($this->cache->fetch($this->tokenCacheKey)); |
|
102 | 1 | } |
|
103 | |||
104 | 43 | } |
|
105 | |||
106 | /** |
||
107 | * Performs a connection to defined endpoint with defined options |
||
108 | * |
||
109 | * @param string $method |
||
110 | * @param Route|string $route |
||
111 | * @param array $options |
||
112 | * @return \GuzzleHttp\Message\ResponseInterface |
||
113 | * @throws \Wonnova\SDK\Exception\ServerException |
||
114 | * @throws \Wonnova\SDK\Exception\InvalidRequestException |
||
115 | * @throws \Wonnova\SDK\Exception\NotFoundException |
||
116 | * @throws \Wonnova\SDK\Exception\RuntimeException |
||
117 | */ |
||
118 | 42 | public function connect($method, $route, array $options = []) |
|
119 | { |
||
120 | // Perform authentication if token has not been set yet |
||
121 | 42 | if (! isset($this->token)) { |
|
122 | 41 | $this->authenticate(); |
|
123 | 41 | } |
|
124 | |||
125 | // Add the language and token headers |
||
126 | 42 | $options = $this->processOptionsWithDefaults($options); |
|
127 | 42 | $response = $this->send($this->createRequest($method, $route, $options)); |
|
0 ignored issues
–
show
|
|||
128 | 42 | $code = $response->getStatusCode(); |
|
129 | 42 | if (intval($code) === 200) { |
|
130 | 37 | return $response; |
|
131 | } |
||
132 | |||
133 | // In case of error throw proper exception |
||
134 | switch ($code) { |
||
135 | 6 | case 401: // Token not valid. Reconect |
|
136 | 2 | $message = json_decode($response->getBody()->getContents(), true); |
|
137 | |||
138 | // If the server returned an INVALID_TOKEN response, reconnect |
||
139 | 2 | if (isset($message['error']) && $message['error'] === ResponseCodes::INVALID_TOKEN) { |
|
140 | 1 | $this->resetToken(); |
|
141 | 1 | return $this->connect($method, $route, $options); |
|
142 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
143 | } |
||
144 | |||
145 | 1 | throw new UnauthorizedException( |
|
146 | 1 | sprintf( |
|
147 | 1 | 'Unauthorized request to "%s" with method "%s" and response message "%s"', |
|
148 | 1 | $route, |
|
149 | 1 | $method, |
|
150 | 1 | isset($message['message']) ? $message['message'] : '' |
|
151 | 1 | ), |
|
152 | $code |
||
153 | 1 | ); |
|
154 | 4 | case 400: |
|
155 | 1 | $message = json_decode($response->getBody()->getContents(), true); |
|
156 | 1 | throw new InvalidRequestException( |
|
157 | 1 | sprintf( |
|
158 | 1 | 'Invalid request to "%s" with method "%s" and response message "%s"', |
|
159 | 1 | $route, |
|
160 | 1 | $method, |
|
161 | 2 | isset($message['message']) ? $message['message'] : '' |
|
162 | 1 | ), |
|
163 | $code |
||
164 | 1 | ); |
|
165 | 3 | case 404: |
|
166 | 1 | throw new NotFoundException( |
|
167 | 1 | sprintf('Route "%s" with method "%s" was not found', $route, $method), |
|
168 | $code |
||
169 | 1 | ); |
|
170 | 2 | case 500: |
|
171 | 1 | throw new ServerException( |
|
172 | 1 | sprintf('There was a server error processing a request to "%s" with method "%s"', $route, $method), |
|
173 | $code |
||
174 | 1 | ); |
|
175 | 1 | default: |
|
176 | 1 | throw new RuntimeException( |
|
177 | 1 | sprintf( |
|
178 | 1 | 'Unexpected error occurred whith request to route "%s" with method "%s"', |
|
179 | 1 | $route, |
|
180 | $method |
||
181 | 1 | ), |
|
182 | $code |
||
183 | 1 | ); |
|
184 | 1 | } |
|
185 | } |
||
186 | |||
187 | /** |
||
188 | * Resets the token so that it can be reinitialized. |
||
189 | * This has to be used when current token has expired or is invalid |
||
190 | */ |
||
191 | 1 | private function resetToken() |
|
192 | { |
||
193 | 1 | $this->token = null; |
|
194 | 1 | $this->cache->delete($this->tokenCacheKey); |
|
195 | 1 | } |
|
196 | |||
197 | /** |
||
198 | * Performs authentication caching the auth token |
||
199 | */ |
||
200 | 41 | private function authenticate() |
|
201 | { |
||
202 | 41 | $response = $this->send($this->createRequest('POST', self::AUTH_ROUTE, [ |
|
203 | 41 | 'json' => $this->credentials->toArray() |
|
204 | 41 | ])); |
|
205 | 41 | $this->token = $this->serializer->deserialize( |
|
206 | 41 | $response->getBody()->getContents(), |
|
207 | 41 | 'Wonnova\SDK\Auth\Token', |
|
208 | 'json' |
||
209 | 41 | ); |
|
210 | 41 | $this->cache->save($this->tokenCacheKey, $this->token->getAccessToken()); |
|
211 | 41 | } |
|
212 | |||
213 | /** |
||
214 | * @param array $options |
||
215 | * @return array |
||
216 | */ |
||
217 | 42 | protected function processOptionsWithDefaults(array $options) |
|
218 | { |
||
219 | 42 | $options['headers'] = isset($options['headers']) ? $options['headers'] : []; |
|
220 | |||
221 | 42 | $options['headers'][Headers::LANGUAGE_HEADER] = $this->language; |
|
222 | 42 | $options['headers'][Headers::TOKEN_HEADER] = $this->token->getAccessToken(); |
|
223 | |||
224 | 42 | return $options; |
|
225 | } |
||
226 | |||
227 | /** |
||
228 | * Fetches a route and maps a resource list of models under provided key |
||
229 | * |
||
230 | * @param Route|string $route |
||
231 | * @param $resourceKey |
||
232 | * @param $resourceClass |
||
233 | * @return ArrayCollection |
||
234 | */ |
||
235 | 11 | protected function getResourceCollection($route, $resourceKey, $resourceClass) |
|
236 | { |
||
237 | 11 | $response = $this->connect('GET', $route); |
|
238 | 11 | $contents = $this->serializer->deserialize($response->getBody()->getContents(), 'array', 'json'); |
|
239 | 11 | return new ArrayCollection($this->serializer->deserialize( |
|
240 | 11 | $contents[$resourceKey], |
|
241 | 11 | sprintf('array<%s>', $resourceClass), |
|
242 | 'array' |
||
243 | 11 | )); |
|
244 | } |
||
245 | |||
246 | /** |
||
247 | * Returns users list |
||
248 | * |
||
249 | * @return Collection|User[] |
||
250 | */ |
||
251 | 7 | View Code Duplication | public function getUsers() |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
252 | { |
||
253 | 7 | $response = $this->connect('GET', self::USERS_ROUTE); |
|
254 | 2 | $contents = $response->getBody()->getContents(); |
|
255 | 2 | return new ArrayCollection($this->serializer->deserialize( |
|
256 | 2 | $contents, |
|
257 | 2 | 'array<Wonnova\SDK\Model\User>', |
|
258 | 'json' |
||
259 | 2 | )); |
|
260 | } |
||
261 | |||
262 | /** |
||
263 | * Returns information about certain user |
||
264 | * |
||
265 | * @param $userId |
||
266 | * @return User |
||
267 | */ |
||
268 | 3 | View Code Duplication | public function getUser($userId) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
269 | { |
||
270 | 3 | $response = $this->connect('GET', new Route(self::USERS_ROUTE, [], [ |
|
271 | 'userId' => $userId |
||
272 | 3 | ])); |
|
273 | 3 | $contents = $response->getBody()->getContents(); |
|
274 | 3 | return $this->serializer->deserialize($contents, 'Wonnova\SDK\Model\User', 'json'); |
|
0 ignored issues
–
show
The return type of
return $this->serializer...\Model\\User', 'json'); (object|array|integer|double|string|boolean ) is incompatible with the return type declared by the interface Wonnova\SDK\Connection\A...rsAPIInterface::getUser of type Wonnova\SDK\Model\User .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Creates provided user |
||
279 | * |
||
280 | * @param User $user |
||
281 | */ |
||
282 | 1 | View Code Duplication | public function createUser(User $user) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
283 | { |
||
284 | 1 | $response = $this->connect('POST', self::USERS_ROUTE, [ |
|
285 | 'json' => $user |
||
286 | 1 | ]); |
|
287 | 1 | $contents = $response->getBody()->getContents(); |
|
288 | 1 | $userData = $this->serializer->deserialize($contents, 'array', 'json'); |
|
289 | // The server will return the user ID. Set it to the model |
||
290 | 1 | $user->setUserId($userData['userId']); |
|
291 | 1 | } |
|
292 | |||
293 | /** |
||
294 | * Updates provided user |
||
295 | * |
||
296 | * @param User $user |
||
297 | */ |
||
298 | 2 | public function updateUser(User $user) |
|
299 | { |
||
300 | 2 | $userId = $user->getUserId(); |
|
301 | 2 | if (empty($userId)) { |
|
302 | 1 | throw new InvalidArgumentException('Provided user has an empty userId.'); |
|
303 | } |
||
304 | |||
305 | 1 | $response = $this->connect('PUT', new Route(self::UPDATE_USER_ROUTE, [ |
|
306 | 'userId' => $userId |
||
307 | 1 | ]), [ |
|
308 | 'json' => $user |
||
309 | 1 | ]); |
|
310 | 1 | $contents = $response->getBody()->getContents(); |
|
311 | // The server will return the user data. Refresh the model |
||
312 | 1 | $user->fromArray($this->serializer->deserialize($contents, 'array', 'json')); |
|
313 | 1 | } |
|
314 | |||
315 | /** |
||
316 | * |
||
317 | * |
||
318 | * @param User|string $user A User model or userId |
||
319 | * @return Collection|Notification[] |
||
320 | */ |
||
321 | 1 | View Code Duplication | public function getUserNotifications($user) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
322 | { |
||
323 | 1 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
324 | 1 | return $this->getResourceCollection(new Route(self::USER_NOTIFICATIONS_ROUTE, [ |
|
325 | 'userId' => $userId |
||
326 | 1 | ]), 'notifications', 'Wonnova\SDK\Model\Notification'); |
|
327 | } |
||
328 | |||
329 | /** |
||
330 | * Returns the list of badges that certain user has won |
||
331 | * |
||
332 | * @param User|string $user A User model or userId |
||
333 | * @return Collection|Badge[] |
||
334 | */ |
||
335 | 1 | View Code Duplication | public function getUserBadges($user) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
336 | { |
||
337 | 1 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
338 | 1 | return $this->getResourceCollection(new Route(self::USER_BADGES_ROUTE, [ |
|
339 | 'userId' => $userId |
||
340 | 1 | ]), 'badges', 'Wonnova\SDK\Model\Badge'); |
|
341 | } |
||
342 | |||
343 | /** |
||
344 | * Returns the number of achievements of each type for certain user |
||
345 | * |
||
346 | * @param User|string $user A User model or userId |
||
347 | * @param array|string $types List of types in a comma-separated string or array. |
||
348 | * All the types will be returned by default |
||
349 | * @return Collection|Achievement[] |
||
350 | */ |
||
351 | 1 | public function getUserAchievements($user, $types = []) |
|
352 | { |
||
353 | 1 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
354 | 1 | $types = empty($types) ? Achievement::getAllTypesList() : $types; |
|
355 | 1 | $types = is_array($types) ? implode(',', $types) : $types; |
|
356 | |||
357 | 1 | return $this->getResourceCollection(new Route( |
|
358 | 1 | self::USER_ACHIEVEMENTS_ROUTE, |
|
359 | 1 | ['userId' => $userId], |
|
360 | 1 | ['types' => $types] |
|
361 | 1 | ), 'achievements', 'Wonnova\SDK\Model\Achievement'); |
|
362 | } |
||
363 | |||
364 | /** |
||
365 | * Returns the list of steps in a quest telling if certain user has already completed them |
||
366 | * |
||
367 | * @param User|string $user A User model or userId |
||
368 | * @param string $questCode |
||
369 | * @return Collection|QuestStep[] |
||
370 | */ |
||
371 | 1 | View Code Duplication | public function getUserProgressInQuest($user, $questCode) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
372 | { |
||
373 | 1 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
374 | 1 | return $this->getResourceCollection(new Route(self::USER_QUEST_PROGRESS_ROUTE, [ |
|
375 | 1 | 'userId' => $userId, |
|
376 | 'questCode' => $questCode |
||
377 | 1 | ]), 'questSteps', 'Wonnova\SDK\Model\QuestStep'); |
|
378 | } |
||
379 | |||
380 | /** |
||
381 | * Returns the list of created quests |
||
382 | * |
||
383 | * @return Collection|Quest[] |
||
384 | */ |
||
385 | 1 | public function getQuests() |
|
386 | { |
||
387 | 1 | return $this->getResourceCollection(self::QUESTS_ROUTE, 'quests', 'Wonnova\SDK\Model\Quest'); |
|
388 | } |
||
389 | |||
390 | /** |
||
391 | * Returns all the quests with which a user is involved with, including the list of their steps |
||
392 | * |
||
393 | * @param User|string $user A User model or userId |
||
394 | * @return Collection|Quest[] |
||
395 | */ |
||
396 | 1 | View Code Duplication | public function getUserStatusInQuests($user) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
397 | { |
||
398 | 1 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
399 | 1 | return $this->getResourceCollection(new Route(self::USER_QUESTS_STATUS_ROUTE, [ |
|
400 | 'userId' => $userId |
||
401 | 1 | ]), 'quests', 'Wonnova\SDK\Model\Quest'); |
|
402 | } |
||
403 | |||
404 | /** |
||
405 | * @return Collection|Level[] |
||
406 | */ |
||
407 | 1 | public function getLevels() |
|
408 | { |
||
409 | 1 | return $this->getResourceCollection(self::LEVELS_ROUTE, 'levels', 'Wonnova\SDK\Model\Level'); |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * Returns the level of a user in certain scenario |
||
414 | * |
||
415 | * @param User|string $user A User model or userId |
||
416 | * @param string|null $scenarioCode |
||
417 | * @return Level |
||
418 | */ |
||
419 | 2 | public function getUserLevelInScenario($user, $scenarioCode = null) |
|
420 | { |
||
421 | 2 | $userId = $user instanceof User ? $user->getUserId() : $user; |
|
422 | 2 | $route = self::USER_LEVEL_ROUTE; |
|
423 | $options = [ |
||
424 | 2 | 'userId' => $userId, |
|
425 | 2 | ]; |
|
426 | |||
427 | 2 | if (! empty($scenarioCode)) { |
|
428 | 1 | $route = self::USER_LEVEL_WITH_SCENARIO_ROUTE; |
|
429 | 1 | $options['scenarioCode'] = $scenarioCode; |
|
430 | 1 | } |
|
431 | |||
432 | 2 | $response = $this->connect('GET', new Route($route, $options)); |
|
433 | |||
434 | 2 | $contents = $response->getBody()->getContents(); |
|
435 | 2 | $contents = $this->serializer->deserialize($contents, 'array', 'json'); |
|
436 | 2 | return $this->serializer->deserialize($contents['level'], 'Wonnova\SDK\Model\Level', 'array'); |
|
0 ignored issues
–
show
The return type of
return $this->serializer...odel\\Level', 'array'); (object|array|integer|double|string|boolean ) is incompatible with the return type declared by the interface Wonnova\SDK\Connection\A...:getUserLevelInScenario of type Wonnova\SDK\Model\Level .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
437 | } |
||
438 | |||
439 | /** |
||
440 | * Returns the list of top teams ordered by total score of their members |
||
441 | * If a user is provided, the list will include the team of that user, even if it is not in the top list |
||
442 | * |
||
443 | * @param int|null $maxCount Maximum number of results |
||
444 | * @param User|string|null $user A User model or userId |
||
445 | * @return Collection|Team[] |
||
446 | */ |
||
447 | 2 | public function getTeamsLeaderboard($maxCount = null, $user = null) |
|
448 | { |
||
449 | $queryParams = [ |
||
450 | 2 | 'userId' => null, |
|
451 | 'maxCount' => null |
||
452 | 2 | ]; |
|
453 | 2 | if (is_int($maxCount)) { |
|
454 | 1 | $queryParams['maxCount'] = $maxCount; |
|
455 | 1 | } |
|
456 | 2 | if (isset($user)) { |
|
457 | 1 | $queryParams['userId'] = $user instanceof User ? $user->getUserId() : $user; |
|
458 | 1 | } |
|
459 | |||
460 | 2 | return $this->getResourceCollection( |
|
461 | 2 | new Route(self::TEAMS_LEADERBOARD_ROUTE, [], $queryParams), |
|
462 | 2 | 'scores', |
|
463 | 'Wonnova\SDK\Model\Team' |
||
464 | 2 | ); |
|
465 | } |
||
466 | |||
467 | /** |
||
468 | * Returns the top rated items |
||
469 | * |
||
470 | * @param int $maxCount |
||
471 | * @return Collection|Item[] |
||
472 | */ |
||
473 | 1 | public function getItemsLeaderboard($maxCount = 6) |
|
474 | { |
||
475 | 1 | return $this->getResourceCollection(new Route(self::ITEMS_LEADERBOARD_ROUTE, [], [ |
|
476 | 'minCount' => $maxCount |
||
477 | 1 | ]), 'leaderboard', 'Wonnova\SDK\Model\Item'); |
|
478 | } |
||
479 | |||
480 | /** |
||
481 | * Rates an item increasing its score and setting the rate from certain user. |
||
482 | * |
||
483 | * @param User|string $user a User model or userId |
||
484 | * @param Item|string $item an Item model or itemId |
||
485 | * @param int $score |
||
486 | * @return Item |
||
487 | */ |
||
488 | 1 | public function rateItem($user, $item, $score = 0) |
|
489 | { |
||
490 | $data = [ |
||
491 | 1 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
492 | 1 | 'points' => $score, |
|
493 | 1 | 'item' => $item instanceof Item ? $item->toArray() : [ |
|
494 | 'id' => $item |
||
495 | 1 | ] |
|
496 | 1 | ]; |
|
497 | 1 | $response = $this->connect('POST', self::ITEM_RATE_ROUTE, [ |
|
498 | 'json' => $data |
||
499 | 1 | ]); |
|
500 | 1 | $contents = $response->getBody()->getContents(); |
|
501 | 1 | $itemData = $this->serializer->deserialize($contents, 'array', 'json'); |
|
502 | |||
503 | // If an Item wasn't provided, create a new Item instance |
||
504 | 1 | if (! $item instanceof Item) { |
|
505 | 1 | $item = new Item(); |
|
506 | 1 | } |
|
507 | |||
508 | // Refresh the Item's data and return it |
||
509 | 1 | $item->fromArray($itemData['item']); |
|
510 | 1 | return $item; |
|
511 | } |
||
512 | |||
513 | /** |
||
514 | * Rates an item increasing its score and setting the rate from certain user. |
||
515 | * |
||
516 | * @param User|string $user a User model or userId |
||
517 | * @param array $items an array of Item models |
||
518 | * @return ArrayCollection |
||
519 | */ |
||
520 | 1 | public function rateSeveralItems($user, array $items) |
|
521 | { |
||
522 | $data = [ |
||
523 | 1 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
524 | 1 | 'itemsList' => [], |
|
525 | 1 | ]; |
|
526 | |||
527 | 1 | foreach ($items as $item) { |
|
528 | 1 | if ($item instanceof Item) { |
|
529 | 1 | $data['itemsList'][] = $item->toArray(); |
|
530 | 1 | } |
|
531 | 1 | } |
|
532 | |||
533 | 1 | $response = $this->connect('POST', self::ITEM_RATE_LIST_ROUTE, [ |
|
534 | 'json' => $data |
||
535 | 1 | ]); |
|
536 | 1 | $contents = $this->serializer->deserialize($response->getBody()->getContents(), 'array', 'json'); |
|
537 | |||
538 | 1 | return new ArrayCollection($this->serializer->deserialize( |
|
539 | 1 | $contents['items'], |
|
540 | 1 | 'array<Wonnova\SDK\Model\Item>', |
|
541 | 'array' |
||
542 | 1 | )); |
|
543 | } |
||
544 | |||
545 | /** |
||
546 | * Deletes certain item |
||
547 | * |
||
548 | * @param Item|string $item an Item model or itemId |
||
549 | * @return void |
||
550 | */ |
||
551 | 1 | View Code Duplication | public function deleteItem($item) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
552 | { |
||
553 | 1 | $itemId = $item instanceof Item ? $item->getItemId() : $item; |
|
554 | 1 | $this->connect('DELETE', new Route(self::ITEM_ROUTE, [ |
|
555 | 'itemId' => $itemId |
||
556 | 1 | ])); |
|
557 | 1 | } |
|
558 | |||
559 | /** |
||
560 | * Resets an item's score to zero |
||
561 | * |
||
562 | * @param Item|string $item an Item model or itemId |
||
563 | * @return void |
||
564 | */ |
||
565 | 1 | View Code Duplication | public function resetItemScore($item) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
566 | { |
||
567 | 1 | $itemId = $item instanceof Item ? $item->getItemId() : $item; |
|
568 | 1 | $this->connect('PUT', new Route(self::ITEM_RESET_SCORE_ROUTE, [ |
|
569 | 'itemId' => $itemId |
||
570 | 1 | ])); |
|
571 | 1 | } |
|
572 | |||
573 | /** |
||
574 | * Returns a partial model of certain user defined by its userId |
||
575 | * By calling this method, only the properties username, fullName, avatar and score of the User will be popullated, |
||
576 | * as well as the provided userId |
||
577 | * |
||
578 | * @param $userId |
||
579 | * @return User |
||
580 | */ |
||
581 | 1 | public function getUserData($userId) |
|
582 | { |
||
583 | 1 | $response = $this->connect('GET', new Route(self::USER_ABOUT_ROUTE, [ |
|
584 | 'userId' => $userId |
||
585 | 1 | ])); |
|
586 | 1 | $contents = $response->getBody()->getContents(); |
|
587 | 1 | $responseData = $this->serializer->deserialize($contents, 'array', 'json'); |
|
588 | |||
589 | // Create the User model to be returned and populate it |
||
590 | 1 | $user = new User(); |
|
591 | 1 | $user->fromArray($responseData['userData']); |
|
592 | 1 | $user->setUserId($userId); |
|
593 | 1 | return $user; |
|
594 | } |
||
595 | |||
596 | /** |
||
597 | * Performs an action notification from certain user |
||
598 | * |
||
599 | * @param User|string $user A User model or userId |
||
600 | * @param string $actionCode |
||
601 | * @param Item|string $item An Item model or itemId |
||
602 | * @param array $categories |
||
603 | * @return void |
||
604 | */ |
||
605 | 3 | public function notifyAction($user, $actionCode, $item = null, array $categories = []) |
|
606 | { |
||
607 | // Prepare request body |
||
608 | $requestData = [ |
||
609 | 3 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
610 | 'actionCode' => $actionCode |
||
611 | 3 | ]; |
|
612 | 3 | View Code Duplication | if (isset($item)) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
613 | 1 | $requestData['item'] = $item instanceof Item ? $item->toArray() : [ |
|
614 | 'id' => $item |
||
615 | 1 | ]; |
|
616 | 1 | } |
|
617 | 3 | if (! empty($categories)) { |
|
618 | 1 | $requestData['categories'] = $categories; |
|
619 | 1 | } |
|
620 | |||
621 | // Perform request |
||
622 | 3 | $this->connect('POST', self::ACTION_NOTIFICATION_ROUTE, [ |
|
623 | 'json' => $requestData |
||
624 | 3 | ]); |
|
625 | 3 | } |
|
626 | |||
627 | /** |
||
628 | * Performs an action notification from certain user |
||
629 | * |
||
630 | * @param User|string $user A User model or userId |
||
631 | * @param array $actions array of Action objects or strings |
||
632 | * @return void |
||
633 | */ |
||
634 | 4 | public function notifySeveralActions($user, array $actions) |
|
635 | { |
||
636 | // Prepare request body |
||
637 | $requestData = [ |
||
638 | 4 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
639 | 4 | 'actions' => [], |
|
640 | 4 | ]; |
|
641 | |||
642 | 4 | foreach ($actions as $action) { |
|
643 | |||
644 | 4 | if (is_string($action)) { |
|
645 | 1 | $actionCode = $action; |
|
646 | 1 | $action = new Action(); |
|
647 | 1 | $action->setActionCode($actionCode); |
|
648 | 1 | } |
|
649 | |||
650 | 4 | if ($action instanceof Action) { |
|
651 | 4 | $requestData['actions'][] = $action->toArray(); |
|
652 | 4 | } |
|
653 | 4 | } |
|
654 | |||
655 | // Perform request |
||
656 | 4 | $this->connect('POST', self::ACTION_NOTIFY_SEVERAL_ROUTE, [ |
|
657 | 'json' => $requestData |
||
658 | 4 | ]); |
|
659 | 4 | } |
|
660 | |||
661 | /** |
||
662 | * Performs an interaction notification between two users |
||
663 | * |
||
664 | * @param User|string $user A User model or userId |
||
665 | * @param User|string $targetUser A User model or userId |
||
666 | * @param string $interactionCode |
||
667 | * @param Item|null $item An Item model or itemId |
||
668 | * @param array $categories |
||
669 | * @return void |
||
670 | */ |
||
671 | 3 | public function notifyInteraction($user, $targetUser, $interactionCode, $item = null, array $categories = []) |
|
672 | { |
||
673 | // Prepare request body |
||
674 | $requestData = [ |
||
675 | 3 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
676 | 3 | 'targetUserId' => $targetUser instanceof User ? $targetUser->getUserId() : $targetUser, |
|
677 | 'interactionCode' => $interactionCode |
||
678 | 3 | ]; |
|
679 | 3 | View Code Duplication | if (isset($item)) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
680 | 1 | $requestData['item'] = $item instanceof Item ? $item->toArray() : [ |
|
681 | 'id' => $item |
||
682 | 1 | ]; |
|
683 | 1 | } |
|
684 | 3 | if (! empty($categories)) { |
|
685 | 1 | $requestData['categories'] = $categories; |
|
686 | 1 | } |
|
687 | |||
688 | // Perform request |
||
689 | 3 | $this->connect('POST', self::INTERACTION_NOTIFICATION_ROUTE, [ |
|
690 | 'json' => $requestData |
||
691 | 3 | ]); |
|
692 | 3 | } |
|
693 | |||
694 | /** |
||
695 | * Returns the number of times a user has performed certain action |
||
696 | * |
||
697 | * @param User|string $user A User model or userId |
||
698 | * @param string $actionCode |
||
699 | * @return int |
||
700 | */ |
||
701 | 1 | View Code Duplication | public function getUserActionOccurrences($user, $actionCode) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
702 | { |
||
703 | 1 | $response = $this->connect('GET', new Route(self::USER_ACTION_OCCURRENCES_ROUTE, [ |
|
704 | 1 | 'userId' => $user instanceof User ? $user->getUserId() : $user, |
|
705 | 'actionCode' => $actionCode |
||
706 | 1 | ])); |
|
707 | 1 | $contents = $response->getBody()->getContents(); |
|
708 | 1 | return $this->serializer->deserialize($contents, 'array', 'json')['occurrences']; |
|
709 | } |
||
710 | |||
711 | /** |
||
712 | * Returns information about the status of an interactionaccording to its limits |
||
713 | * |
||
714 | * @param User|string $user A User model or userId |
||
715 | * @param User|string $targetUser A User model or userId |
||
716 | * @param string $interactionCode |
||
717 | * @param Item|string $item An Item model or itemId |
||
718 | * @return array |
||
719 | */ |
||
720 | 1 | public function getInteractionStatus($user, $targetUser, $interactionCode, $item) |
|
721 | { |
||
722 | // Prepare request body |
||
723 | $requestData = [ |
||
724 | 1 | 'user' => $user instanceof User ? $user->getUserId() : $user, |
|
725 | 'targetUser' => [ |
||
726 | 1 | 'id' => $targetUser instanceof User ? $targetUser->getUserId() : $targetUser |
|
727 | 1 | ], |
|
728 | 1 | 'interactionCode' => $interactionCode, |
|
729 | 1 | 'item' => $item instanceof Item ? $item->toArray() : [ |
|
730 | 'id' => $item |
||
731 | 1 | ] |
|
732 | 1 | ]; |
|
733 | |||
734 | 1 | $response = $this->connect('POST', self::INTERACTION_STATUS_ROUTE, [ |
|
735 | 'json' => $requestData |
||
736 | 1 | ]); |
|
737 | 1 | $contents = $response->getBody()->getContents(); |
|
738 | 1 | $responseData = $this->serializer->deserialize($contents, 'array', 'json'); |
|
739 | |||
740 | // Process response properties |
||
741 | 1 | unset($responseData['status']); |
|
742 | 1 | if (! isset($responseData['score'])) { |
|
743 | 1 | $responseData['score'] = 0; |
|
744 | 1 | } |
|
745 | |||
746 | 1 | return $responseData; |
|
0 ignored issues
–
show
The return type of
return $responseData; (object|array|integer|double|string|boolean ) is incompatible with the return type declared by the interface Wonnova\SDK\Connection\A...e::getInteractionStatus of type array .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
747 | } |
||
748 | |||
749 | /** |
||
750 | * Returns the list of most recent updates for certain user |
||
751 | * |
||
752 | * @param User|string $user A User model or userId |
||
753 | * @param int $maxCount |
||
754 | * @return Collection|Update[] |
||
755 | */ |
||
756 | 1 | public function getUserLastUpdates($user, $maxCount = null) |
|
757 | { |
||
758 | 1 | $queryParams = []; |
|
759 | 1 | if (is_int($maxCount)) { |
|
760 | 1 | $queryParams['minCount'] = $maxCount; |
|
761 | 1 | } |
|
762 | 1 | $route = new Route(self::USER_LAST_UPDATES, [ |
|
763 | 1 | 'userId' => $user instanceof User ? $user->getUserId() : $user |
|
764 | 1 | ], $queryParams); |
|
765 | 1 | return $this->getResourceCollection($route, 'lastUpdates', 'Wonnova\SDK\Model\Update'); |
|
766 | } |
||
767 | } |
||
768 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.