koel/app/Services/SongService.php

123 lines
3.8 KiB
PHP
Raw Normal View History

2022-06-10 10:47:46 +00:00
<?php
namespace App\Services;
use App\Events\LibraryChanged;
2022-06-10 10:47:46 +00:00
use App\Models\Album;
use App\Models\Artist;
use App\Models\Song;
use App\Repositories\SongRepository;
use App\Values\SongUpdateData;
use Illuminate\Support\Arr;
2022-06-10 10:47:46 +00:00
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Psr\Log\LoggerInterface;
use Throwable;
2022-06-10 10:47:46 +00:00
class SongService
{
public function __construct(private SongRepository $songRepository, private LoggerInterface $logger)
2022-06-10 10:47:46 +00:00
{
}
/** @return Collection|array<array-key, Song> */
public function updateSongs(array $songIds, SongUpdateData $data): Collection
{
$updatedSongs = collect();
DB::transaction(function () use ($songIds, $data, $updatedSongs): void {
foreach ($songIds as $id) {
/** @var Song|null $song */
$song = Song::with('album', 'album.artist', 'artist')->find($id);
2022-07-29 06:47:10 +00:00
if ($song) {
$updatedSongs->push($this->updateSong($song, $data));
2022-06-10 10:47:46 +00:00
}
}
});
return $updatedSongs;
}
private function updateSong(Song $song, SongUpdateData $data): Song
{
$maybeSetAlbumArtist = static function (Album $album) use ($data): void {
if ($data->albumArtistName) {
$album->artist_id = Artist::getOrCreate($data->albumArtistName)->id;
2022-07-06 16:08:55 +00:00
$album->save();
}
};
$maybeSetAlbum = static function () use ($data, $song, $maybeSetAlbumArtist): void {
if ($data->albumName) {
$album = Album::getOrCreate($song->artist, $data->albumName);
$song->album_id = $album->id;
2022-07-06 16:08:55 +00:00
$maybeSetAlbumArtist($album);
}
};
// if album artist name is provided, get/create an album with that artist and assign it to the song
if ($data->albumArtistName) {
$album = Album::getOrCreate(Artist::getOrCreate($data->albumArtistName), $data->albumName);
$song->album_id = $album->id;
} else {
$maybeSetAlbum();
}
2022-06-10 10:47:46 +00:00
if ($data->artistName) {
$artist = Artist::getOrCreate($data->artistName);
$song->artist_id = $artist->id;
2022-07-06 16:08:55 +00:00
} else {
$maybeSetAlbum();
2022-06-10 10:47:46 +00:00
}
// For string attributes like title, lyrics, and genre, we use "??" because empty strings still have effects
$song->title = $data->title ?? $song->title;
$song->lyrics = $data->lyrics ?? $song->lyrics;
$song->genre = $data->genre ?? $song->genre;
2022-06-10 10:47:46 +00:00
$song->track = $data->track ?: $song->track;
$song->year = $data->year ?: $song->year;
2022-06-10 10:47:46 +00:00
$song->disc = $data->disc ?: $song->disc;
$song->push();
2022-06-10 10:47:46 +00:00
return $this->songRepository->getOne($song->id);
}
/**
* @param array<string>|string $ids
*/
public function deleteSongs(array|string $ids): void
{
$ids = Arr::wrap($ids);
DB::transaction(function () use ($ids): void {
$shouldBackUp = config('koel.backup_on_delete');
/** @var Collection|array<array-key, Song> $songs */
$songs = Song::query()->findMany($ids);
Song::destroy($ids);
$songs->each(function (Song $song) use ($shouldBackUp): void {
try {
if ($shouldBackUp) {
rename($song->path, $song->path . '.bak');
} else {
unlink($song->path);
}
} catch (Throwable $e) {
$this->logger->error('Failed to remove song file', [
'path' => $song->path,
'exception' => $e,
]);
}
});
event(new LibraryChanged());
});
}
2022-06-10 10:47:46 +00:00
}