public function sync($tags, $force = false)
{
// If the file is not new or changed and we're not forcing update, don't do anything.
if (!$this->isNewOrChanged() && !$force) {
return true;
}
// If the file is invalid, don't do anything.
if (!($info = $this->getInfo())) {
return false;
}
// Fixes #366. If the file is new, we use all tags by simply setting $force to false.
if ($this->isNew()) {
$force = false;
}
$artist = null;
if ($this->isChanged() || $force) {
// This is a changed file, or the user is forcing updates.
// In such a case, the user must have specified a list of tags to sync.
// A sample command could be: ./artisan koel:sync --force --tags=artist,album,lyrics
// We cater for these tags by removing those not specified.
// There's a special case with 'album' though.
// If 'compilation' tag is specified, 'album' must be counted in as well.
// But if 'album' isn't specified, we don't want to update normal albums.
// This variable is to keep track of this state.
$changeCompilationAlbumOnly = false;
if (in_array('compilation', $tags, true) && !in_array('album', $tags, true)) {
$tags[] = 'album';
$changeCompilationAlbumOnly = true;
}
$info = array_intersect_key($info, array_flip($tags));
// If the "artist" tag is specified, use it.
// Otherwise, re-use the existing model value.
$artist = isset($info['artist']) ? Artist::get($info['artist']) : $this->song->album->artist;
$isCompilation = (bool) array_get($info, 'compilation');
// If the "album" tag is specified, use it.
// Otherwise, re-use the existing model value.
if (isset($info['album'])) {
$album = $changeCompilationAlbumOnly ? $this->song->album : Album::get($artist, $info['album'], $isCompilation);
} else {
$album = $this->song->album;
}
} else {
// The file is newly added.
$isCompilation = (bool) array_get($info, 'compilation');
$artist = Artist::get($info['artist']);
$album = Album::get($artist, $info['album'], $isCompilation);
}
if (!$album->has_cover) {
// If the album has no cover, we try to get the cover image from existing tag data
if (!empty($info['cover'])) {
try {
$album->generateCover($info['cover']);
} catch (Exception $e) {
Log::error($e);
}
} elseif ($cover = $this->getCoverFileUnderSameDirectory()) {
$album->copyCoverFile($cover);
}
}
$info['album_id'] = $album->id;
// If the song is part of a compilation, make sure we properly set its
// artist and contributing artist attributes.
if ($isCompilation) {
$info['contributing_artist_id'] = $artist->id;
}
// Remove these values from the info array, so that we can just use the array as model's input data.
array_forget($info, ['artist', 'albumartist', 'album', 'cover', 'compilation']);
return Song::updateOrCreate(['id' => $this->hash], $info);
}