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 | |||
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
|
|||
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
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. ![]() |
|||
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 |
Late static binding only has effect in subclasses. A
final
class cannot be extended anymore so late static binding cannot occurr. Consider replacingstatic::
withself::
.To learn more about late static binding, please refer to the PHP core documentation.