1 | <?php |
||||
2 | |||||
3 | namespace App\Services; |
||||
4 | |||||
5 | use App\Models\Album; |
||||
6 | use App\Models\Artist; |
||||
7 | use App\Models\Playlist; |
||||
8 | use App\Models\Song; |
||||
9 | use App\Models\SongZipArchive; |
||||
10 | use Illuminate\Database\Eloquent\Collection; |
||||
11 | use InvalidArgumentException; |
||||
12 | |||||
13 | class DownloadService |
||||
14 | { |
||||
15 | private $s3Service; |
||||
16 | |||||
17 | 2 | public function __construct(S3Service $s3Service) |
|||
18 | { |
||||
19 | 2 | $this->s3Service = $s3Service; |
|||
20 | 2 | } |
|||
21 | |||||
22 | /** |
||||
23 | * Generic method to generate a download archive from various source types. |
||||
24 | * |
||||
25 | * @param Song|Collection|Album|Artist|Playlist $mixed |
||||
26 | * |
||||
27 | * @throws InvalidArgumentException |
||||
28 | * |
||||
29 | * @return string Full path to the generated archive |
||||
30 | */ |
||||
31 | public function from($mixed): string |
||||
32 | { |
||||
33 | switch (get_class($mixed)) { |
||||
34 | case Song::class: |
||||
35 | return $this->fromSong($mixed); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
36 | case Collection::class: |
||||
37 | return $this->fromMultipleSongs($mixed); |
||||
0 ignored issues
–
show
It seems like
$mixed can also be of type App\Models\Album and App\Models\Artist and App\Models\Playlist and App\Models\Song ; however, parameter $songs of App\Services\DownloadService::fromMultipleSongs() does only seem to accept Illuminate\Database\Eloquent\Collection , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
38 | case Album::class: |
||||
39 | return $this->fromAlbum($mixed); |
||||
0 ignored issues
–
show
It seems like
$mixed can also be of type App\Models\Artist and App\Models\Playlist and App\Models\Song and Illuminate\Database\Eloquent\Collection ; however, parameter $album of App\Services\DownloadService::fromAlbum() does only seem to accept App\Models\Album , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
40 | case Artist::class: |
||||
41 | return $this->fromArtist($mixed); |
||||
0 ignored issues
–
show
It seems like
$mixed can also be of type App\Models\Album and App\Models\Playlist and App\Models\Song and Illuminate\Database\Eloquent\Collection ; however, parameter $artist of App\Services\DownloadService::fromArtist() does only seem to accept App\Models\Artist , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
42 | case Playlist::class: |
||||
43 | return $this->fromPlaylist($mixed); |
||||
0 ignored issues
–
show
It seems like
$mixed can also be of type App\Models\Album and App\Models\Artist and App\Models\Song and Illuminate\Database\Eloquent\Collection ; however, parameter $playlist of App\Services\DownloadService::fromPlaylist() does only seem to accept App\Models\Playlist , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
44 | } |
||||
45 | |||||
46 | throw new InvalidArgumentException('Unsupported download type.'); |
||||
47 | } |
||||
48 | |||||
49 | 2 | public function fromSong(Song $song): string |
|||
50 | { |
||||
51 | 2 | if ($s3Params = $song->s3_params) { |
|||
52 | // The song is hosted on Amazon S3. |
||||
53 | // We download it back to our local server first. |
||||
54 | $url = $this->s3Service->getSongPublicUrl($song); |
||||
55 | abort_unless($url, 404); |
||||
0 ignored issues
–
show
$url of type string is incompatible with the type boolean expected by parameter $boolean of abort_unless() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
56 | |||||
57 | $localPath = sys_get_temp_dir().DIRECTORY_SEPARATOR.basename($s3Params['key']); |
||||
58 | |||||
59 | // The following function requires allow_url_fopen to be ON. |
||||
60 | // We're just assuming that to be the case here. |
||||
61 | copy($url, $localPath); |
||||
62 | } else { |
||||
63 | // The song is hosted locally. Make sure the file exists. |
||||
64 | 2 | $localPath = $song->path; |
|||
65 | 2 | abort_unless(file_exists($localPath), 404); |
|||
66 | } |
||||
67 | |||||
68 | 2 | return $localPath; |
|||
69 | } |
||||
70 | |||||
71 | protected function fromMultipleSongs(Collection $songs): string |
||||
72 | { |
||||
73 | if ($songs->count() === 1) { |
||||
74 | return $this->fromSong($songs->first()); |
||||
75 | } |
||||
76 | |||||
77 | return (new SongZipArchive()) |
||||
78 | ->addSongs($songs) |
||||
79 | ->finish() |
||||
80 | ->getPath(); |
||||
81 | } |
||||
82 | |||||
83 | protected function fromPlaylist(Playlist $playlist): string |
||||
84 | { |
||||
85 | return $this->fromMultipleSongs($playlist->songs); |
||||
86 | } |
||||
87 | |||||
88 | protected function fromAlbum(Album $album): string |
||||
89 | { |
||||
90 | return $this->fromMultipleSongs($album->songs); |
||||
91 | } |
||||
92 | |||||
93 | protected function fromArtist(Artist $artist): string |
||||
94 | { |
||||
95 | return $this->fromMultipleSongs($artist->songs); |
||||
0 ignored issues
–
show
$artist->songs of type App\Models\Song is incompatible with the type Illuminate\Database\Eloquent\Collection expected by parameter $songs of App\Services\DownloadService::fromMultipleSongs() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
96 | } |
||||
97 | } |
||||
98 |