• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jwilsson / spotify-web-api-php / 12841789784

18 Jan 2025 06:46AM UTC coverage: 98.701%. Remained the same
12841789784

push

github

jwilsson
6.2.0 changelog

760 of 770 relevant lines covered (98.7%)

21.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.48
/src/SpotifyWebAPI.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace SpotifyWebAPI;
6

7
class SpotifyWebAPI
8
{
9
    protected string $accessToken = '';
10
    protected array $lastResponse = [];
11
    protected array $options = [
12
        'auto_refresh' => false,
13
        'auto_retry' => false,
14
        'return_assoc' => false,
15
    ];
16
    protected ?Request $request = null;
17
    protected ?Session $session = null;
18

19
    /**
20
     * Constructor
21
     * Set options and class instances to use.
22
     *
23
     * @param array|object $options Optional. Options to set.
24
     * @param Session $session Optional. The Session object to use.
25
     * @param Request $request Optional. The Request object to use.
26
     */
27
    public function __construct(array|object $options = [], ?Session $session = null, ?Request $request = null)
28
    {
29
        $this->setOptions($options);
396✔
30
        $this->setSession($session);
396✔
31

32
        $this->request = $request ?? new Request();
396✔
33
    }
34

35
    /**
36
     * Add authorization headers.
37
     *
38
     * @param $headers array. Optional. Additional headers to merge with the authorization headers.
39
     *
40
     * @return array Authorization headers, optionally merged with the passed ones.
41
     */
42
    protected function authHeaders(array $headers = []): array
43
    {
44
        $accessToken = $this->session ? $this->session->getAccessToken() : $this->accessToken;
380✔
45

46
        if ($accessToken) {
380✔
47
            $headers = array_merge($headers, [
8✔
48
                'Authorization' => 'Bearer ' . $accessToken,
8✔
49
            ]);
8✔
50
        }
51

52
        return $headers;
380✔
53
    }
54

55
    /**
56
     * Try to fetch a snapshot ID from a response.
57
     *
58
     * @param object|array $body The parsed response body.
59
     *
60
     * @return string|bool A snapshot ID or false if none exists.
61
     */
62
    protected function getSnapshotId(array|object $body): string|bool
63
    {
64
        $body = (array) $body;
28✔
65

66
        return $body['snapshot_id'] ?? false;
28✔
67
    }
68

69
    /**
70
     * Convert Spotify object IDs to URIs.
71
     *
72
     * @param string|array $ids ID(s) to convert.
73
     * @param string $type Spotify object type.
74
     *
75
     * @return string|array URI(s).
76
     */
77
    protected function idToUri(string|array $ids, string $type): string|array
78
    {
79
        $type = 'spotify:' . $type . ':';
24✔
80

81
        $ids = array_map(function ($id) use ($type) {
24✔
82
            if (substr($id, 0, strlen($type)) != $type && substr($id, 0, 7) != 'spotify') {
20✔
83
                $id = $type . $id;
16✔
84
            }
85

86
            return $id;
20✔
87
        }, (array) $ids);
24✔
88

89
        return count($ids) == 1 ? $ids[0] : $ids;
24✔
90
    }
91

92
    /**
93
     * Send a request to the Spotify API, automatically refreshing the access token as needed.
94
     *
95
     * @param string $method The HTTP method to use.
96
     * @param string $uri The URI to request.
97
     * @param string|array $parameters Optional. Query string parameters or HTTP body, depending on $method.
98
     * @param array $headers Optional. HTTP headers.
99
     *
100
     * @throws SpotifyWebAPIException
101
     * @throws SpotifyWebAPIAuthException
102
     *
103
     * @return array Response data.
104
     * - array|object body The response body. Type is controlled by the `return_assoc` option.
105
     * - array headers Response headers.
106
     * - int status HTTP status code.
107
     * - string url The requested URL.
108
     */
109
    protected function sendRequest(
110
        string $method,
111
        string $uri,
112
        string|array $parameters = [],
113
        array $headers = []
114
    ): array {
115
        $this->request->setOptions([
380✔
116
            'return_assoc' => $this->options['return_assoc'],
380✔
117
        ]);
380✔
118

119
        try {
120
            $headers = $this->authHeaders($headers);
380✔
121

122
            return $this->request->api($method, $uri, $parameters, $headers);
380✔
123
        } catch (SpotifyWebAPIException $e) {
8✔
124
            if ($this->options['auto_refresh'] && $e->hasExpiredToken()) {
8✔
125
                $result = $this->session->refreshAccessToken();
4✔
126

127
                if (!$result) {
4✔
128
                    throw new SpotifyWebAPIException('Could not refresh access token.');
×
129
                }
130

131
                return $this->sendRequest($method, $uri, $parameters, $headers);
4✔
132
            } elseif ($this->options['auto_retry'] && $e->isRateLimited()) {
4✔
133
                ['headers' => $lastHeaders] = $this->request->getLastResponse();
4✔
134

135
                sleep((int) $lastHeaders['retry-after']);
4✔
136

137
                return $this->sendRequest($method, $uri, $parameters, $headers);
4✔
138
            }
139

140
            throw $e;
×
141
        }
142
    }
143

144
    /**
145
     * Convert an array to a comma-separated string. If it's already a string, do nothing.
146
     *
147
     * @param array|string $value The value to convert.
148
     *
149
     * @return string A comma-separated string.
150
     */
151
    protected function toCommaString(string|array $value): string
152
    {
153
        if (is_array($value)) {
84✔
154
            return implode(',', $value);
84✔
155
        }
156

157
        return $value;
4✔
158
    }
159

160
    /**
161
     * Convert URIs to Spotify object IDs.
162
     *
163
     * @param string|array $uriIds URI(s) to convert.
164
     * @param string $type Spotify object type.
165
     *
166
     * @return string|array ID(s).
167
     */
168
    protected function uriToId(string|array $uriIds, string $type): string|array
169
    {
170
        $type = 'spotify:' . $type . ':';
236✔
171

172
        $uriIds = array_map(function ($id) use ($type) {
236✔
173
            return str_replace($type, '', $id);
236✔
174
        }, (array) $uriIds);
236✔
175

176
        return count($uriIds) == 1 ? $uriIds[0] : $uriIds;
236✔
177
    }
178

179
    /**
180
     * Add albums to the current user's Spotify library.
181
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/save-albums-user
182
     *
183
     * @param string|array $albums Album IDs or URIs to add.
184
     *
185
     * @return bool Whether the albums was successfully added.
186
     */
187
    public function addMyAlbums(string|array $albums): bool
188
    {
189
        $albums = $this->uriToId($albums, 'album');
4✔
190
        $albums = json_encode([
4✔
191
            'ids' => (array) $albums,
4✔
192
        ]);
4✔
193

194
        $headers = [
4✔
195
            'Content-Type' => 'application/json',
4✔
196
        ];
4✔
197

198
        $uri = '/v1/me/albums';
4✔
199

200
        $this->lastResponse = $this->sendRequest('PUT', $uri, $albums, $headers);
4✔
201

202
        return $this->lastResponse['status'] == 200;
4✔
203
    }
204

205
    /**
206
     * Add episodes to the current user's Spotify library.
207
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/save-episodes-user
208
     *
209
     * @param string|array $episodes Episode IDs or URIs to add.
210
     *
211
     * @return bool Whether the episodes was successfully added.
212
     */
213
    public function addMyEpisodes(string|array $episodes): bool
214
    {
215
        $episodes = $this->uriToId($episodes, 'episode');
4✔
216
        $episodes = json_encode([
4✔
217
            'ids' => (array) $episodes,
4✔
218
        ]);
4✔
219

220
        $headers = [
4✔
221
            'Content-Type' => 'application/json',
4✔
222
        ];
4✔
223

224
        $uri = '/v1/me/episodes';
4✔
225

226
        $this->lastResponse = $this->sendRequest('PUT', $uri, $episodes, $headers);
4✔
227

228
        return $this->lastResponse['status'] == 200;
4✔
229
    }
230

231
    /**
232
     * Add shows to the current user's Spotify library.
233
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/save-shows-user
234
     *
235
     * @param string|array $shows Show IDs or URIs to add.
236
     *
237
     * @return bool Whether the shows was successfully added.
238
     */
239
    public function addMyShows(string|array $shows): bool
240
    {
241
        $shows = $this->uriToId($shows, 'show');
4✔
242
        $shows = json_encode([
4✔
243
            'ids' => (array) $shows,
4✔
244
        ]);
4✔
245

246
        $headers = [
4✔
247
            'Content-Type' => 'application/json',
4✔
248
        ];
4✔
249

250
        $uri = '/v1/me/shows';
4✔
251

252
        $this->lastResponse = $this->sendRequest('PUT', $uri, $shows, $headers);
4✔
253

254
        return $this->lastResponse['status'] == 200;
4✔
255
    }
256

257
    /**
258
     * Add tracks to the current user's Spotify library.
259
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/save-tracks-user
260
     *
261
     * @param string|array $tracks Track IDs or URIs to add.
262
     *
263
     * @return bool Whether the tracks was successfully added.
264
     */
265
    public function addMyTracks(string|array $tracks): bool
266
    {
267
        $tracks = $this->uriToId($tracks, 'track');
4✔
268
        $tracks = json_encode([
4✔
269
            'ids' => (array) $tracks,
4✔
270
        ]);
4✔
271

272
        $headers = [
4✔
273
            'Content-Type' => 'application/json',
4✔
274
        ];
4✔
275

276
        $uri = '/v1/me/tracks';
4✔
277

278
        $this->lastResponse = $this->sendRequest('PUT', $uri, $tracks, $headers);
4✔
279

280
        return $this->lastResponse['status'] == 200;
4✔
281
    }
282

283
    /**
284
     * Add tracks to a playlist.
285
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/add-tracks-to-playlist
286
     *
287
     * @param string $playlistId ID of the playlist to add tracks to.
288
     * @param string|array $tracks Track IDs, track URIs, and episode URIs to add.
289
     * @param array|object $options Optional. Options for the new tracks.
290
     * - int position Optional. Zero-based track position in playlist. Tracks will be appended if omitted or false.
291
     *
292
     * @return string|bool A new snapshot ID or false if the tracks weren't successfully added.
293
     */
294
    public function addPlaylistTracks(
295
        string $playlistId,
296
        string|array $tracks,
297
        array|object $options = []
298
    ): string|bool {
299
        $options = array_merge((array) $options, [
8✔
300
            'uris' => (array) $this->idToUri($tracks, 'track')
8✔
301
        ]);
8✔
302

303
        $options = json_encode($options);
8✔
304

305
        $headers = [
8✔
306
            'Content-Type' => 'application/json',
8✔
307
        ];
8✔
308

309
        $playlistId = $this->uriToId($playlistId, 'playlist');
8✔
310

311
        $uri = '/v1/playlists/' . $playlistId . '/tracks';
8✔
312

313
        $this->lastResponse = $this->sendRequest('POST', $uri, $options, $headers);
8✔
314

315
        return $this->getSnapshotId($this->lastResponse['body']);
8✔
316
    }
317

318
    /**
319
     * Change the current user's playback device.
320
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/transfer-a-users-playback
321
     *
322
     * @param array|object $options Options for the playback transfer.
323
     * - string|array device_ids Required. ID of the device to switch to.
324
     * - bool play Optional. Whether to start playing on the new device
325
     *
326
     * @return bool Whether the playback device was successfully changed.
327
     */
328
    public function changeMyDevice(array|object $options): bool
329
    {
330
        $options = array_merge((array) $options, [
4✔
331
            'device_ids' => (array) $options['device_ids'],
4✔
332
        ]);
4✔
333

334
        $options = json_encode($options);
4✔
335

336
        $headers = [
4✔
337
            'Content-Type' => 'application/json',
4✔
338
        ];
4✔
339

340
        $uri = '/v1/me/player';
4✔
341

342
        $this->lastResponse = $this->sendRequest('PUT', $uri, $options, $headers);
4✔
343

344
        return $this->lastResponse['status'] == 204;
4✔
345
    }
346

347
    /**
348
     * Change playback volume for the current user.
349
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/set-volume-for-users-playback
350
     *
351
     * @param array|object $options Optional. Options for the playback volume.
352
     * - int volume_percent Required. The volume to set.
353
     * - string device_id Optional. ID of the device to target.
354
     *
355
     * @return bool Whether the playback volume was successfully changed.
356
     */
357
    public function changeVolume(array|object $options): bool
358
    {
359
        $options = http_build_query($options, '', '&');
4✔
360

361
        // We need to manually append data to the URI since it's a PUT request
362
        $uri = '/v1/me/player/volume?' . $options;
4✔
363

364
        $this->lastResponse = $this->sendRequest('PUT', $uri);
4✔
365

366
        return $this->lastResponse['status'] == 204;
4✔
367
    }
368

369
    /**
370
     * Create a new playlist.
371
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/create-playlist
372
     *
373
     * @param string $userId ID or URI of the user to create the playlist for.
374
     * @param array|object $options Options for the new playlist.
375
     * - string name Required. Name of the playlist.
376
     * - bool collaborative Optional. Whether the playlist should be collaborative or not.
377
     * - string description Optional. Description of the playlist.
378
     * - bool public Optional. Whether the playlist should be public or not.
379
     *
380
     * @return array|object The new playlist. Type is controlled by the `return_assoc` option.
381
     */
382
    public function createPlaylist(string|array|object $userId, array|object $options = []): array|object
383
    {
384
        if (is_array($userId) || is_object($userId)) {
8✔
385
            trigger_error(
4✔
386
                'Calling SpotifyWebAPI::createPlaylist() without a user ID is deprecated.',
4✔
387
                E_USER_DEPRECATED
4✔
388
            );
4✔
389

390
            $options = $userId;
4✔
391
            $uri = '/v1/me/playlists';
4✔
392
        } else {
393
            $userId = $this->uriToId($userId, 'user');
4✔
394
            $uri = '/v1/users/' . $userId . '/playlists';
4✔
395
        }
396

397
        $options = json_encode($options);
8✔
398

399
        $headers = [
8✔
400
            'Content-Type' => 'application/json',
8✔
401
        ];
8✔
402

403
        $this->lastResponse = $this->sendRequest('POST', $uri, $options, $headers);
8✔
404

405
        return $this->lastResponse['body'];
8✔
406
    }
407

408
    /**
409
     * Check to see if the current user is following one or more artists or other Spotify users.
410
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-current-user-follows
411
     *
412
     * @param string $type The type to check: either 'artist' or 'user'.
413
     * @param string|array $ids IDs or URIs of the users or artists to check for.
414
     *
415
     * @return array Whether each user or artist is followed.
416
     */
417
    public function currentUserFollows(string $type, string|array $ids): array
418
    {
419
        $ids = $this->uriToId($ids, $type);
4✔
420
        $ids = $this->toCommaString($ids);
4✔
421

422
        $options = [
4✔
423
            'ids' => $ids,
4✔
424
            'type' => $type,
4✔
425
        ];
4✔
426

427
        $uri = '/v1/me/following/contains';
4✔
428

429
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
430

431
        return $this->lastResponse['body'];
4✔
432
    }
433

434
    /**
435
     * Delete albums from the current user's Spotify library.
436
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/remove-albums-user
437
     *
438
     * @param string|array $albums Album IDs or URIs to delete.
439
     *
440
     * @return bool Whether the albums was successfully deleted.
441
     */
442
    public function deleteMyAlbums(string|array $albums): bool
443
    {
444
        $albums = $this->uriToId($albums, 'album');
4✔
445
        $albums = json_encode([
4✔
446
            'ids' => (array) $albums,
4✔
447
        ]);
4✔
448

449
        $headers = [
4✔
450
            'Content-Type' => 'application/json',
4✔
451
        ];
4✔
452

453
        $uri = '/v1/me/albums';
4✔
454

455
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $albums, $headers);
4✔
456

457
        return $this->lastResponse['status'] == 200;
4✔
458
    }
459

460
    /**
461
     * Delete episodes from the current user's Spotify library.
462
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/remove-episodes-user
463
     *
464
     * @param string|array $episodes Episode IDs or URIs to delete.
465
     *
466
     * @return bool Whether the episodes was successfully deleted.
467
     */
468
    public function deleteMyEpisodes(string|array $episodes): bool
469
    {
470
        $episodes = $this->uriToId($episodes, 'episode');
4✔
471
        $episodes = json_encode([
4✔
472
            'ids' => (array) $episodes,
4✔
473
        ]);
4✔
474

475
        $headers = [
4✔
476
            'Content-Type' => 'application/json',
4✔
477
        ];
4✔
478

479
        $uri = '/v1/me/episodes';
4✔
480

481
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $episodes, $headers);
4✔
482

483
        return $this->lastResponse['status'] == 200;
4✔
484
    }
485

486
    /**
487
     * Delete shows from the current user's Spotify library.
488
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/remove-shows-user
489
     *
490
     * @param string|array $shows Show IDs or URIs to delete.
491
     *
492
     * @return bool Whether the shows was successfully deleted.
493
     */
494
    public function deleteMyShows(string|array $shows): bool
495
    {
496
        $shows = $this->uriToId($shows, 'show');
4✔
497
        $shows = json_encode([
4✔
498
            'ids' => (array) $shows,
4✔
499
        ]);
4✔
500

501
        $headers = [
4✔
502
            'Content-Type' => 'application/json',
4✔
503
        ];
4✔
504

505
        $uri = '/v1/me/shows';
4✔
506

507
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $shows, $headers);
4✔
508

509
        return $this->lastResponse['status'] == 200;
4✔
510
    }
511

512
    /**
513
     * Delete tracks from the current user's Spotify library.
514
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/remove-tracks-user
515
     *
516
     * @param string|array $tracks Track IDs or URIs to delete.
517
     *
518
     * @return bool Whether the tracks was successfully deleted.
519
     */
520
    public function deleteMyTracks(string|array $tracks): bool
521
    {
522
        $tracks = $this->uriToId($tracks, 'track');
4✔
523
        $tracks = json_encode([
4✔
524
            'ids' => (array) $tracks,
4✔
525
        ]);
4✔
526

527
        $headers = [
4✔
528
            'Content-Type' => 'application/json',
4✔
529
        ];
4✔
530

531
        $uri = '/v1/me/tracks';
4✔
532

533
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $tracks, $headers);
4✔
534

535
        return $this->lastResponse['status'] == 200;
4✔
536
    }
537

538
    /**
539
     * Delete tracks from a playlist and retrieve a new snapshot ID.
540
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/remove-tracks-playlist
541
     *
542
     * @param string $playlistId ID or URI of the playlist to delete tracks from.
543
     * @param array $tracks An array with the key "tracks" containing arrays or objects with tracks to delete.
544
     * Or an array with the key "positions" containing integer positions of the tracks to delete.
545
     * If the "tracks" key is used, the following fields are also available:
546
     * - string uri Required. Track ID, track URI, or episode URI.
547
     * - int|array positions Optional. The track's positions in the playlist.
548
     * @param string $snapshotId Required when `$tracks['positions']` is used, optional otherwise.
549
     * The playlist's snapshot ID.
550
     *
551
     * @return string|bool A new snapshot ID or false if the tracks weren't successfully deleted.
552
     */
553
    public function deletePlaylistTracks(string $playlistId, array $tracks, string $snapshotId = ''): string|bool
554
    {
555
        $options = [];
12✔
556

557
        if ($snapshotId) {
12✔
558
            $options['snapshot_id'] = $snapshotId;
8✔
559
        }
560

561
        if (isset($tracks['positions'])) {
12✔
562
            $options['positions'] = $tracks['positions'];
8✔
563
        } else {
564
            $options['tracks'] = array_map(function ($track) {
4✔
565
                $track = (array) $track;
4✔
566

567
                if (isset($track['positions'])) {
4✔
568
                    $track['positions'] = (array) $track['positions'];
4✔
569
                }
570

571
                $track['uri'] = $this->idToUri($track['uri'], 'track');
4✔
572

573
                return $track;
4✔
574
            }, $tracks['tracks']);
4✔
575
        }
576

577
        $options = json_encode($options);
12✔
578

579
        $headers = [
12✔
580
            'Content-Type' => 'application/json',
12✔
581
        ];
12✔
582

583
        $playlistId = $this->uriToId($playlistId, 'playlist');
12✔
584

585
        $uri = '/v1/playlists/' . $playlistId . '/tracks';
12✔
586

587
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $options, $headers);
12✔
588

589
        return $this->getSnapshotId($this->lastResponse['body']);
12✔
590
    }
591

592
    /**
593
     * Add the current user as a follower of one or more artists or other Spotify users.
594
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/follow-artists-users
595
     *
596
     * @param string $type The type of ID to follow: either 'artist' or 'user'.
597
     * @param string|array $ids IDs or URIs of the users or artists to follow.
598
     *
599
     * @return bool Whether the artist or user was successfully followed.
600
     */
601
    public function followArtistsOrUsers(string $type, string|array $ids): bool
602
    {
603
        $ids = $this->uriToId($ids, $type);
4✔
604
        $ids = json_encode([
4✔
605
            'ids' => (array) $ids,
4✔
606
        ]);
4✔
607

608
        $headers = [
4✔
609
            'Content-Type' => 'application/json',
4✔
610
        ];
4✔
611

612
        // We need to manually append data to the URI since it's a PUT request
613
        $uri = '/v1/me/following?type=' . $type;
4✔
614

615
        $this->lastResponse = $this->sendRequest('PUT', $uri, $ids, $headers);
4✔
616

617
        return $this->lastResponse['status'] == 204;
4✔
618
    }
619

620
    /**
621
     * Add the current user as a follower of a playlist.
622
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/follow-playlist
623
     *
624
     * @param string $playlistId ID or URI of the playlist to follow.
625
     * @param array|object $options Optional. Options for the followed playlist.
626
     * - bool public Optional. Whether the playlist should be followed publicly or not.
627
     *
628
     * @return bool Whether the playlist was successfully followed.
629
     */
630
    public function followPlaylist(string $playlistId, array|object $options = []): bool
631
    {
632
        $options = $options ? json_encode($options) : '';
4✔
633

634
        $headers = [
4✔
635
            'Content-Type' => 'application/json',
4✔
636
        ];
4✔
637

638
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
639

640
        $uri = '/v1/playlists/' . $playlistId . '/followers';
4✔
641

642
        $this->lastResponse = $this->sendRequest('PUT', $uri, $options, $headers);
4✔
643

644
        return $this->lastResponse['status'] == 200;
4✔
645
    }
646

647
    /**
648
     * Get an album.
649
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-album
650
     *
651
     * @param string $albumId ID or URI of the album.
652
     * @param array|object $options Optional. Options for the album.
653
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
654
     *
655
     * @return array|object The requested album. Type is controlled by the `return_assoc` option.
656
     */
657
    public function getAlbum(string $albumId, array|object $options = []): array|object
658
    {
659
        $albumId = $this->uriToId($albumId, 'album');
4✔
660
        $uri = '/v1/albums/' . $albumId;
4✔
661

662
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
663

664
        return $this->lastResponse['body'];
4✔
665
    }
666

667
    /**
668
     * Get multiple albums.
669
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-multiple-albums
670
     *
671
     * @param array $albumIds IDs or URIs of the albums.
672
     * @param array|object $options Optional. Options for the albums.
673
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
674
     *
675
     * @return array|object The requested albums. Type is controlled by the `return_assoc` option.
676
     */
677
    public function getAlbums(array $albumIds, array|object $options = []): array|object
678
    {
679
        $albumIds = $this->uriToId($albumIds, 'album');
4✔
680
        $options = array_merge((array) $options, [
4✔
681
            'ids' => $this->toCommaString($albumIds),
4✔
682
        ]);
4✔
683

684
        $uri = '/v1/albums/';
4✔
685

686
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
687

688
        return $this->lastResponse['body'];
4✔
689
    }
690

691
    /**
692
     * Get an album's tracks.
693
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-albums-tracks
694
     *
695
     * @param string $albumId ID or URI of the album.
696
     * @param array|object $options Optional. Options for the tracks.
697
     * - int limit Optional. Limit the number of tracks.
698
     * - int offset Optional. Number of tracks to skip.
699
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
700
     *
701
     * @return array|object The requested album tracks. Type is controlled by the `return_assoc` option.
702
     */
703
    public function getAlbumTracks(string $albumId, array|object $options = []): array|object
704
    {
705
        $albumId = $this->uriToId($albumId, 'album');
4✔
706
        $uri = '/v1/albums/' . $albumId . '/tracks';
4✔
707

708
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
709

710
        return $this->lastResponse['body'];
4✔
711
    }
712

713
    /**
714
     * Get an artist.
715
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artist
716
     *
717
     * @param string $artistId ID or URI of the artist.
718
     *
719
     * @return array|object The requested artist. Type is controlled by the `return_assoc` option.
720
     */
721
    public function getArtist(string $artistId): array|object
722
    {
723
        $artistId = $this->uriToId($artistId, 'artist');
4✔
724
        $uri = '/v1/artists/' . $artistId;
4✔
725

726
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
727

728
        return $this->lastResponse['body'];
4✔
729
    }
730

731
    /**
732
     * Get multiple artists.
733
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-multiple-artists
734
     *
735
     * @param array $artistIds IDs or URIs of the artists.
736
     *
737
     * @return array|object The requested artists. Type is controlled by the `return_assoc` option.
738
     */
739
    public function getArtists(array $artistIds): array|object
740
    {
741
        $artistIds = $this->uriToId($artistIds, 'artist');
4✔
742
        $artistIds = $this->toCommaString($artistIds);
4✔
743

744
        $options = [
4✔
745
            'ids' => $artistIds,
4✔
746
        ];
4✔
747

748
        $uri = '/v1/artists/';
4✔
749

750
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
751

752
        return $this->lastResponse['body'];
4✔
753
    }
754

755
    /**
756
     * Get an artist's related artists.
757
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artists-related-artists
758
     *
759
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
760
     *
761
     * @param string $artistId ID or URI of the artist.
762
     *
763
     * @return array|object The artist's related artists. Type is controlled by the `return_assoc` option.
764
     */
765
    public function getArtistRelatedArtists(string $artistId): array|object
766
    {
767
        $artistId = $this->uriToId($artistId, 'artist');
4✔
768
        $uri = '/v1/artists/' . $artistId . '/related-artists';
4✔
769

770
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
771

772
        return $this->lastResponse['body'];
4✔
773
    }
774

775
    /**
776
     * Get an artist's albums.
777
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artists-albums
778
     *
779
     * @param string $artistId ID or URI of the artist.
780
     * @param array|object $options Optional. Options for the albums.
781
     * - string market Optional. Limit the results to items that are playable in this country, for example SE.
782
     * - string|array include_groups Optional. Album types to return. If omitted, all album types will be returned.
783
     * - int limit Optional. Limit the number of albums.
784
     * - int offset Optional. Number of albums to skip.
785
     *
786
     * @return array|object The artist's albums. Type is controlled by the `return_assoc` option.
787
     */
788
    public function getArtistAlbums(string $artistId, array|object $options = []): array|object
789
    {
790
        $options = (array) $options;
4✔
791

792
        if (isset($options['include_groups'])) {
4✔
793
            $options['include_groups'] = $this->toCommaString($options['include_groups']);
4✔
794
        }
795

796
        $artistId = $this->uriToId($artistId, 'artist');
4✔
797
        $uri = '/v1/artists/' . $artistId . '/albums';
4✔
798

799
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
800

801
        return $this->lastResponse['body'];
4✔
802
    }
803

804
    /**
805
     * Get an artist's top tracks in a country.
806
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-artists-top-tracks
807
     *
808
     * @param string $artistId ID or URI of the artist.
809
     * @param array|object $options Options for the tracks.
810
     * - string market Required. An ISO 3166-1 alpha-2 country code specifying the country to get the top tracks for.
811
     *
812
     * @return array|object The artist's top tracks. Type is controlled by the `return_assoc` option.
813
     */
814
    public function getArtistTopTracks(string $artistId, array|object $options): array|object
815
    {
816
        $artistId = $this->uriToId($artistId, 'artist');
4✔
817
        $uri = '/v1/artists/' . $artistId . '/top-tracks';
4✔
818

819
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
820

821
        return $this->lastResponse['body'];
4✔
822
    }
823

824
    /**
825
     * Get audio analysis for track.
826
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-audio-analysis
827
     *
828
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
829
     *
830
     * @param string $trackId ID or URI of the track.
831
     *
832
     * @return array|object The track's audio analysis. Type is controlled by the `return_assoc` option.
833
     */
834
    public function getAudioAnalysis(string $trackId): array|object
835
    {
836
        $trackId = $this->uriToId($trackId, 'track');
4✔
837
        $uri = '/v1/audio-analysis/' . $trackId;
4✔
838

839
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
840

841
        return $this->lastResponse['body'];
4✔
842
    }
843

844
    /**
845
     * Get an audiobook.
846
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-audiobook
847
     *
848
     * @param string $audiobookId ID or URI of the audiobook.
849
     * @param array|object $options Optional. Options for the audiobook.
850
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to audiobooks available in that market.
851
     *
852
     * @return array|object The requested audiobook. Type is controlled by the `return_assoc` option.
853
     */
854
    public function getAudiobook(string $audiobookId, array|object $options = [])
855
    {
856
        $audiobookId = $this->uriToId($audiobookId, 'show');
4✔
857
        $uri = '/v1/audiobooks/' . $audiobookId;
4✔
858

859
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
860

861
        return $this->lastResponse['body'];
4✔
862
    }
863

864
    /**
865
     * Get multiple audiobooks.
866
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-multiple-audiobooks
867
     *
868
     * @param array $audiobookIds IDs or URIs of the audiobooks.
869
     * @param array|object $options Optional. Options for the audiobooks.
870
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to audiobooks available in that market.
871
     *
872
     * @return array|object The requested audiobooks. Type is controlled by the `return_assoc` option.
873
     */
874
    public function getAudiobooks(array $audiobookIds, array|object $options = [])
875
    {
876
        $audiobookIds = $this->uriToId($audiobookIds, 'show');
4✔
877
        $audiobookIds = $this->toCommaString($audiobookIds);
4✔
878

879
        $options = array_merge((array) $options, [
4✔
880
            'ids' => $this->toCommaString($audiobookIds),
4✔
881
        ]);
4✔
882

883
        $uri = '/v1/audiobooks/';
4✔
884

885
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
886

887
        return $this->lastResponse['body'];
4✔
888
    }
889

890
    /**
891
     * Get audio features of a single track.
892
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-audio-features
893
     *
894
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
895
     *
896
     * @param string $trackId ID or URI of the track.
897
     *
898
     * @return array|object The track's audio features. Type is controlled by the `return_assoc` option.
899
     */
900
    public function getAudioFeatures(string $trackId): array|object
901
    {
902
        $trackId = $this->uriToId($trackId, 'track');
4✔
903
        $uri = '/v1/audio-features/' . $trackId;
4✔
904

905
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
906

907
        return $this->lastResponse['body'];
4✔
908
    }
909

910
    /**
911
     * Get a list of categories used to tag items in Spotify (on, for example, the Spotify player’s "Discover" tab).
912
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-categories
913
     *
914
     * @param array|object $options Optional. Options for the categories.
915
     * - string locale Optional. Language to show categories in, for example 'sv_SE'.
916
     * - string country Optional. ISO 3166-1 alpha-2 country code. Show categories from this country.
917
     * - int limit Optional. Limit the number of categories.
918
     * - int offset Optional. Number of categories to skip.
919
     *
920
     * @return array|object The list of categories. Type is controlled by the `return_assoc` option.
921
     */
922
    public function getCategoriesList(array|object $options = []): array|object
923
    {
924
        $uri = '/v1/browse/categories';
4✔
925

926
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
927

928
        return $this->lastResponse['body'];
4✔
929
    }
930

931
    /**
932
     * Get a single category used to tag items in Spotify (on, for example, the Spotify player’s "Discover" tab).
933
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-category
934
     *
935
     * @param string $categoryId ID of the category.
936
     *
937
     * @param array|object $options Optional. Options for the category.
938
     * - string locale Optional. Language to show category in, for example 'sv_SE'.
939
     * - string country Optional. ISO 3166-1 alpha-2 country code. Show category from this country.
940
     *
941
     * @return array|object The category. Type is controlled by the `return_assoc` option.
942
     */
943
    public function getCategory(string $categoryId, array|object $options = []): array|object
944
    {
945
        $uri = '/v1/browse/categories/' . $categoryId;
4✔
946

947
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
948

949
        return $this->lastResponse['body'];
4✔
950
    }
951

952
    /**
953
     * Get a list of Spotify playlists tagged with a particular category.
954
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-categories-playlists
955
     *
956
     * @param string $categoryId ID of the category.
957
     *
958
     * @param array|object $options Optional. Options for the category's playlists.
959
     * - string country Optional. ISO 3166-1 alpha-2 country code. Show category playlists from this country.
960
     * - int limit Optional. Limit the number of playlists.
961
     * - int offset Optional. Number of playlists to skip.
962
     *
963
     * @return array|object The list of playlists. Type is controlled by the `return_assoc` option.
964
     */
965
    public function getCategoryPlaylists(string $categoryId, array|object $options = []): array|object
966
    {
967
        $uri = '/v1/browse/categories/' . $categoryId . '/playlists';
4✔
968

969
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
970

971
        return $this->lastResponse['body'];
4✔
972
    }
973

974
    /**
975
     * Get a chapter.
976
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-chapter
977
     *
978
     * @param string $chapterId ID or URI of the chapter.
979
     * @param array|object $options Optional. Options for the chapter.
980
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
981
     *
982
     * @return array|object The requested chapter. Type is controlled by the `return_assoc` option.
983
     */
984
    public function getChapter(string $chapterId, array|object $options = [])
985
    {
986
        $chapterId = $this->uriToId($chapterId, 'episode');
4✔
987
        $uri = '/v1/chapters/' . $chapterId;
4✔
988

989
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
990

991
        return $this->lastResponse['body'];
4✔
992
    }
993

994
    /**
995
     * Get multiple chapters.
996
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-several-chapters
997
     *
998
     * @param array $chapterIds IDs or URIs of the chapters.
999
     * @param array|object $options Optional. Options for the chapters.
1000
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
1001
     *
1002
     * @return array|object The requested chapters. Type is controlled by the `return_assoc` option.
1003
     */
1004
    public function getChapters(array $chapterIds, array|object $options = [])
1005
    {
1006
        $chapterIds = $this->uriToId($chapterIds, 'episode');
4✔
1007
        $options = array_merge((array) $options, [
4✔
1008
            'ids' => $this->toCommaString($chapterIds),
4✔
1009
        ]);
4✔
1010

1011
        $uri = '/v1/chapters/';
4✔
1012

1013
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1014

1015
        return $this->lastResponse['body'];
4✔
1016
    }
1017

1018
    /**
1019
     * Get an episode.
1020
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-an-episode
1021
     *
1022
     * @param string $episodeId ID or URI of the episode.
1023
     * @param array|object $options Optional. Options for the episode.
1024
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
1025
     *
1026
     * @return array|object The requested episode. Type is controlled by the `return_assoc` option.
1027
     */
1028
    public function getEpisode(string $episodeId, array|object $options = []): array|object
1029
    {
1030
        $episodeId = $this->uriToId($episodeId, 'episode');
4✔
1031
        $uri = '/v1/episodes/' . $episodeId;
4✔
1032

1033
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1034

1035
        return $this->lastResponse['body'];
4✔
1036
    }
1037

1038
    /**
1039
     * Get multiple episodes.
1040
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-multiple-episodes
1041
     *
1042
     * @param string|array $episodeIds IDs or URIs of the episodes.
1043
     * @param array|object $options Optional. Options for the episodes.
1044
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
1045
     *
1046
     * @return array|object The requested episodes. Type is controlled by the `return_assoc` option.
1047
     */
1048
    public function getEpisodes(string|array $episodeIds, array|object $options = []): array|object
1049
    {
1050
        $episodeIds = $this->uriToId($episodeIds, 'episode');
4✔
1051
        $options = array_merge((array) $options, [
4✔
1052
            'ids' => $this->toCommaString($episodeIds),
4✔
1053
        ]);
4✔
1054

1055
        $uri = '/v1/episodes/';
4✔
1056

1057
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1058

1059
        return $this->lastResponse['body'];
4✔
1060
    }
1061

1062
    /**
1063
     * Get Spotify featured playlists.
1064
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-featured-playlists
1065
     *
1066
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
1067
     *
1068
     * @param array|object $options Optional. Options for the playlists.
1069
     * - string locale Optional. Language to show playlists in, for example 'sv_SE'.
1070
     * - string country Optional. ISO 3166-1 alpha-2 country code. Show playlists from this country.
1071
     * - string timestamp Optional. A ISO 8601 timestamp. Show playlists relevant to this date and time.
1072
     * - int limit Optional. Limit the number of playlists.
1073
     * - int offset Optional. Number of playlists to skip.
1074
     *
1075
     * @return array|object The featured playlists. Type is controlled by the `return_assoc` option.
1076
     */
1077
    public function getFeaturedPlaylists(array|object $options = []): array|object
1078
    {
1079
        $uri = '/v1/browse/featured-playlists';
4✔
1080

1081
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1082

1083
        return $this->lastResponse['body'];
4✔
1084
    }
1085

1086
    /**
1087
     * Get a list of possible seed genres.
1088
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-recommendation-genres
1089
     *
1090
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
1091
     *
1092
     * @return array|object All possible seed genres. Type is controlled by the `return_assoc` option.
1093
     */
1094
    public function getGenreSeeds(): array|object
1095
    {
1096
        $uri = '/v1/recommendations/available-genre-seeds';
4✔
1097

1098
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1099

1100
        return $this->lastResponse['body'];
4✔
1101
    }
1102

1103
    /**
1104
     * Get the latest full response from the Spotify API.
1105
     *
1106
     * @return array Response data.
1107
     * - array|object body The response body. Type is controlled by the `return_assoc` option.
1108
     * - array headers Response headers.
1109
     * - int status HTTP status code.
1110
     * - string url The requested URL.
1111
     */
1112
    public function getLastResponse(): array
1113
    {
1114
        return $this->lastResponse;
4✔
1115
    }
1116

1117
    /**
1118
     * Get all markets where Spotify is available.
1119
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-available-markets
1120
     *
1121
     * @return array|object All markets where Spotify is available. Type is controlled by the `return_assoc` option.
1122
     */
1123
    public function getMarkets(): array|object
1124
    {
1125
        $uri = '/v1/markets';
4✔
1126

1127
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1128

1129
        return $this->lastResponse['body'];
4✔
1130
    }
1131

1132
    /**
1133
     * Get audio features of multiple tracks.
1134
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-several-audio-features
1135
     *
1136
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
1137
     *
1138
     * @param string|array $trackIds IDs or URIs of the tracks.
1139
     *
1140
     * @return array|object The tracks' audio features. Type is controlled by the `return_assoc` option.
1141
     */
1142
    public function getMultipleAudioFeatures(string|array $trackIds): array|object
1143
    {
1144
        $trackIds = $this->uriToId($trackIds, 'track');
4✔
1145
        $options = [
4✔
1146
            'ids' => $this->toCommaString($trackIds),
4✔
1147
        ];
4✔
1148

1149
        $uri = '/v1/audio-features';
4✔
1150

1151
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1152

1153
        return $this->lastResponse['body'];
4✔
1154
    }
1155

1156
    /**
1157
     * Get the current user’s currently playing track.
1158
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-the-users-currently-playing-track
1159
     *
1160
     * @param array|object $options Optional. Options for the track.
1161
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1162
     * - string|array additional_types Optional. Types of media to return info about.
1163
     *
1164
     * @return array|object|null The user's currently playing track or null if nothing's currently playing.
1165
     * Type is controlled by the `return_assoc` option.
1166
     */
1167
    public function getMyCurrentTrack(array|object $options = []): array|object|null
1168
    {
1169
        $uri = '/v1/me/player/currently-playing';
8✔
1170
        $options = (array) $options;
8✔
1171

1172
        if (isset($options['additional_types'])) {
8✔
1173
            $options['additional_types'] = $this->toCommaString($options['additional_types']);
4✔
1174
        }
1175

1176
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
8✔
1177

1178
        return $this->lastResponse['body'];
8✔
1179
    }
1180

1181
    /**
1182
     * Get the current user’s devices.
1183
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-users-available-devices
1184
     *
1185
     * @return array|object The user's devices. Type is controlled by the `return_assoc` option.
1186
     */
1187
    public function getMyDevices(): array|object
1188
    {
1189
        $uri = '/v1/me/player/devices';
4✔
1190

1191
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1192

1193
        return $this->lastResponse['body'];
4✔
1194
    }
1195

1196
    /**
1197
     * Get the current user’s current playback information.
1198
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-information-about-the-users-current-playback
1199
     *
1200
     * @param array|object $options Optional. Options for the info.
1201
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1202
     * - string|array additional_types Optional. Types of media to return info about.
1203
     *
1204
     * @return array|object|null The user's playback information or null if nothing's currently playing.
1205
     * Type is controlled by the `return_assoc` option.
1206
     */
1207
    public function getMyCurrentPlaybackInfo(array|object $options = []): array|object|null
1208
    {
1209
        $uri = '/v1/me/player';
8✔
1210
        $options = (array) $options;
8✔
1211

1212
        if (isset($options['additional_types'])) {
8✔
1213
            $options['additional_types'] = $this->toCommaString($options['additional_types']);
4✔
1214
        }
1215

1216
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
8✔
1217

1218
        return $this->lastResponse['body'];
8✔
1219
    }
1220

1221

1222
    /**
1223
     * Get the current user’s playlists.
1224
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-list-of-current-users-playlists
1225
     *
1226
     * @param array|object $options Optional. Options for the playlists.
1227
     * - int limit Optional. Limit the number of playlists.
1228
     * - int offset Optional. Number of playlists to skip.
1229
     *
1230
     * @return array|object The user's playlists. Type is controlled by the `return_assoc` option.
1231
     */
1232
    public function getMyPlaylists(array|object $options = []): array|object
1233
    {
1234
        $uri = '/v1/me/playlists';
4✔
1235

1236
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1237

1238
        return $this->lastResponse['body'];
4✔
1239
    }
1240

1241
    /**
1242
     * Get the current user’s queue.
1243
     *
1244
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-queue
1245
     *
1246
     * @return array|object The currently playing song and queue. Type is controlled by the `return_assoc` option.
1247
     */
1248
    public function getMyQueue()
1249
    {
1250
        $uri = '/v1/me/player/queue';
4✔
1251

1252
        $this->lastResponse = $this->sendRequest('GET', $uri, []);
4✔
1253

1254
        return $this->lastResponse['body'];
4✔
1255
    }
1256

1257
    /**
1258
      * Get the current user’s recently played tracks.
1259
      * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-recently-played
1260
      *
1261
      * @param array|object $options Optional. Options for the tracks.
1262
      * - int limit Optional. Number of tracks to return.
1263
      * - string after Optional. Unix timestamp in ms (13 digits). Returns all items after this position.
1264
      * - string before Optional. Unix timestamp in ms (13 digits). Returns all items before this position.
1265
      *
1266
      * @return array|object The most recently played tracks. Type is controlled by the `return_assoc` option.
1267
      */
1268
    public function getMyRecentTracks(array|object $options = []): array|object
1269
    {
1270
        $uri = '/v1/me/player/recently-played';
4✔
1271

1272
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1273

1274
        return $this->lastResponse['body'];
4✔
1275
    }
1276

1277
    /**
1278
     * Get the current user’s saved albums.
1279
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-saved-albums
1280
     *
1281
     * @param array|object $options Optional. Options for the albums.
1282
     * - int limit Optional. Number of albums to return.
1283
     * - int offset Optional. Number of albums to skip.
1284
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1285
     *
1286
     * @return array|object The user's saved albums. Type is controlled by the `return_assoc` option.
1287
     */
1288
    public function getMySavedAlbums(array|object $options = []): array|object
1289
    {
1290
        $uri = '/v1/me/albums';
4✔
1291

1292
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1293

1294
        return $this->lastResponse['body'];
4✔
1295
    }
1296

1297
    /**
1298
     * Get the current user’s saved episodes.
1299
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-saved-episodes
1300
     *
1301
     * @param array|object $options Optional. Options for the episodes.
1302
     * - int limit Optional. Number of episodes to return.
1303
     * - int offset Optional. Number of episodes to skip.
1304
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
1305
     *
1306
     * @return array|object The user's saved episodes. Type is controlled by the `return_assoc` option.
1307
     */
1308
    public function getMySavedEpisodes(array|object $options = []): array|object
1309
    {
1310
        $uri = '/v1/me/episodes';
4✔
1311

1312
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1313

1314
        return $this->lastResponse['body'];
4✔
1315
    }
1316

1317
    /**
1318
     * Get the current user’s saved tracks.
1319
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-saved-tracks
1320
     *
1321
     * @param array|object $options Optional. Options for the tracks.
1322
     * - int limit Optional. Limit the number of tracks.
1323
     * - int offset Optional. Number of tracks to skip.
1324
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1325
     *
1326
     * @return array|object The user's saved tracks. Type is controlled by the `return_assoc` option.
1327
     */
1328
    public function getMySavedTracks(array|object $options = []): array|object
1329
    {
1330
        $uri = '/v1/me/tracks';
4✔
1331

1332
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1333

1334
        return $this->lastResponse['body'];
4✔
1335
    }
1336

1337
    /**
1338
     * Get the current user’s saved shows.
1339
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-saved-shows
1340
     *
1341
     * @param array|object $options Optional. Options for the shows.
1342
     * - int limit Optional. Limit the number of shows.
1343
     * - int offset Optional. Number of shows to skip.
1344
     *
1345
     * @return array|object The user's saved shows. Type is controlled by the `return_assoc` option.
1346
     */
1347
    public function getMySavedShows(array|object $options = []): array|object
1348
    {
1349
        $uri = '/v1/me/shows';
4✔
1350

1351
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1352

1353
        return $this->lastResponse['body'];
4✔
1354
    }
1355

1356
    /**
1357
     * Get the current user's top tracks or artists.
1358
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-top-artists-and-tracks
1359
     *
1360
     * @param string $type The type to fetch, either 'artists' or 'tracks'.
1361
     * @param array $options Optional. Options for the results.
1362
     * - int limit Optional. Limit the number of results.
1363
     * - int offset Optional. Number of results to skip.
1364
     * - string time_range Optional. Over what time frame the data is calculated. See Spotify API docs for more info.
1365
     *
1366
     * @return array|object A list of the requested top entity. Type is controlled by the `return_assoc` option.
1367
     */
1368
    public function getMyTop(string $type, array|object $options = []): array|object
1369
    {
1370
        $uri = '/v1/me/top/' . $type;
4✔
1371

1372
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1373

1374
        return $this->lastResponse['body'];
4✔
1375
    }
1376

1377
    /**
1378
     * Get new releases.
1379
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-new-releases
1380
     *
1381
     * @param array|object $options Optional. Options for the items.
1382
     * - string country Optional. ISO 3166-1 alpha-2 country code. Show items relevant to this country.
1383
     * - int limit Optional. Limit the number of items.
1384
     * - int offset Optional. Number of items to skip.
1385
     *
1386
     * @return array|object The new releases. Type is controlled by the `return_assoc` option.
1387
     */
1388
    public function getNewReleases(array|object $options = []): array|object
1389
    {
1390
        $uri = '/v1/browse/new-releases';
4✔
1391

1392
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1393

1394
        return $this->lastResponse['body'];
4✔
1395
    }
1396

1397
    /**
1398
     * Get a specific playlist.
1399
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-playlist
1400
     *
1401
     * @param string $playlistId ID or URI of the playlist.
1402
     * @param array|object $options Optional. Options for the playlist.
1403
     * - string|array fields Optional. A list of fields to return. See Spotify docs for more info.
1404
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1405
     * - string|array additional_types Optional. Types of media to return info about.
1406
     *
1407
     * @return array|object The user's playlist. Type is controlled by the `return_assoc` option.
1408
     */
1409
    public function getPlaylist(string $playlistId, array|object $options = []): array|object
1410
    {
1411
        $options = (array) $options;
4✔
1412

1413
        if (isset($options['fields'])) {
4✔
1414
            $options['fields'] = $this->toCommaString($options['fields']);
4✔
1415
        }
1416

1417
        if (isset($options['additional_types'])) {
4✔
1418
            $options['additional_types'] = $this->toCommaString($options['additional_types']);
×
1419
        }
1420

1421
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
1422

1423
        $uri = '/v1/playlists/' . $playlistId;
4✔
1424

1425
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1426

1427
        return $this->lastResponse['body'];
4✔
1428
    }
1429

1430
    /**
1431
     * Get a playlist's cover image.
1432
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-playlist-cover
1433
     *
1434
     * @param string $playlistId ID or URI of the playlist.
1435
     *
1436
     * @return array|object The playlist cover image. Type is controlled by the `return_assoc` option.
1437
     */
1438
    public function getPlaylistImage(string $playlistId): array|object
1439
    {
1440
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
1441

1442
        $uri = '/v1/playlists/' . $playlistId . '/images';
4✔
1443

1444
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1445

1446
        return $this->lastResponse['body'];
4✔
1447
    }
1448

1449
    /**
1450
     * Get the tracks in a playlist.
1451
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-playlists-tracks
1452
     *
1453
     * @param string $playlistId ID or URI of the playlist.
1454
     * @param array|object $options Optional. Options for the tracks.
1455
     * - string|array fields Optional. A list of fields to return. See Spotify docs for more info.
1456
     * - int limit Optional. Limit the number of tracks.
1457
     * - int offset Optional. Number of tracks to skip.
1458
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1459
     * - string|array additional_types Optional. Types of media to return info about.
1460
     *
1461
     * @return array|object The tracks in the playlist. Type is controlled by the `return_assoc` option.
1462
     */
1463
    public function getPlaylistTracks(string $playlistId, array|object $options = []): array|object
1464
    {
1465
        $options = (array) $options;
4✔
1466

1467
        if (isset($options['fields'])) {
4✔
1468
            $options['fields'] = $this->toCommaString($options['fields']);
4✔
1469
        }
1470

1471
        if (isset($options['additional_types'])) {
4✔
1472
            $options['additional_types'] = $this->toCommaString($options['additional_types']);
4✔
1473
        }
1474

1475
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
1476

1477
        $uri = '/v1/playlists/' . $playlistId . '/tracks';
4✔
1478

1479
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1480

1481
        return $this->lastResponse['body'];
4✔
1482
    }
1483

1484
    /**
1485
     * Get recommendations based on artists, tracks, or genres.
1486
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-recommendations
1487
     *
1488
     * @deprecated See https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api
1489
     *
1490
     * @param array|object $options Optional. Options for the recommendations.
1491
     * - int limit Optional. Limit the number of recommendations.
1492
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1493
     * - mixed max_* Optional. Max value for one of the tunable track attributes.
1494
     * - mixed min_* Optional. Min value for one of the tunable track attributes.
1495
     * - array seed_artists Artist IDs to seed by.
1496
     * - array seed_genres Genres to seed by. Call SpotifyWebAPI::getGenreSeeds() for a complete list.
1497
     * - array seed_tracks Track IDs to seed by.
1498
     * - mixed target_* Optional. Target value for one of the tunable track attributes.
1499
     *
1500
     * @return array|object The requested recommendations. Type is controlled by the `return_assoc` option.
1501
     */
1502
    public function getRecommendations(array|object $options = []): array|object
1503
    {
1504
        $options = (array) $options;
4✔
1505

1506
        array_walk($options, function (&$value, $key) {
4✔
1507
            if (substr($key, 0, 5) == 'seed_') {
4✔
1508
                $value = $this->toCommaString($value);
4✔
1509
            }
1510
        });
4✔
1511

1512
        $uri = '/v1/recommendations';
4✔
1513

1514
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1515

1516
        return $this->lastResponse['body'];
4✔
1517
    }
1518

1519
    /**
1520
     * Get the Request object in use.
1521
     *
1522
     * @return Request The Request object in use.
1523
     */
1524
    public function getRequest(): Request
1525
    {
1526
        return $this->request;
4✔
1527
    }
1528

1529
    /**
1530
     * Get a show.
1531
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-show
1532
     *
1533
     * @param string $showId ID or URI of the show.
1534
     * @param array|object $options Optional. Options for the show.
1535
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to shows available in that market.
1536
     *
1537
     * @return array|object The requested show. Type is controlled by the `return_assoc` option.
1538
     */
1539
    public function getShow(string $showId, array|object $options = []): array|object
1540
    {
1541
        $showId = $this->uriToId($showId, 'show');
4✔
1542
        $uri = '/v1/shows/' . $showId;
4✔
1543

1544
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1545

1546
        return $this->lastResponse['body'];
4✔
1547
    }
1548

1549
    /**
1550
     * Get a show's episodes.
1551
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-a-shows-episodes
1552
     *
1553
     * @param string $showId ID or URI of the album.
1554
     * @param array|object $options Optional. Options for the episodes.
1555
     * - int limit Optional. Limit the number of episodes.
1556
     * - int offset Optional. Number of episodes to skip.
1557
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to episodes available in that market.
1558
     *
1559
     * @return array|object The requested show episodes. Type is controlled by the `return_assoc` option.
1560
     */
1561
    public function getShowEpisodes(string $showId, array|object $options = []): array|object
1562
    {
1563
        $showId = $this->uriToId($showId, 'show');
4✔
1564
        $uri = '/v1/shows/' . $showId . '/episodes';
4✔
1565

1566
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1567

1568
        return $this->lastResponse['body'];
4✔
1569
    }
1570

1571
    /**
1572
     * Get multiple shows.
1573
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-multiple-shows
1574
     *
1575
     * @param string|array $showIds IDs or URIs of the shows.
1576
     * @param array|object $options Optional. Options for the shows.
1577
     * - string market Optional. ISO 3166-1 alpha-2 country code, limit results to shows available in that market.
1578
     *
1579
     * @return array|object The requested shows. Type is controlled by the `return_assoc` option.
1580
     */
1581
    public function getShows(string|array $showIds, array|object $options = []): array|object
1582
    {
1583
        $showIds = $this->uriToId($showIds, 'show');
4✔
1584
        $options = array_merge((array) $options, [
4✔
1585
            'ids' => $this->toCommaString($showIds),
4✔
1586
        ]);
4✔
1587

1588
        $uri = '/v1/shows/';
4✔
1589

1590
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1591

1592
        return $this->lastResponse['body'];
4✔
1593
    }
1594

1595
    /**
1596
     * Get a track.
1597
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-track
1598
     *
1599
     * @param string $trackId ID or URI of the track.
1600
     * @param array|object $options Optional. Options for the track.
1601
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1602
     *
1603
     * @return array|object The requested track. Type is controlled by the `return_assoc` option.
1604
     */
1605
    public function getTrack(string $trackId, array|object $options = []): array|object
1606
    {
1607
        $trackId = $this->uriToId($trackId, 'track');
16✔
1608
        $uri = '/v1/tracks/' . $trackId;
16✔
1609

1610
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
16✔
1611

1612
        return $this->lastResponse['body'];
16✔
1613
    }
1614

1615
    /**
1616
     * Get multiple tracks.
1617
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-several-tracks
1618
     *
1619
     * @param array $trackIds IDs or URIs of the tracks.
1620
     * @param array|object $options Optional. Options for the tracks.
1621
     * - string market Optional. ISO 3166-1 alpha-2 country code, provide this if you wish to apply Track Relinking.
1622
     *
1623
     * @return array|object The requested tracks. Type is controlled by the `return_assoc` option.
1624
     */
1625
    public function getTracks(array $trackIds, array|object $options = []): array|object
1626
    {
1627
        $trackIds = $this->uriToId($trackIds, 'track');
4✔
1628
        $options = array_merge((array) $options, [
4✔
1629
            'ids' => $this->toCommaString($trackIds),
4✔
1630
        ]);
4✔
1631

1632
        $uri = '/v1/tracks/';
4✔
1633

1634
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1635

1636
        return $this->lastResponse['body'];
4✔
1637
    }
1638

1639
    /**
1640
     * Get a user.
1641
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-users-profile
1642
     *
1643
     * @param string $userId ID or URI of the user.
1644
     *
1645
     * @return array|object The requested user. Type is controlled by the `return_assoc` option.
1646
     */
1647
    public function getUser(string $userId): array|object
1648
    {
1649
        $userId = $this->uriToId($userId, 'user');
4✔
1650
        $uri = '/v1/users/' . $userId;
4✔
1651

1652
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1653

1654
        return $this->lastResponse['body'];
4✔
1655
    }
1656

1657
    /**
1658
     * Get the artists followed by the current user.
1659
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-followed
1660
     *
1661
     * @param array|object $options Optional. Options for the artists.
1662
     * - int limit Optional. Limit the number of artists returned.
1663
     * - string after Optional. The last artist ID retrieved from the previous request.
1664
     *
1665
     * @return array|object A list of artists. Type is controlled by the `return_assoc` option.
1666
     */
1667
    public function getUserFollowedArtists(array|object $options = []): array|object
1668
    {
1669
        $options = (array) $options;
4✔
1670

1671
        if (!isset($options['type'])) {
4✔
1672
            $options['type'] = 'artist'; // Undocumented until more values are supported.
4✔
1673
        }
1674

1675
        $uri = '/v1/me/following';
4✔
1676

1677
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1678

1679
        return $this->lastResponse['body'];
4✔
1680
    }
1681

1682
    /**
1683
     * Get a user's playlists.
1684
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-list-users-playlists
1685
     *
1686
     * @param string $userId ID or URI of the user.
1687
     * @param array|object $options Optional. Options for the tracks.
1688
     * - int limit Optional. Limit the number of tracks.
1689
     * - int offset Optional. Number of tracks to skip.
1690
     *
1691
     * @return array|object The user's playlists. Type is controlled by the `return_assoc` option.
1692
     */
1693
    public function getUserPlaylists(string $userId, array|object $options = []): array|object
1694
    {
1695
        $userId = $this->uriToId($userId, 'user');
4✔
1696
        $uri = '/v1/users/' . $userId . '/playlists';
4✔
1697

1698
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1699

1700
        return $this->lastResponse['body'];
4✔
1701
    }
1702

1703
    /**
1704
     * Get the currently authenticated user.
1705
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile
1706
     *
1707
     * @return array|object The currently authenticated user. Type is controlled by the `return_assoc` option.
1708
     */
1709
    public function me(): array|object
1710
    {
1711
        $uri = '/v1/me';
4✔
1712

1713
        $this->lastResponse = $this->sendRequest('GET', $uri);
4✔
1714

1715
        return $this->lastResponse['body'];
4✔
1716
    }
1717

1718
    /**
1719
     * Check if albums are saved in the current user's Spotify library.
1720
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-users-saved-albums
1721
     *
1722
     * @param string|array $albums Album IDs or URIs to check for.
1723
     *
1724
     * @return array Whether each album is saved.
1725
     */
1726
    public function myAlbumsContains(string|array $albums): array
1727
    {
1728
        $albums = $this->uriToId($albums, 'album');
4✔
1729
        $albums = $this->toCommaString($albums);
4✔
1730

1731
        $options = [
4✔
1732
            'ids' => $albums,
4✔
1733
        ];
4✔
1734

1735
        $uri = '/v1/me/albums/contains';
4✔
1736

1737
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1738

1739
        return $this->lastResponse['body'];
4✔
1740
    }
1741

1742
    /**
1743
     * Check if episodes are saved in the current user's Spotify library.
1744
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-users-saved-episodes
1745
     *
1746
     * @param string|array $episodes Episode IDs or URIs to check for.
1747
     *
1748
     * @return array Whether each episode is saved.
1749
     */
1750
    public function myEpisodesContains(string|array $episodes): array
1751
    {
1752
        $episodes = $this->uriToId($episodes, 'episode');
4✔
1753
        $episodes = $this->toCommaString($episodes);
4✔
1754

1755
        $options = [
4✔
1756
            'ids' => $episodes,
4✔
1757
        ];
4✔
1758

1759
        $uri = '/v1/me/episodes/contains';
4✔
1760

1761
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1762

1763
        return $this->lastResponse['body'];
4✔
1764
    }
1765

1766
    /**
1767
     * Check if shows are saved in the current user's Spotify library.
1768
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-users-saved-shows
1769
     *
1770
     * @param string|array $shows Show IDs or URIs to check for.
1771
     *
1772
     * @return array Whether each show is saved.
1773
     */
1774
    public function myShowsContains(string|array $shows): array
1775
    {
1776
        $shows = $this->uriToId($shows, 'show');
4✔
1777
        $shows = $this->toCommaString($shows);
4✔
1778

1779
        $options = [
4✔
1780
            'ids' => $shows,
4✔
1781
        ];
4✔
1782

1783
        $uri = '/v1/me/shows/contains';
4✔
1784

1785
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1786

1787
        return $this->lastResponse['body'];
4✔
1788
    }
1789

1790
    /**
1791
     * Check if tracks are saved in the current user's Spotify library.
1792
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-users-saved-tracks
1793
     *
1794
     * @param string|array $tracks Track IDs or URIs to check for.
1795
     *
1796
     * @return array Whether each track is saved.
1797
     */
1798
    public function myTracksContains(string|array $tracks): array
1799
    {
1800
        $tracks = $this->uriToId($tracks, 'track');
4✔
1801
        $tracks = $this->toCommaString($tracks);
4✔
1802

1803
        $options = [
4✔
1804
            'ids' => $tracks,
4✔
1805
        ];
4✔
1806

1807
        $uri = '/v1/me/tracks/contains';
4✔
1808

1809
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
1810

1811
        return $this->lastResponse['body'];
4✔
1812
    }
1813

1814
    /**
1815
     * Play the next track in the current users's queue.
1816
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/skip-users-playback-to-next-track
1817
     *
1818
     * @param string $deviceId Optional. ID of the device to target.
1819
     *
1820
     * @return bool Whether the track was successfully skipped.
1821
     */
1822
    public function next(string $deviceId = ''): bool
1823
    {
1824
        $uri = '/v1/me/player/next';
4✔
1825

1826
        // We need to manually append data to the URI since it's a POST request
1827
        if ($deviceId) {
4✔
1828
            $uri = $uri . '?device_id=' . $deviceId;
4✔
1829
        }
1830

1831
        $this->lastResponse = $this->sendRequest('POST', $uri);
4✔
1832

1833
        return $this->lastResponse['status'] == 204;
4✔
1834
    }
1835

1836
    /**
1837
     * Pause playback for the current user.
1838
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/pause-a-users-playback
1839
     *
1840
     * @param string $deviceId Optional. ID of the device to pause on.
1841
     *
1842
     * @return bool Whether the playback was successfully paused.
1843
     */
1844
    public function pause(string $deviceId = ''): bool
1845
    {
1846
        $uri = '/v1/me/player/pause';
4✔
1847

1848
        // We need to manually append data to the URI since it's a PUT request
1849
        if ($deviceId) {
4✔
1850
            $uri = $uri . '?device_id=' . $deviceId;
4✔
1851
        }
1852

1853
        $this->lastResponse = $this->sendRequest('PUT', $uri);
4✔
1854

1855
        return $this->lastResponse['status'] == 204;
4✔
1856
    }
1857

1858
    /**
1859
     * Start playback for the current user.
1860
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/start-a-users-playback
1861
     *
1862
     * @param string $deviceId Optional. ID of the device to play on.
1863
     * @param array|object $options Optional. Options for the playback.
1864
     * - string context_uri Optional. URI of the context to play, for example an album.
1865
     * - array uris Optional. Spotify track URIs to play.
1866
     * - object offset Optional. Indicates from where in the context playback should start.
1867
     * - int position_ms. Optional. Indicates the position to start playback from.
1868
     *
1869
     * @return bool Whether the playback was successfully started.
1870
     */
1871
    public function play(string $deviceId = '', array|object $options = []): bool
1872
    {
1873
        $options = $options ? json_encode($options) : '';
4✔
1874

1875
        $headers = [
4✔
1876
            'Content-Type' => 'application/json',
4✔
1877
        ];
4✔
1878

1879
        $uri = '/v1/me/player/play';
4✔
1880

1881
        // We need to manually append data to the URI since it's a PUT request
1882
        if ($deviceId) {
4✔
1883
            $uri = $uri . '?device_id=' . $deviceId;
4✔
1884
        }
1885

1886
        $this->lastResponse = $this->sendRequest('PUT', $uri, $options, $headers);
4✔
1887

1888
        return $this->lastResponse['status'] == 204;
4✔
1889
    }
1890

1891
    /**
1892
     * Play the previous track in the current users's queue.
1893
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/skip-users-playback-to-previous-track
1894
     *
1895
     * @param string $deviceId Optional. ID of the device to target.
1896
     *
1897
     * @return bool Whether the track was successfully skipped.
1898
     */
1899
    public function previous(string $deviceId = ''): bool
1900
    {
1901
        $uri = '/v1/me/player/previous';
4✔
1902

1903
        // We need to manually append data to the URI since it's a POST request
1904
        if ($deviceId) {
4✔
1905
            $uri = $uri . '?device_id=' . $deviceId;
4✔
1906
        }
1907

1908
        $this->lastResponse = $this->sendRequest('POST', $uri);
4✔
1909

1910
        return $this->lastResponse['status'] == 204;
4✔
1911
    }
1912

1913
    /**
1914
     * Add an item to the queue.
1915
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/add-to-queue
1916
     *
1917
     * @param string $trackUri Required. Track ID, track URI or episode URI to queue.
1918
     * @param string $deviceId Optional. ID of the device to target.
1919
     *
1920
     * @return bool Whether the track was successfully queued.
1921
     */
1922
    public function queue(string $trackUri, string $deviceId = ''): bool
1923
    {
1924
        $uri = '/v1/me/player/queue?uri=' . $this->idToUri($trackUri, 'track');
8✔
1925

1926
        // We need to manually append data to the URI since it's a POST request
1927
        if ($deviceId) {
8✔
1928
            $uri = $uri . '&device_id=' . $deviceId;
8✔
1929
        }
1930

1931
        $this->lastResponse = $this->sendRequest('POST', $uri);
8✔
1932

1933
        return $this->lastResponse['status'] == 204;
8✔
1934
    }
1935

1936
    /**
1937
     * Reorder the tracks in a playlist.
1938
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/reorder-or-replace-playlists-tracks
1939
     *
1940
     * @param string $playlistId ID or URI of the playlist.
1941
     * @param array|object $options Options for the new tracks.
1942
     * - int range_start Required. Position of the first track to be reordered.
1943
     * - int range_length Optional. The amount of tracks to be reordered.
1944
     * - int insert_before Required. Position where the tracks should be inserted.
1945
     * - string snapshot_id Optional. The playlist's snapshot ID.
1946
     *
1947
     * @return string|bool A new snapshot ID or false if the tracks weren't successfully reordered.
1948
     */
1949
    public function reorderPlaylistTracks(string $playlistId, array|object $options): string|bool
1950
    {
1951
        $options = json_encode($options);
8✔
1952

1953
        $headers = [
8✔
1954
            'Content-Type' => 'application/json',
8✔
1955
        ];
8✔
1956

1957
        $playlistId = $this->uriToId($playlistId, 'playlist');
8✔
1958

1959
        $uri = '/v1/playlists/' . $playlistId . '/tracks';
8✔
1960

1961
        $this->lastResponse = $this->sendRequest('PUT', $uri, $options, $headers);
8✔
1962

1963
        return $this->getSnapshotId($this->lastResponse['body']);
8✔
1964
    }
1965

1966
    /**
1967
     * Set repeat mode for the current user’s playback.
1968
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/set-repeat-mode-on-users-playback
1969
     *
1970
     * @param array|object $options Optional. Options for the playback repeat mode.
1971
     * - string state Required. The repeat mode. See Spotify docs for possible values.
1972
     * - string device_id Optional. ID of the device to target.
1973
     *
1974
     * @return bool Whether the playback repeat mode was successfully changed.
1975
     */
1976
    public function repeat(array|object $options): bool
1977
    {
1978
        $options = http_build_query($options, '', '&');
4✔
1979

1980
        // We need to manually append data to the URI since it's a PUT request
1981
        $uri = '/v1/me/player/repeat?' . $options;
4✔
1982

1983
        $this->lastResponse = $this->sendRequest('PUT', $uri);
4✔
1984

1985
        return $this->lastResponse['status'] == 204;
4✔
1986
    }
1987

1988
    /**
1989
     * Replace all tracks in a playlist with new ones.
1990
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/reorder-or-replace-playlists-tracks
1991
     *
1992
     * @param string $playlistId ID or URI of the playlist.
1993
     * @param string|array $tracks IDs, track URIs, or episode URIs to replace with.
1994
     *
1995
     * @return bool Whether the tracks was successfully replaced.
1996
     */
1997
    public function replacePlaylistTracks(string $playlistId, string|array $tracks): bool
1998
    {
1999
        $tracks = $this->idToUri($tracks, 'track');
4✔
2000
        $tracks = json_encode([
4✔
2001
            'uris' => (array) $tracks,
4✔
2002
        ]);
4✔
2003

2004
        $headers = [
4✔
2005
            'Content-Type' => 'application/json',
4✔
2006
        ];
4✔
2007

2008
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
2009

2010
        $uri = '/v1/playlists/' . $playlistId . '/tracks';
4✔
2011

2012
        $this->lastResponse = $this->sendRequest('PUT', $uri, $tracks, $headers);
4✔
2013

2014
        return $this->lastResponse['status'] == 200;
4✔
2015
    }
2016

2017
    /**
2018
     * Search for an item.
2019
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/search
2020
     *
2021
     * @param string $query The term to search for.
2022
     * @param string|array $type The type of item to search for.
2023
     * @param array|object $options Optional. Options for the search.
2024
     * - string market Optional. Limit the results to items that are playable in this market, for example SE.
2025
     * - int limit Optional. Limit the number of items.
2026
     * - int offset Optional. Number of items to skip.
2027
     * - string include_external Optional. Whether or not to mark externally hosted content as playable.
2028
     *
2029
     * @return array|object The search results. Type is controlled by the `return_assoc` option.
2030
     */
2031
    public function search(string $query, string|array $type, array|object $options = []): array|object
2032
    {
2033
        $options = array_merge((array) $options, [
4✔
2034
            'q' => $query,
4✔
2035
            'type' => $this->toCommaString($type),
4✔
2036
        ]);
4✔
2037

2038
        $uri = '/v1/search';
4✔
2039

2040
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
2041

2042
        return $this->lastResponse['body'];
4✔
2043
    }
2044

2045
    /**
2046
     * Change playback position for the current user.
2047
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/seek-to-position-in-currently-playing-track
2048
     *
2049
     * @param array|object $options Optional. Options for the playback seeking.
2050
     * - string position_ms Required. The position in milliseconds to seek to.
2051
     * - string device_id Optional. ID of the device to target.
2052
     *
2053
     * @return bool Whether the playback position was successfully changed.
2054
     */
2055
    public function seek(array|object $options): bool
2056
    {
2057
        $options = http_build_query($options, '', '&');
4✔
2058

2059
        // We need to manually append data to the URI since it's a PUT request
2060
        $uri = '/v1/me/player/seek?' . $options;
4✔
2061

2062
        $this->lastResponse = $this->sendRequest('PUT', $uri);
4✔
2063

2064
        return $this->lastResponse['status'] == 204;
4✔
2065
    }
2066

2067
    /**
2068
     * Set the access token to use.
2069
     *
2070
     * @param string $accessToken The access token.
2071
     *
2072
     * @return self
2073
     */
2074
    public function setAccessToken(string $accessToken): self
2075
    {
2076
        $this->accessToken = $accessToken;
8✔
2077

2078
        return $this;
8✔
2079
    }
2080

2081
    /**
2082
     * Set options
2083
     *
2084
     * @param array|object $options Options to set.
2085
     *
2086
     * @return self
2087
     */
2088
    public function setOptions(array|object $options): self
2089
    {
2090
        $this->options = array_merge($this->options, (array) $options);
396✔
2091

2092
        return $this;
396✔
2093
    }
2094

2095
    /**
2096
     * Set the Session object to use.
2097
     *
2098
     * @param Session $session The Session object.
2099
     *
2100
     * @return self
2101
     */
2102
    public function setSession(?Session $session): self
2103
    {
2104
        $this->session = $session;
396✔
2105

2106
        return $this;
396✔
2107
    }
2108

2109
    /**
2110
     * Set shuffle mode for the current user’s playback.
2111
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/toggle-shuffle-for-users-playback
2112
     *
2113
     * @param array|object $options Optional. Options for the playback shuffle mode.
2114
     * - bool state Required. The shuffle mode. See Spotify docs for possible values.
2115
     * - string device_id Optional. ID of the device to target.
2116
     *
2117
     * @return bool Whether the playback shuffle mode was successfully changed.
2118
     */
2119
    public function shuffle(array|object $options): bool
2120
    {
2121
        $options = array_merge((array) $options, [
4✔
2122
            'state' => $options['state'] ? 'true' : 'false',
4✔
2123
        ]);
4✔
2124

2125
        $options = http_build_query($options, '', '&');
4✔
2126

2127
        // We need to manually append data to the URI since it's a PUT request
2128
        $uri = '/v1/me/player/shuffle?' . $options;
4✔
2129

2130
        $this->lastResponse = $this->sendRequest('PUT', $uri);
4✔
2131

2132
        return $this->lastResponse['status'] == 204;
4✔
2133
    }
2134

2135
    /**
2136
     * Remove the current user as a follower of one or more artists or other Spotify users.
2137
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/unfollow-artists-users
2138
     *
2139
     * @param string $type The type to check: either 'artist' or 'user'.
2140
     * @param string|array $ids IDs or URIs of the users or artists to unfollow.
2141
     *
2142
     * @return bool Whether the artists or users were successfully unfollowed.
2143
     */
2144
    public function unfollowArtistsOrUsers(string $type, string|array $ids): bool
2145
    {
2146
        $ids = $this->uriToId($ids, $type);
4✔
2147
        $ids = json_encode([
4✔
2148
            'ids' => (array) $ids,
4✔
2149
        ]);
4✔
2150

2151
        $headers = [
4✔
2152
            'Content-Type' => 'application/json',
4✔
2153
        ];
4✔
2154

2155
        // We need to manually append data to the URI since it's a DELETE request
2156
        $uri = '/v1/me/following?type=' . $type;
4✔
2157

2158
        $this->lastResponse = $this->sendRequest('DELETE', $uri, $ids, $headers);
4✔
2159

2160
        return $this->lastResponse['status'] == 204;
4✔
2161
    }
2162

2163
    /**
2164
     * Remove the current user as a follower of a playlist.
2165
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/unfollow-playlist
2166
     *
2167
     * @param string $playlistId ID or URI of the playlist to unfollow.
2168
     *
2169
     * @return bool Whether the playlist was successfully unfollowed.
2170
     */
2171
    public function unfollowPlaylist(string $playlistId): bool
2172
    {
2173
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
2174
        $uri = '/v1/playlists/' . $playlistId . '/followers';
4✔
2175

2176
        $this->lastResponse = $this->sendRequest('DELETE', $uri);
4✔
2177

2178
        return $this->lastResponse['status'] == 200;
4✔
2179
    }
2180

2181
    /**
2182
     * Update the details of a playlist.
2183
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/change-playlist-details
2184
     *
2185
     * @param string $playlistId ID or URI of the playlist to update.
2186
     * @param array|object $options Options for the playlist.
2187
     * - bool collaborative Optional. Whether the playlist should be collaborative or not.
2188
     * - string description Optional. Description of the playlist.
2189
     * - string name Optional. Name of the playlist.
2190
     * - bool public Optional. Whether the playlist should be public or not.
2191
     *
2192
     * @return bool Whether the playlist was successfully updated.
2193
     */
2194
    public function updatePlaylist(string $playlistId, array|object $options): bool
2195
    {
2196
        $options = json_encode($options);
4✔
2197

2198
        $headers = [
4✔
2199
            'Content-Type' => 'application/json',
4✔
2200
        ];
4✔
2201

2202
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
2203

2204
        $uri = '/v1/playlists/' . $playlistId;
4✔
2205

2206
        $this->lastResponse = $this->sendRequest('PUT', $uri, $options, $headers);
4✔
2207

2208
        return $this->lastResponse['status'] == 200;
4✔
2209
    }
2210

2211
    /**
2212
     * Update the image of a playlist.
2213
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/upload-custom-playlist-cover
2214
     *
2215
     * @param string $playlistId ID or URI of the playlist to update.
2216
     * @param string $imageData Base64 encoded JPEG image data, maximum 256 KB in size.
2217
     *
2218
     * @return bool Whether the playlist was successfully updated.
2219
     */
2220
    public function updatePlaylistImage(string $playlistId, string $imageData): bool
2221
    {
2222
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
2223

2224
        $uri = '/v1/playlists/' . $playlistId . '/images';
4✔
2225

2226
        $this->lastResponse = $this->sendRequest('PUT', $uri, $imageData);
4✔
2227

2228
        return $this->lastResponse['status'] == 202;
4✔
2229
    }
2230

2231
    /**
2232
     * Check if a set of users are following a playlist.
2233
     * https://developer.spotify.com/documentation/web-api/reference/#/operations/check-if-user-follows-playlist
2234
     *
2235
     * @param string $playlistId ID or URI of the playlist.
2236
     * @param array|object $options Options for the check.
2237
     * - ids string|array Required. IDs or URIs of the users to check for.
2238
     *
2239
     * @return array Whether each user is following the playlist.
2240
     */
2241
    public function usersFollowPlaylist(string $playlistId, array|object $options): array
2242
    {
2243
        $options = (array) $options;
4✔
2244

2245
        if (isset($options['ids'])) {
4✔
2246
            $options['ids'] = $this->uriToId($options['ids'], 'user');
4✔
2247
            $options['ids'] = $this->toCommaString($options['ids']);
4✔
2248
        }
2249

2250
        $playlistId = $this->uriToId($playlistId, 'playlist');
4✔
2251

2252
        $uri = '/v1/playlists/' . $playlistId . '/followers/contains';
4✔
2253

2254
        $this->lastResponse = $this->sendRequest('GET', $uri, $options);
4✔
2255

2256
        return $this->lastResponse['body'];
4✔
2257
    }
2258
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc