/** * 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(config('koel.sync.timeout')); } $path = $path ?: Setting::get('media_path'); $this->setTags($tags); $results = ['good' => [], 'bad' => [], 'ugly' => []]; $getID3 = new getID3(); $files = $this->gatherFiles($path); if ($syncCommand) { $syncCommand->createProgressBar(count($files)); } foreach ($files 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->updateProgressBar(); $syncCommand->logToConsole($file->getPath(), $song, $file->getSyncError()); } } // 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()); }