GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 625674...909c28 )
by Christian
01:42
created

UserService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * (c) Christian Gripp <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Core23\LastFm\Service;
13
14
use Core23\LastFm\Client\ApiClientInterface;
15
use Core23\LastFm\Filter\Period;
16
use Core23\LastFm\Filter\RangeFilter;
17
use Core23\LastFm\Model\Album;
18
use Core23\LastFm\Model\Artist;
19
use Core23\LastFm\Model\Chart;
20
use Core23\LastFm\Model\Song;
21
use Core23\LastFm\Model\SongInfo;
22
use Core23\LastFm\Model\Tag;
23
use Core23\LastFm\Model\User;
24
use Core23\LastFm\Util\ApiHelper;
25
26
final class UserService implements UserServiceInterface
27
{
28
    /**
29
     * @var ApiClientInterface
30
     */
31
    private $client;
32
33
    /**
34
     * @param ApiClientInterface $client
35
     */
36
    public function __construct(ApiClientInterface $client)
37
    {
38
        $this->client = $client;
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function getArtistTracks(string $username, string $artist, ?RangeFilter $filter = null, int $page = 1): array
45
    {
46
        $query = null !== $filter ? $filter->getQuery('startTimestamp', 'endTimestamp') : [];
47
        $query = array_merge($query, [
48
            'user'           => $username,
49
            'artist'         => $artist,
50
            'page'           => $page,
51
        ]);
52
53
        $response = $this->client->unsignedCall('user.getArtistTracks', $query);
54
55
        if (!isset($response['artisttracks']['track'])) {
56
            return [];
57
        }
58
59
        return ApiHelper::mapList(
60
            static function ($data) {
61
                return Song::fromApi($data);
62
            },
63
            $response['artisttracks']['track']
64
        );
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function getFriends(string $username, bool $recenttracks = false, $limit = 50, int $page = 1): array
71
    {
72
        $response = $this->client->unsignedCall('user.getFriends', [
73
            'user'         => $username,
74
            'recenttracks' => (int) $recenttracks,
75
            'limit'        => $limit,
76
            'page'         => $page,
77
        ]);
78
79
        if (!isset($response['friends']['user'])) {
80
            return [];
81
        }
82
83
        return ApiHelper::mapList(
84
            static function ($data) {
85
                return User::fromApi($data);
86
            },
87
            $response['friends']['user']
88
        );
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function getInfo(string $username): ?User
95
    {
96
        $response =  $this->client->unsignedCall('user.getInfo', [
97
            'user' => $username,
98
        ]);
99
100
        if (!isset($response['user'])) {
101
            return null;
102
        }
103
104
        return User::fromApi($response['user']);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Core23\LastFm\Mo...Api($response['user']); (self) is incompatible with the return type declared by the interface Core23\LastFm\Service\Us...rviceInterface::getInfo of type Core23\LastFm\Model\User|null.

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 my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function getLovedTracks(string $username, int $limit = 50, int $page = 1): array
111
    {
112
        $response = $this->client->unsignedCall('user.getLovedTracks', [
113
            'user'  => $username,
114
            'limit' => $limit,
115
            'page'  => $page,
116
        ]);
117
118
        if (!isset($response['lovedtracks']['track'])) {
119
            return [];
120
        }
121
122
        return ApiHelper::mapList(
123
            static function ($data) {
124
                return Song::fromApi($data);
125
            },
126
            $response['lovedtracks']['track']
127
        );
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function getRecentTracks(string $username, ?RangeFilter $filter = null, $extended = false, $limit = 50, int $page = 1): array
134
    {
135
        $query = null !== $filter ? $filter->getQuery('from', 'to') : [];
136
        $query = array_merge($query, [
137
            'user'     => $username,
138
            'limit'    => $limit,
139
            'page'     => $page,
140
            'extended' => (int) $extended,
141
        ]);
142
143
        $response = $this->client->unsignedCall('user.getRecentTracks', $query);
144
145
        if (!isset($response['recenttracks']['track'])) {
146
            return [];
147
        }
148
149
        return ApiHelper::mapList(
150
            static function ($data) {
151
                return Song::fromApi($data);
152
            },
153
            $response['recenttracks']['track']
154
        );
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function getPersonalTagsForArtist(string $username, string $tag, int $limit = 50, int $page = 1): array
161
    {
162
        $response =  $this->client->unsignedCall('user.getPersonalTags', [
163
            'taggingtype' => 'artist',
164
            'user'        => $username,
165
            'tag'         => $tag,
166
            'limit'       => $limit,
167
            'page'        => $page,
168
        ]);
169
170
        if (!isset($response['taggings']['artists']['artist'])) {
171
            return [];
172
        }
173
174
        return ApiHelper::mapList(
175
            static function ($data) {
176
                return Artist::fromApi($data);
177
            },
178
            $response['taggings']['artists']['artist']
179
        );
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185
    public function getPersonalTagsForAlbum(string $username, string $tag, int $limit = 50, int $page = 1): array
186
    {
187
        $response = $this->client->unsignedCall('user.getPersonalTags', [
188
            'taggingtype' => 'album',
189
            'user'        => $username,
190
            'tag'         => $tag,
191
            'limit'       => $limit,
192
            'page'        => $page,
193
        ]);
194
195
        if (!isset($response['taggings']['albums']['album'])) {
196
            return [];
197
        }
198
199
        return ApiHelper::mapList(
200
            static function ($data) {
201
                return Album::fromApi($data);
202
            },
203
            $response['taggings']['albums']['album']
204
        );
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    public function getPersonalTagsForTracks(string $username, string $tag, int $limit = 50, int $page = 1): array
211
    {
212
        $response = $this->client->unsignedCall('user.getPersonalTags', [
213
            'taggingtype' => 'track',
214
            'user'        => $username,
215
            'tag'         => $tag,
216
            'limit'       => $limit,
217
            'page'        => $page,
218
        ]);
219
220
        if (!isset($response['taggings']['tracks']['track'])) {
221
            return [];
222
        }
223
224
        return ApiHelper::mapList(
225
            static function ($data) {
226
                return SongInfo::fromApi($data);
227
            },
228
            $response['taggings']['tracks']['track']
229
        );
230
    }
231
232
    /**
233
     * {@inheritdoc}
234
     */
235
    public function getTopAlbums(string $username, Period $period, int $limit = 50, int $page = 1): array
236
    {
237
        $response = $this->client->unsignedCall('user.getTopAlbums', [
238
            'user'   => $username,
239
            'period' => $period->getValue(),
240
            'limit'  => $limit,
241
            'page'   => $page,
242
        ]);
243
244
        if (!isset($response['topalbums']['album'])) {
245
            return [];
246
        }
247
248
        return ApiHelper::mapList(
249
            static function ($data) {
250
                return Album::fromApi($data);
251
            },
252
            $response['topalbums']['album']
253
        );
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259
    public function getTopArtists(string $username, Period $period, int $limit = 50, int $page = 1): array
260
    {
261
        $response = $this->client->unsignedCall('user.getTopArtists', [
262
            'user'   => $username,
263
            'period' => $period->getValue(),
264
            'limit'  => $limit,
265
            'page'   => $page,
266
        ]);
267
268
        if (!isset($response['topartists']['artist'])) {
269
            return [];
270
        }
271
272
        return ApiHelper::mapList(
273
            static function ($data) {
274
                return Artist::fromApi($data);
275
            },
276
            $response['topartists']['artist']
277
        );
278
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283
    public function getTopTags(string $username, int $limit = 50): array
284
    {
285
        $response = $this->client->unsignedCall('user.getTopTags', [
286
            'user'  => $username,
287
            'limit' => $limit,
288
        ]);
289
290
        if (!isset($response['toptags']['tag'])) {
291
            return [];
292
        }
293
294
        return ApiHelper::mapList(
295
            static function ($data) {
296
                return Tag::fromApi($data);
297
            },
298
            $response['toptags']['tag']
299
        );
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305
    public function getTopTracks(string $username, Period $period, int $limit = 50, int $page = 1): array
306
    {
307
        $response = $this->client->unsignedCall('user.getTopTracks', [
308
            'user'   => $username,
309
            'period' => $period->getValue(),
310
            'limit'  => $limit,
311
            'page'   => $page,
312
        ]);
313
314
        if (!isset($response['toptracks']['track'])) {
315
            return [];
316
        }
317
318
        return ApiHelper::mapList(
319
            static function ($data) {
320
                return SongInfo::fromApi($data);
321
            },
322
            $response['toptracks']['track']
323
        );
324
    }
325
326
    /**
327
     * {@inheritdoc}
328
     */
329
    public function getWeeklyAlbumChart(string $username, ?RangeFilter $filter = null): array
330
    {
331
        $query = null !== $filter ? $filter->getQuery('from', 'to') : [];
332
        $query = array_merge($query, [
333
            'user'     => $username,
334
        ]);
335
336
        $response = $this->client->unsignedCall('user.getWeeklyAlbumChart', $query);
337
338
        if (!isset($response['weeklyalbumchart']['album'])) {
339
            return [];
340
        }
341
342
        return ApiHelper::mapList(
343
            static function ($data) {
344
                return Album::fromApi($data);
345
            },
346
            $response['weeklyalbumchart']['album']
347
        );
348
    }
349
350
    /**
351
     * {@inheritdoc}
352
     */
353
    public function getWeeklyArtistChart(string $username, ?RangeFilter $filter = null): array
354
    {
355
        $query = null !== $filter ? $filter->getQuery('from', 'to') : [];
356
        $query = array_merge($query, [
357
            'user'     => $username,
358
        ]);
359
360
        $response = $this->client->unsignedCall('user.getWeeklyArtistChart', $query);
361
362
        if (!isset($response['weeklyartistchart']['artist'])) {
363
            return [];
364
        }
365
366
        return ApiHelper::mapList(
367
            static function ($data) {
368
                return Artist::fromApi($data);
369
            },
370
            $response['weeklyartistchart']['artist']
371
        );
372
    }
373
374
    /**
375
     * {@inheritdoc}
376
     */
377
    public function getWeeklyChartList(string $username): array
378
    {
379
        $response = $this->client->unsignedCall('user.getWeeklyChartList', [
380
            'user' => $username,
381
        ]);
382
383
        if (!isset($response['weeklychartlist']['chart'])) {
384
            return [];
385
        }
386
387
        return ApiHelper::mapList(
388
            static function ($data) {
389
                return Chart::fromApi($data);
390
            },
391
            $response['weeklychartlist']['chart']
392
        );
393
    }
394
395
    /**
396
     * {@inheritdoc}
397
     */
398
    public function getWeeklyTrackChart(string $username, ?RangeFilter $filter = null): array
399
    {
400
        $query = null !== $filter ? $filter->getQuery('from', 'to') : [];
401
        $query = array_merge($query, [
402
            'user'     => $username,
403
        ]);
404
405
        $response = $this->client->unsignedCall('user.getWeeklyTrackChart', $query);
406
407
        if (!isset($response['weeklytrackchart']['track'])) {
408
            return [];
409
        }
410
411
        return ApiHelper::mapList(
412
            static function ($data) {
413
                return SongInfo::fromApi($data);
414
            },
415
            $response['weeklytrackchart']['track']
416
        );
417
    }
418
}
419