From 1c4bc006b7b7362598524d2c65f3a84e9eda0cc0 Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 18 Aug 2013 23:19:04 -0500 Subject: [PATCH] Finished basic stats for tracks, playlists and albums Finished downloading for albums and playlists --- .../Api/Web/PlaylistsController.php | 61 +++------ app/controllers/PlaylistsController.php | 26 ++++ app/models/Entities/Album.php | 2 +- app/models/Entities/Playlist.php | 121 +++++++++++++++++- app/models/Entities/Track.php | 10 +- app/models/PlaylistDownloader.php | 26 ++-- app/routes.php | 1 + public/scripts/app/services/playlists.coffee | 2 +- public/templates/playlists/show.html | 10 +- 9 files changed, 201 insertions(+), 58 deletions(-) diff --git a/app/controllers/Api/Web/PlaylistsController.php b/app/controllers/Api/Web/PlaylistsController.php index 1a303493..e1e44398 100644 --- a/app/controllers/Api/Web/PlaylistsController.php +++ b/app/controllers/Api/Web/PlaylistsController.php @@ -10,6 +10,7 @@ use Entities\Comment; use Entities\Image; use Entities\Playlist; + use Entities\ResourceLogItem; use Entities\Track; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Input; @@ -33,64 +34,38 @@ } public function getShow($id) { - $playlist = Playlist::with(['tracks' => function($query) { $query->details(); }, 'comments' => function($query) { $query->with('user'); }])->find($id); + $playlist = Playlist::with(['tracks.user', 'tracks' => function($query) { $query->details(); }, 'comments', 'comments.user'])->details()->find($id); if (!$playlist || !$playlist->canView(Auth::user())) App::abort('404'); - $tracks = []; - foreach ($playlist->tracks as $track) { - $tracks[] = Track::mapPublicTrackSummary($track); + if (Input::get('log')) { + ResourceLogItem::logItem('playlist', $id, ResourceLogItem::VIEW); + $playlist->view_count++; } - $comments = []; - foreach ($playlist->comments as $comment) { - $comments[] = Comment::mapPublic($comment); - } - - return Response::json([ - 'id' => $playlist->id, - 'title' => $playlist->title, - 'description' => $playlist->description, - 'slug' => $playlist->slug, - 'created_at' => $playlist->created_at, - 'url' => $playlist->url, - 'covers' => [ - 'small' => $playlist->getCoverUrl(Image::SMALL), - 'normal' => $playlist->getCoverUrl(Image::NORMAL) - ], - 'is_pinned' => true, - 'is_public' => $playlist->is_public == 1, - 'tracks' => $tracks, - 'comments' => ['count' => count($comments), 'list' => $comments], - ], 200); + return Response::json(Playlist::mapPublicPlaylistShow($playlist), 200); } public function getPinned() { - $query = Playlist::join('pinned_playlists', function($join) { - $join->on('playlist_id', '=', 'playlists.id'); - }) + $query = Playlist + ::with(['tracks.user', 'tracks' => function($query) {}, 'comments', 'comments.user']) + ->details() + ->join('pinned_playlists', function($join) { + $join->on('playlist_id', '=', 'playlists.id'); + }) ->where('pinned_playlists.user_id', '=', Auth::user()->id) ->orderBy('title', 'asc') - ->select('playlists.id', 'playlists.title', 'playlists.slug', 'playlists.created_at', 'playlists.user_id', 'playlists.is_public', 'playlists.description') + ->select('playlists.*') ->get(); $playlists = []; foreach ($query as $playlist) { - $playlists[] = [ - 'id' => $playlist->id, - 'title' => $playlist->title, - 'description' => $playlist->description, - 'slug' => $playlist->slug, - 'created_at' => $playlist->created_at, - 'url' => $playlist->url, - 'covers' => [ - 'small' => $playlist->getCoverUrl(Image::SMALL), - 'normal' => $playlist->getCoverUrl(Image::NORMAL) - ], - 'is_pinned' => true, - 'is_public' => $playlist->is_public == 1 - ]; + $mapped = Playlist::mapPublicPlaylistSummary($playlist); + $mapped['description'] = $playlist->description; + $mapped['is_pinned'] = true; + $playlists[] = $mapped; } + return Response::json($playlists, 200); } diff --git a/app/controllers/PlaylistsController.php b/app/controllers/PlaylistsController.php index 09b62c55..acfea0ab 100644 --- a/app/controllers/PlaylistsController.php +++ b/app/controllers/PlaylistsController.php @@ -1,6 +1,8 @@ slug]); } + + public function getDownload($id, $extension) { + $playlist = Playlist::with('tracks', 'user', 'tracks.album')->find($id); + if (!$playlist || !$playlist->is_public) + App::abort(404); + + $format = null; + $formatName = null; + + foreach (Track::$Formats as $name => $item) { + if ($item['extension'] == $extension) { + $format = $item; + $formatName = $name; + break; + } + } + + if ($format == null) + App::abort(404); + + ResourceLogItem::logItem('playlist', $id, ResourceLogItem::DOWNLOAD, $format['index']); + $downloader = new PlaylistDownloader($playlist, $formatName); + $downloader->download(); + } } \ No newline at end of file diff --git a/app/models/Entities/Album.php b/app/models/Entities/Album.php index bfb34d15..90377d96 100644 --- a/app/models/Entities/Album.php +++ b/app/models/Entities/Album.php @@ -106,7 +106,7 @@ return [ 'id' => $album->id, - 'track_count' => $album->tracks->count(), + 'track_count' => $album->tracks()->count(), 'title' => $album->title, 'slug' => $album->slug, 'created_at' => $album->created_at, diff --git a/app/models/Entities/Playlist.php b/app/models/Entities/Playlist.php index ebf6ae95..e3ae234e 100644 --- a/app/models/Entities/Playlist.php +++ b/app/models/Entities/Playlist.php @@ -1,6 +1,10 @@ with(['users' => function($query) { + $query->whereUserId(Auth::user()->id); + }]); + } + + return !$query; + } + + public static function mapPublicPlaylistShow($playlist) { + $tracks = []; + foreach ($playlist->tracks as $track) { + $tracks[] = Track::mapPublicTrackSummary($track); + } + + $formats = []; + foreach (Track::$Formats as $name => $format) { + $formats[] = [ + 'name' => $name, + 'extension' => $format['extension'], + 'url' => $playlist->getDownloadUrl($name), + 'size' => Helpers::formatBytes($playlist->getFilesize($name)) + ]; + } + + $comments = []; + foreach ($playlist->comments as $comment) { + $comments[] = Comment::mapPublic($comment); + } + + $data = self::mapPublicPlaylistSummary($playlist); + $data['tracks'] = $tracks; + $data['comments'] = $comments; + $data['formats'] = $formats; + + return $data; + } + + public static function mapPublicPlaylistSummary($playlist) { + $userData = [ + 'stats' => [ + 'views' => 0, + 'downloads' => 0 + ], + 'is_favourited' => false + ]; + + if ($playlist->users->count()) { + $userRow = $playlist->users[0]; + $userData = [ + 'stats' => [ + 'views' => $userRow->view_count, + 'downloads' => $userRow->download_count, + ], + 'is_favourited' => $userRow->is_favourited + ]; + } + + return [ + 'id' => $playlist->id, + 'track_count' => $playlist->tracks->count(), + 'title' => $playlist->title, + 'slug' => $playlist->slug, + 'created_at' => $playlist->created_at, + 'is_public' => $playlist->is_public, + 'stats' => [ + 'views' => $playlist->view_count, + 'downloads' => $playlist->download_count, + 'comments' => $playlist->comment_count, + 'favourites' => $playlist->favourite_count + ], + 'covers' => [ + 'small' => $playlist->getCoverUrl(Image::SMALL), + 'normal' => $playlist->getCoverUrl(Image::NORMAL) + ], + 'url' => $playlist->url, + 'user' => [ + 'id' => $playlist->user->id, + 'name' => $playlist->user->display_name, + 'url' => $playlist->user->url, + ], + 'user_data' => $userData + ]; } public function tracks() { @@ -21,6 +111,10 @@ ->orderBy('position', 'asc'); } + public function users() { + return $this->hasMany('Entities\ResourceUser'); + } + public function comments(){ return $this->hasMany('Entities\Comment'); } @@ -47,7 +141,26 @@ } public function getUrlAttribute() { - return '/playlist/' . $this->id . '-' . $this->slug; + return URL::to('/playlist/' . $this->id . '-' . $this->slug); + } + + public function getDownloadUrl($format) { + return URL::to('p' . $this->id . '/dl.' . Track::$Formats[$format]['extension']); + } + + public function getFilesize($format) { + $tracks = $this->tracks()->get(); + if (!count($tracks)) + return 0; + + return Cache::remember($this->getCacheKey('filesize-' . $format), 1440, function() use ($tracks, $format) { + $size = 0; + foreach ($tracks as $track) { + $size += $track->getFilesize($format); + } + + return $size; + }); } public function getCoverUrl($type = Image::NORMAL) { @@ -63,4 +176,8 @@ $pin->user_id = $userId; $pin->save(); } + + private function getCacheKey($key) { + return 'album-' . $this->id . '-' . $key; + } } \ No newline at end of file diff --git a/app/models/Entities/Track.php b/app/models/Entities/Track.php index 21cad80c..5aaa593c 100644 --- a/app/models/Entities/Track.php +++ b/app/models/Entities/Track.php @@ -245,6 +245,14 @@ return URL::to('/tracks/' . $this->id . '-' . $this->slug); } + public function getDownloadDirectoryAttribute() { + if ($this->album) { + return $this->user->display_name . '/' . $this->album->title; + } + + return $this->user->display_name; + } + public function getReleaseDate() { if($this->attributes['released_at'] !== NULL) return $this->attributes['released_at']; @@ -281,7 +289,7 @@ return $this->cover->getUrl($type); } - public function getStreamUrl($format) { + public function getStreamUrl() { return URL::to('/t' . $this->id . '/stream'); } diff --git a/app/models/PlaylistDownloader.php b/app/models/PlaylistDownloader.php index 6ea860f9..56357372 100644 --- a/app/models/PlaylistDownloader.php +++ b/app/models/PlaylistDownloader.php @@ -12,17 +12,15 @@ function download() { $zip = new ZipStream($this->_playlist->user->display_name . ' - ' . $this->_playlist->title . '.zip'); $zip->setComment( - 'Album: ' . $this->_playlist->title ."\r\n". - 'Artist: ' . $this->_playlist->user->display_name ."\r\n". + 'Playlist: '. $this->_playlist->title ."\r\n". + 'Curator: ' . $this->_playlist->user->display_name ."\r\n". 'URL: ' . $this->_playlist->url ."\r\n"."\r\n". 'Downloaded on '. date('l, F jS, Y, \a\t h:i:s A') . '.' ); - $directory = $this->_playlist->user->display_name . '/' . $this->_playlist->title . '/'; - $notes = - 'Album: ' . $this->_playlist->title ."\r\n". - 'Artist: ' . $this->_playlist->user->display_name ."\r\n". + 'Playlist: '. $this->_playlist->title ."\r\n". + 'Curator: ' . $this->_playlist->user->display_name ."\r\n". 'URL: ' . $this->_playlist->url ."\r\n". "\r\n". $this->_playlist->description ."\r\n". @@ -31,18 +29,28 @@ 'Tracks' ."\r\n". "\r\n"; + $m3u = ''; + $index = 1; foreach ($this->_playlist->tracks as $track) { if (!$track->is_downloadable) continue; - $zip->addLargeFile($track->getFileFor($this->_format), $directory . $track->getDownloadFilenameFor($this->_format)); + $trackTarget = $track->downloadDirectory . '/' . $track->getDownloadFilenameFor($this->_format); + $zip->addLargeFile($track->getFileFor($this->_format), $trackTarget); $notes .= - $track->track_number . '. ' . $track->title ."\r\n". + $index . '. ' . $track->title ."\r\n". $track->description ."\r\n". "\r\n"; + + $m3u .= '#EXTINF:' . $track->duration . ',' . $track->title . "\r\n"; + $m3u .= '../' . $trackTarget . "\r\n"; + + $index++; } - $zip->addFile($notes, $directory . 'Album Notes.txt'); + $playlistDir = 'Pony.fm Playlists/'; + $zip->addFile($notes, $playlistDir . $this->_playlist->title . '.txt'); + $zip->addFile($m3u, $playlistDir . $this->_playlist->title . '.m3u'); $zip->finalize(); } } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index 774a46cf..2ff8a27f 100644 --- a/app/routes.php +++ b/app/routes.php @@ -41,6 +41,7 @@ Route::get('playlist/{id}-{slug}', 'PlaylistsController@getPlaylist'); Route::get('p{id}', 'PlaylistsController@getShortlink')->where('id', '\d+'); + Route::get('p{id}/dl.{extension}', 'PlaylistsController@getDownload' ); Route::group(['prefix' => 'api/web'], function() { Route::get('/taxonomies/all', 'Api\Web\TaxonomiesController@getAll'); diff --git a/public/scripts/app/services/playlists.coffee b/public/scripts/app/services/playlists.coffee index 8b1b4fc9..1175f6da 100644 --- a/public/scripts/app/services/playlists.coffee +++ b/public/scripts/app/services/playlists.coffee @@ -11,7 +11,7 @@ angular.module('ponyfm').factory('playlists', [ force = force || false return playlists[id] if !force && playlists[id] def = new $.Deferred() - $http.get('/api/web/playlists/' + id).success (playlist) -> + $http.get('/api/web/playlists/' + id + '?log=true').success (playlist) -> def.resolve playlist playlists[id] = def.promise() diff --git a/public/templates/playlists/show.html b/public/templates/playlists/show.html index 7e948f67..487c5317 100644 --- a/public/templates/playlists/show.html +++ b/public/templates/playlists/show.html @@ -5,12 +5,13 @@
+
@@ -38,6 +39,13 @@ Share or Embed + +

Stats

+