#4: Refactored a bunch of common logic between albums and playlists into a trait.

This commit is contained in:
Peter Deltchev 2015-11-09 21:49:12 -08:00
parent 3456e6b499
commit c28c887e29
5 changed files with 150 additions and 141 deletions

View file

@ -23,19 +23,17 @@ namespace Poniverse\Ponyfm;
use Exception; use Exception;
use Helpers; use Helpers;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Auth; use Auth;
use Cache; use Cache;
use File; use Poniverse\Ponyfm\Traits\TrackCollection;
use URL; use URL;
use Poniverse\Ponyfm\Jobs\EncodeTrackFile;
use Poniverse\Ponyfm\Traits\SlugTrait; use Poniverse\Ponyfm\Traits\SlugTrait;
class Album extends Model class Album extends Model
{ {
use SoftDeletes, SlugTrait, DispatchesJobs; use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection;
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
@ -85,6 +83,10 @@ class Album extends Model
return $this->hasMany('Poniverse\Ponyfm\Track')->orderBy('track_number', 'asc'); 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() public function comments()
{ {
return $this->hasMany('Poniverse\Ponyfm\Comment')->orderBy('created_at', 'desc'); 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) public function syncTrackIds($trackIds)
{ {
$trackIdsInAlbum = []; $trackIdsInAlbum = [];

View file

@ -91,7 +91,9 @@ class AlbumsController extends ApiControllerBase
{ {
// Validation // Validation
try { try {
/** @var Album $album */
$album = Album::with('tracks.trackFiles')->findOrFail($id); $album = Album::with('tracks.trackFiles')->findOrFail($id);
} catch (ModelNotFoundException $e) { } catch (ModelNotFoundException $e) {
return $this->notFound('Album not found!'); return $this->notFound('Album not found!');
} }
@ -100,14 +102,10 @@ class AlbumsController extends ApiControllerBase
return $this->notFound('Format not found!'); return $this->notFound('Format not found!');
} }
$trackCount = $album->countDownloadableTracks(); $trackCount = $album->countDownloadableTracks($format);
try { $availableFilesCount = $album->countAvailableTrackFiles($format);
$cachedCount = $album->countCachedTrackFiles($format);
} catch (ModelNotFoundException $e) {
return $this->notFound('Track file in album not found!');
}
if ($trackCount === $cachedCount) { if ($trackCount === $availableFilesCount) {
$url = $album->getDownloadUrl($format); $url = $album->getDownloadUrl($format);
} else { } else {
$album->encodeCacheableTrackFiles($format); $album->encodeCacheableTrackFiles($format);

View file

@ -116,6 +116,7 @@ class PlaylistsController extends ApiControllerBase
{ {
// Validation // Validation
try { try {
/** @var $playlist Playlist */
$playlist = Playlist::with('tracks.trackFiles')->findOrFail($id); $playlist = Playlist::with('tracks.trackFiles')->findOrFail($id);
} catch (ModelNotFoundException $e) { } catch (ModelNotFoundException $e) {
return $this->notFound('Playlist not found!'); return $this->notFound('Playlist not found!');
@ -129,14 +130,10 @@ class PlaylistsController extends ApiControllerBase
return $this->notFound('Format not found!'); return $this->notFound('Format not found!');
} }
$trackCount = $playlist->countDownloadableTracks(); $trackCount = $playlist->countDownloadableTracks($format);
try { $availableFilesCount = $playlist->countAvailableTrackFiles($format);
$cachedCount = $playlist->countCachedTrackFiles($format);
} catch (ModelNotFoundException $e) {
return $this->notFound('Track file in playlist not found!');
}
if ($trackCount === $cachedCount) { if ($trackCount === $availableFilesCount) {
$url = $playlist->getDownloadUrl($format); $url = $playlist->getDownloadUrl($format);
} else { } else {
$playlist->encodeCacheableTrackFiles($format); $playlist->encodeCacheableTrackFiles($format);

View file

@ -20,21 +20,19 @@
namespace Poniverse\Ponyfm; namespace Poniverse\Ponyfm;
use File;
use Helpers; use Helpers;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Auth; use Auth;
use Cache; use Cache;
use Poniverse\Ponyfm\Traits\TrackCollection;
use URL; use URL;
use Poniverse\Ponyfm\Jobs\EncodeTrackFile;
use Poniverse\Ponyfm\Traits\SlugTrait; use Poniverse\Ponyfm\Traits\SlugTrait;
class Playlist extends Model class Playlist extends Model
{ {
use SoftDeletes, SlugTrait, DispatchesJobs; use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection;
protected $table = 'playlists'; protected $table = 'playlists';
@ -158,6 +156,12 @@ class Playlist extends Model
->orderBy('position', 'asc'); ->orderBy('position', 'asc');
} }
public function trackFiles()
{
$trackIds = $this->tracks->lists('id');
return TrackFile::whereIn('track_id', $trackIds);
}
public function users() public function users()
{ {
return $this->hasMany('Poniverse\Ponyfm\ResourceUser'); 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']); 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) public function getFilesize($format)
{ {
$tracks = $this->tracks; $tracks = $this->tracks;

View file

@ -0,0 +1,127 @@
<?php
/**
* Pony.fm - A community for pony fan music.
* Copyright (C) 2015 Peter Deltchev
* Copyright (C) 2015 Kelvin Zhang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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();
}
}