app\models\File::sync PHP Method

sync() public method

Sync the song with all available media info against the database.
public sync ( array $tags, boolean $force = false ) : boolean | Song
$tags array The (selective) tags to sync (if the song exists)
$force boolean Whether to force syncing, even if the file is unchanged
return boolean | Song A Song object on success, true if file exists but is unmodified, or false on an error.
    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);
    }

Usage Example

Exemplo n.º 1
0
 /**
  * Sync the media. Oh sync the media.
  *
  * @param string|null $path
  * @param array       $tags        The tags to sync.
  *                                 Only taken into account for existing records.
  *                                 New records will have all tags synced in regardless.
  * @param bool        $force       Whether to force syncing even unchanged files
  * @param SyncMedia   $syncCommand The SyncMedia command object, to log to console if executed by artisan.
  */
 public function sync($path = null, $tags = [], $force = false, SyncMedia $syncCommand = null)
 {
     if (!app()->runningInConsole()) {
         set_time_limit(env('APP_MAX_SCAN_TIME', 600));
     }
     $path = $path ?: Setting::get('media_path');
     $this->setTags($tags);
     $results = ['good' => [], 'bad' => [], 'ugly' => []];
     $getID3 = new getID3();
     foreach ($this->gatherFiles($path) as $file) {
         $file = new File($file, $getID3);
         $song = $file->sync($this->tags, $force);
         if ($song === true) {
             $results['ugly'][] = $file;
         } elseif ($song === false) {
             $results['bad'][] = $file;
         } else {
             $results['good'][] = $file;
         }
         if ($syncCommand) {
             $syncCommand->logToConsole($file->getPath(), $song);
         }
     }
     // Delete non-existing songs.
     $hashes = array_map(function ($f) {
         return self::getHash($f->getPath());
     }, array_merge($results['ugly'], $results['good']));
     Song::whereNotIn('id', $hashes)->delete();
     // Trigger LibraryChanged, so that TidyLibrary handler is fired to, erm, tidy our library.
     event(new LibraryChanged());
 }
All Usage Examples Of app\models\File::sync