Spotify   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 144
Duplicated Lines 6.25 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 24
lcom 1
cbo 6
dl 9
loc 144
rs 10
c 1
b 0
f 0
ccs 0
cts 106
cp 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A connect() 0 8 1
A assertValidAccessToken() 0 10 3
A getSearchQuery() 0 10 1
A getTrackId() 0 20 4
A fetchUserPlaylists() 0 6 2
A getPlaylistId() 0 12 3
A getUserId() 0 12 2
A createPlaylist() 0 12 1
A assertValidPlaylistName() 9 9 3
B replacePlaylistTracks() 0 24 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace HansOtt\Lastify\Services;
4
5
use HansOtt\Lastify\SyncProgress;
6
use HansOtt\Lastify\TrackInfo;
7
use HansOtt\Lastify\SyncResult;
8
use InvalidArgumentException;
9
use SpotifyWebAPI\SpotifyWebAPI;
10
use HansOtt\Lastify\TrackCollection;
11
use HansOtt\Lastify\TrackInfo\Artist;
12
use HansOtt\Lastify\CanManagePlaylists;
13
use HansOtt\Lastify\Exception\PlaylistDoesNotExist;
14
15
final class Spotify implements CanManagePlaylists
16
{
17
    private $api;
18
19
    private $userId = null;
20
21
    public function __construct(SpotifyWebAPI $api)
22
    {
23
        $this->api = $api;
24
    }
25
26
    public static function connect($accessToken)
27
    {
28
        static::assertValidAccessToken($accessToken);
0 ignored issues
show
Comprehensibility introduced by
Since HansOtt\Lastify\Services\Spotify is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
29
        $api = new SpotifyWebAPI();
30
        $api->setAccessToken($accessToken);
31
32
        return new static($api);
33
    }
34
35
    private static function assertValidAccessToken($accessToken)
36
    {
37
        if (!is_string($accessToken)) {
38
            throw new InvalidArgumentException('The access token should be a string, instead got:' . gettype($accessToken));
39
        }
40
41
        if (empty($accessToken)) {
42
            throw new InvalidArgumentException('The access token cannot be empty');
43
        }
44
    }
45
46
    private function getSearchQuery(TrackInfo $info)
47
    {
48
        $addArtistName = function ($artistNames, Artist $artist) {
49
            return $artistNames . $artist->getName();
50
        };
51
52
        $artistNames = array_reduce($info->getArtists(), $addArtistName, '');
53
54
        return $info->getName() . ' ' . $artistNames;
55
    }
56
57
    private function getTrackId(TrackInfo $track)
58
    {
59
        $options = [
60
            'type' => 'track',
61
            'limit' => 1,
62
        ];
63
64
        $query = $this->getSearchQuery($track);
65
        $result = $this->api->search($query, $options);
66
67
        $tracks = is_array($result->tracks->items) ? $result->tracks->items : [];
68
69
        if (empty($tracks)) {
70
            return null;
71
        }
72
73
        $firstMatch = array_shift($tracks);
74
75
        return !empty($firstMatch->id) ? $firstMatch->id : null;
76
    }
77
78
    private function fetchUserPlaylists()
79
    {
80
        $response = $this->api->getMyPlaylists();
81
82
        return isset($response->items) ? $response->items : [];
83
    }
84
85
    public function getPlaylistId($name)
86
    {
87
        $playlists = $this->fetchUserPlaylists();
88
89
        foreach ($playlists as $playlist) {
90
            if ($playlist->name == $name) {
91
                return $playlist->id;
92
            }
93
        }
94
95
        throw new PlaylistDoesNotExist($name);
96
    }
97
98
    private function getUserId()
99
    {
100
        if (isset($this->userId)) {
101
            return $this->userId;
102
        }
103
104
        $user = $this->api->me();
105
        $userId = (int) $user->id;
106
        $this->userId = $userId;
107
108
        return $userId;
109
    }
110
111
    public function createPlaylist($name)
112
    {
113
        $this->assertValidPlaylistName($name);
114
115
        $options = [
116
            'name' => $name
117
        ];
118
119
        $createdPlaylist = $this->api->createUserPlaylist($this->getUserId(), $options);
120
121
        return $createdPlaylist->id;
122
    }
123
124 View Code Duplication
    private function assertValidPlaylistName($name)
0 ignored issues
show
Duplication introduced by
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.

Loading history...
125
    {
126
        if (!is_string($name)) {
127
            throw new InvalidArgumentException('The playlist name should be a string, instead got:' . gettype($name));
128
        }
129
        if (empty($name)) {
130
            throw new InvalidArgumentException('The playlist name cannot be empty');
131
        }
132
    }
133
134
    public function replacePlaylistTracks($playlistId, TrackCollection $newTracks, SyncProgress $progress)
135
    {
136
        $syncResult = new SyncResult();
137
        $trackIds = [];
138
139
        foreach ($newTracks as $track) {
140
            $progress->step($track);
141
            $trackId = $this->getTrackId($track);
142
143
            if (empty($trackId)) {
144
                $syncResult->addIgnoredTrack($track);
145
            } else {
146
                $trackIds[] = $trackId;
147
            }
148
        }
149
150
        $this->api->replaceUserPlaylistTracks(
151
            $this->getUserId(),
152
            $playlistId,
153
            $trackIds
154
        );
155
156
        return $syncResult;
157
    }
158
}
159