diff --git a/app/Album.php b/app/Album.php index 26858b76..f72ee9ca 100644 --- a/app/Album.php +++ b/app/Album.php @@ -23,19 +23,17 @@ namespace Poniverse\Ponyfm; use Exception; use Helpers; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Bus\DispatchesJobs; use Auth; use Cache; -use File; +use Poniverse\Ponyfm\Traits\TrackCollection; use URL; -use Poniverse\Ponyfm\Jobs\EncodeTrackFile; use Poniverse\Ponyfm\Traits\SlugTrait; class Album extends Model { - use SoftDeletes, SlugTrait, DispatchesJobs; + use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection; protected $dates = ['deleted_at']; @@ -85,6 +83,10 @@ class Album extends Model return $this->hasMany('Poniverse\Ponyfm\Track')->orderBy('track_number', 'asc'); } + public function trackFiles() { + return $this->hasManyThrough(TrackFile::class, Track::class, 'album_id', 'track_id'); + } + public function comments() { return $this->hasMany('Poniverse\Ponyfm\Comment')->orderBy('created_at', 'desc'); @@ -277,68 +279,6 @@ class Album extends Model } } - public function countDownloadableTracks() - { - $trackCount = 0; - - foreach ($this->tracks as $track) { - if ($track->is_downloadable == true) { - $trackCount++; - } else { - continue; - } - } - - return $trackCount; - } - - public function countCachedTrackFiles($format) - { - $cachedCount = 0; - - foreach ($this->tracks as $track) { - /** @var $track Track */ - - - if ($track->is_downloadable == false) { - continue; - } - - try { - $trackFile = $track->trackFiles()->where('format', $format)->firstOrFail(); - } catch (ModelNotFoundException $e) { - throw $e; - } - - if ($trackFile->expires_at != null && File::exists($trackFile->getFile())) { - $cachedCount++; - } - } - - return $cachedCount; - } - - public function encodeCacheableTrackFiles($format) - { - foreach ($this->tracks as $track) { - /** @var $track Track */ - - if ($track->is_downloadable == false) { - continue; - } - - try { - $trackFile = $track->trackFiles()->where('format', $format)->firstOrFail(); - } catch (ModelNotFoundException $e) { - throw $e; - } - - if (!File::exists($trackFile->getFile()) && $trackFile->is_in_progress != true) { - $this->dispatch(new EncodeTrackFile($trackFile, true)); - } - } - } - public function syncTrackIds($trackIds) { $trackIdsInAlbum = []; diff --git a/app/Http/Controllers/Api/Web/AlbumsController.php b/app/Http/Controllers/Api/Web/AlbumsController.php index 67b0b98d..71f986b2 100644 --- a/app/Http/Controllers/Api/Web/AlbumsController.php +++ b/app/Http/Controllers/Api/Web/AlbumsController.php @@ -91,7 +91,9 @@ class AlbumsController extends ApiControllerBase { // Validation try { + /** @var Album $album */ $album = Album::with('tracks.trackFiles')->findOrFail($id); + } catch (ModelNotFoundException $e) { return $this->notFound('Album not found!'); } @@ -100,14 +102,10 @@ class AlbumsController extends ApiControllerBase return $this->notFound('Format not found!'); } - $trackCount = $album->countDownloadableTracks(); - try { - $cachedCount = $album->countCachedTrackFiles($format); - } catch (ModelNotFoundException $e) { - return $this->notFound('Track file in album not found!'); - } + $trackCount = $album->countDownloadableTracks($format); + $availableFilesCount = $album->countAvailableTrackFiles($format); - if ($trackCount === $cachedCount) { + if ($trackCount === $availableFilesCount) { $url = $album->getDownloadUrl($format); } else { $album->encodeCacheableTrackFiles($format); diff --git a/app/Http/Controllers/Api/Web/PlaylistsController.php b/app/Http/Controllers/Api/Web/PlaylistsController.php index 246d2724..aac920b3 100644 --- a/app/Http/Controllers/Api/Web/PlaylistsController.php +++ b/app/Http/Controllers/Api/Web/PlaylistsController.php @@ -116,6 +116,7 @@ class PlaylistsController extends ApiControllerBase { // Validation try { + /** @var $playlist Playlist */ $playlist = Playlist::with('tracks.trackFiles')->findOrFail($id); } catch (ModelNotFoundException $e) { return $this->notFound('Playlist not found!'); @@ -129,14 +130,10 @@ class PlaylistsController extends ApiControllerBase return $this->notFound('Format not found!'); } - $trackCount = $playlist->countDownloadableTracks(); - try { - $cachedCount = $playlist->countCachedTrackFiles($format); - } catch (ModelNotFoundException $e) { - return $this->notFound('Track file in playlist not found!'); - } + $trackCount = $playlist->countDownloadableTracks($format); + $availableFilesCount = $playlist->countAvailableTrackFiles($format); - if ($trackCount === $cachedCount) { + if ($trackCount === $availableFilesCount) { $url = $playlist->getDownloadUrl($format); } else { $playlist->encodeCacheableTrackFiles($format); diff --git a/app/Playlist.php b/app/Playlist.php index e68eb981..b30cc7b2 100644 --- a/app/Playlist.php +++ b/app/Playlist.php @@ -20,21 +20,19 @@ namespace Poniverse\Ponyfm; -use File; use Helpers; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Bus\DispatchesJobs; use Auth; use Cache; +use Poniverse\Ponyfm\Traits\TrackCollection; use URL; -use Poniverse\Ponyfm\Jobs\EncodeTrackFile; use Poniverse\Ponyfm\Traits\SlugTrait; class Playlist extends Model { - use SoftDeletes, SlugTrait, DispatchesJobs; + use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection; protected $table = 'playlists'; @@ -158,6 +156,12 @@ class Playlist extends Model ->orderBy('position', 'asc'); } + public function trackFiles() + { + $trackIds = $this->tracks->lists('id'); + return TrackFile::whereIn('track_id', $trackIds); + } + public function users() { return $this->hasMany('Poniverse\Ponyfm\ResourceUser'); @@ -204,63 +208,6 @@ class Playlist extends Model return URL::to('p' . $this->id . '/dl.' . Track::$Formats[$format]['extension']); } - public function countDownloadableTracks() - { - $trackCount = 0; - - foreach ($this->tracks as $track) { - if ($track->is_downloadable == true) { - $trackCount++; - } else { - continue; - } - } - - return $trackCount; - } - - public function countCachedTrackFiles($format) - { - $cachedCount = 0; - - foreach ($this->tracks as $track) { - /** @var $track Track */ - - if ($track->is_downloadable == false) { - continue; - } - - $trackFile = $track->trackFiles()->where('format', $format)->firstOrFail(); - - if ($trackFile->expires_at != null && File::exists($trackFile->getFile())) { - $cachedCount++; - } - } - - return $cachedCount; - } - - public function encodeCacheableTrackFiles($format) - { - foreach ($this->tracks as $track) { - /** @var $track Track */ - - if ($track->is_downloadable == false) { - continue; - } - - try { - $trackFile = $track->trackFiles()->where('format', $format)->firstOrFail(); - } catch (ModelNotFoundException $e) { - throw $e; - } - - if (!File::exists($trackFile->getFile()) && $trackFile->is_in_progress != true) { - $this->dispatch(new EncodeTrackFile($trackFile, true)); - } - } - } - public function getFilesize($format) { $tracks = $this->tracks; diff --git a/app/Traits/TrackCollection.php b/app/Traits/TrackCollection.php new file mode 100644 index 00000000..2be06db0 --- /dev/null +++ b/app/Traits/TrackCollection.php @@ -0,0 +1,127 @@ +. + */ + +namespace Poniverse\Ponyfm\Traits; + + +use File; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\Relation; +use Poniverse\Ponyfm\Jobs\EncodeTrackFile; +use Poniverse\Ponyfm\TrackFile; + + +/** + * Class TrackCollection + * @package Poniverse\Ponyfm\Traits + * + * Contains common logic between albums and playlists. They share some functionality + * because they're both a form of downloadable track collection. + */ +trait TrackCollection +{ + /** + * This relation represents all tracks contained by the collection. + * + * @return Relation + */ + abstract public function tracks(); + + /** + * This relation represents all track files belonging to this collection's + * tracks. + * + * @return Relation + */ + abstract public function trackFiles(); + + + /** + * Returns the number of tracks that are available in the given format. + * + * @param string $format + * @return int the number of downloadable tracks in this collection + */ + public function countDownloadableTracks($format) { + return $this->downloadableTrackFiles($format)->count(); + } + + + /** + * Returns the number of currently-available track files (master files + + * currently cached files) for this collection in the given format. + * + * @param string $format + * @return int + */ + public function countAvailableTrackFiles($format) { + $trackFiles = $this->downloadableTrackFiles($format); + $availableCount = 0; + + foreach ($trackFiles as $trackFile) { + /** @var TrackFile $trackFile */ + + if ( + $trackFile->is_master || + ($trackFile->expires_at != null && File::exists($trackFile->getFile())) + ) { + $availableCount ++; + } + } + + return $availableCount; + } + + + /** + * Kicks off the encoding of any cacheable files in this collection that + * do not currently exist. + * + * @param $format + */ + public function encodeCacheableTrackFiles($format) { + $trackFiles = $this->downloadableTrackFiles($format); + + foreach ($trackFiles as $trackFile) { + /** @var TrackFile $trackFile */ + + if (!File::exists($trackFile->getFile()) && $trackFile->is_in_progress != true) { + $this->dispatch(new EncodeTrackFile($trackFile, true)); + } + } + } + + + /** + * Returns an Eloquent collection of downloadable TrackFiles for this {@link TrackCollection}. + * A {@link TrackFile} is considered downloadable if its associated {@link Track} is. + * + * @param $format + * @return Collection + */ + protected function downloadableTrackFiles($format) { + return $this->trackFiles()->with([ + 'track' => function ($query) { + $query->where('is_downloadable', true); + } + ])->where('format', $format)->get(); + } +}