diff --git a/.arcconfig b/.arcconfig index adbd0155..f4b1e785 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,4 +1,4 @@ { "phabricator.uri" : "https://phabricator.poniverse.net/", "history.immutable" : true -} +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 83dfbb9f..011b6259 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,7 @@ * text=auto -app/config/production/* filter=git-crypt diff=git-crypt -app/config/stage/* filter=git-crypt diff=git-crypt +resources/environments/.env.stage filter=git-crypt diff=git-crypt +resources/environments/.env.production filter=git-crypt diff=git-crypt + +*.css linguist-vendored +*.less linguist-vendored diff --git a/.gitignore b/.gitignore index 423589b7..d44311e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,48 +1,8 @@ -.vagrant - -# Numerous always-ignore extensions -*.diff -*.err -*.orig -*.log -*.rej -*.swo -*.swp -*.vi -*~ -*.sass-cache - -# OS or Editor folders -.DS_Store -Thumbs.db -.cache -.project -.settings -.tmproj -*.esproj -nbproject -*.iml - -# Dreamweaver added files -_notes -dwsync.xml - -# Komodo -*.komodoproject -.komodotools - -# Folders to ignore -.hg -.svn -.CVS -intermediate -publish -.idea - -node_modules -/public/build/ -/bootstrap/compiled.php /vendor -composer.phar -atlassian-ide-plugin.xml +/node_modules +/public/build +/logs +Homestead.yaml +.env +.vagrant _ide_helper.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 015febc4..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contribution Guidelines - -Please submit all issues and pull requests to the [laravel/framework](http://github.com/laravel/framework) repository! \ No newline at end of file diff --git a/app/Album.php b/app/Album.php new file mode 100644 index 00000000..87904abb --- /dev/null +++ b/app/Album.php @@ -0,0 +1,319 @@ +with([ + 'users' => function ($query) { + $query->whereUserId(Auth::user()->id); + } + ]); + } + + return !$query; + } + + protected $table = 'albums'; + + public function user() + { + return $this->belongsTo('App\User'); + } + + public function users() + { + return $this->hasMany('App\ResourceUser'); + } + + public function favourites() + { + return $this->hasMany('App\Favourite'); + } + + public function cover() + { + return $this->belongsTo('App\Image'); + } + + public function tracks() + { + return $this->hasMany('App\Track')->orderBy('track_number', 'asc'); + } + + public function comments() + { + return $this->hasMany('App\Comment')->orderBy('created_at', 'desc'); + } + + public static function mapPublicAlbumShow($album) + { + $tracks = []; + foreach ($album->tracks as $track) { + $tracks[] = Track::mapPublicTrackSummary($track); + } + + $formats = []; + foreach (Track::$Formats as $name => $format) { + $formats[] = [ + 'name' => $name, + 'extension' => $format['extension'], + 'url' => $album->getDownloadUrl($name), + 'size' => Helpers::formatBytes($album->getFilesize($name)) + ]; + } + + $comments = []; + foreach ($album->comments as $comment) { + $comments[] = Comment::mapPublic($comment); + } + + $is_downloadable = 0; + foreach ($album->tracks as $track) { + if ($track->is_downloadable == 1) { + $is_downloadable = 1; + break; + } + } + + $data = self::mapPublicAlbumSummary($album); + $data['tracks'] = $tracks; + $data['comments'] = $comments; + $data['formats'] = $formats; + $data['description'] = $album->description; + $data['is_downloadable'] = $is_downloadable; + $data['share'] = [ + 'url' => URL::to('/a' . $album->id), + 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($album->url) . '&name=' . urlencode($album->title) . '&description=' . urlencode($album->description), + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $album->title . ' by ' . $album->user->display_name . ' on Pony.fm' + ]; + + return $data; + } + + public static function mapPublicAlbumSummary($album) + { + $userData = [ + 'stats' => [ + 'views' => 0, + 'downloads' => 0 + ], + 'is_favourited' => false + ]; + + if (Auth::check() && $album->users->count()) { + $userRow = $album->users[0]; + $userData = [ + 'stats' => [ + 'views' => (int) $userRow->view_count, + 'downloads' => (int) $userRow->download_count, + ], + 'is_favourited' => (bool) $userRow->is_favourited + ]; + } + + return [ + 'id' => (int) $album->id, + 'track_count' => (int) $album->track_count, + 'title' => $album->title, + 'slug' => $album->slug, + 'created_at' => $album->created_at, + 'stats' => [ + 'views' => (int) $album->view_count, + 'downloads' => (int) $album->download_count, + 'comments' => (int) $album->comment_count, + 'favourites' => (int) $album->favourite_count + ], + 'covers' => [ + 'small' => $album->getCoverUrl(Image::SMALL), + 'normal' => $album->getCoverUrl(Image::NORMAL) + ], + 'url' => $album->url, + 'user' => [ + 'id' => (int) $album->user->id, + 'name' => $album->user->display_name, + 'url' => $album->user->url, + ], + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $album->user_id, + 'edit' => Auth::check() && Auth::user()->id == $album->user_id + ] + ]; + } + + public function hasCover() + { + return $this->cover_id != null; + } + + public function getUrlAttribute() + { + return URL::to('albums/' . $this->id . '-' . $this->slug); + } + + public function getDownloadUrl($format) + { + return URL::to('a' . $this->id . '/dl.' . Track::$Formats[$format]['extension']); + } + + public function getFilesize($format) + { + $tracks = $this->tracks; + if (!count($tracks)) { + return 0; + } + + return Cache::remember($this->getCacheKey('filesize-' . $format), 1440, function () use ($tracks, $format) { + $size = 0; + foreach ($tracks as $track) { + // Ensure that only downloadable tracks are added onto the file size + if ($track->is_downloadable == 1) { + $size += $track->getFilesize($format); + } + } + + return $size; + }); + } + + public function getCoverUrl($type = Image::NORMAL) + { + if (!$this->hasCover()) { + return $this->user->getAvatarUrl($type); + } + + return $this->cover->getUrl($type); + } + + public function getDirectory() + { + $dir = (string)(floor($this->id / 100) * 100); + + return \Config::get('ponyfm.files_directory') . '/tracks/' . $dir; + } + + public function getDates() + { + return ['created_at', 'deleted_at', 'published_at']; + } + + public function getFilenameFor($format) + { + if (!isset(Track::$Formats[$format])) { + throw new Exception("$format is not a valid format!"); + } + + $format = Track::$Formats[$format]; + + return "{$this->id}.{$format['extension']}.zip"; + } + + public function updateTrackNumbers() + { + $tracks = Track::whereAlbumId($this->id)->get(); + $index = 1; + + foreach ($tracks as $track) { + $track->track_number = $index; + $index++; + $track->updateTags(); + $track->save(); + } + } + + public function syncTrackIds($trackIds) + { + $trackIdsInAlbum = []; + foreach ($this->tracks as $track) { + $trackIdsInAlbum[] = $track->id; + } + + $trackIdsCount = count($trackIds); + $trackIdsInAlbumCount = count($trackIdsInAlbum); + $isSame = true; + + if ($trackIdsInAlbumCount != $trackIdsCount) { + $isSame = false; + } else { + for ($i = 0; $i < $trackIdsInAlbumCount; $i++) { + if ($i >= $trackIdsCount || $trackIdsInAlbum[$i] != $trackIds[$i]) { + $isSame = false; + break; + } + } + } + + if ($isSame) { + return; + } + + $index = 1; + $tracksToRemove = []; + $albumsToFix = []; + + foreach ($this->tracks as $track) { + $tracksToRemove[$track->id] = $track; + } + + foreach ($trackIds as $trackId) { + if (!strlen(trim($trackId))) { + continue; + } + + $track = Track::find($trackId); + if ($track->album_id != null && $track->album_id != $this->id) { + $albumsToFix[] = $track->album; + } + + $track->album_id = $this->id; + $track->track_number = $index; + $track->updateTags(); + $track->save(); + + unset($tracksToRemove[$track->id]); + $index++; + } + + foreach ($tracksToRemove as $track) { + $track->album_id = null; + $track->track_number = null; + $track->updateTags(); + $track->save(); + } + + foreach ($albumsToFix as $album) { + $album->updateTrackNumbers(); + } + + foreach (Track::$Formats as $name => $format) { + Cache::forget($this->getCacheKey('filesize' . $name)); + } + } + + private function getCacheKey($key) + { + return 'album-' . $this->id . '-' . $key; + } +} diff --git a/app/AlbumDownloader.php b/app/AlbumDownloader.php new file mode 100644 index 00000000..50ea54e4 --- /dev/null +++ b/app/AlbumDownloader.php @@ -0,0 +1,53 @@ +_album = $album; + $this->_format = $format; + } + + function download() + { + $zip = new ZipStream($this->_album->user->display_name . ' - ' . $this->_album->title . '.zip'); + $zip->setComment( + 'Album: ' . $this->_album->title . "\r\n" . + 'Artist: ' . $this->_album->user->display_name . "\r\n" . + 'URL: ' . $this->_album->url . "\r\n" . "\r\n" . + 'Downloaded on ' . date('l, F jS, Y, \a\t h:i:s A') . '.' + ); + + $directory = $this->_album->user->display_name . '/' . $this->_album->title . '/'; + + $notes = + 'Album: ' . $this->_album->title . "\r\n" . + 'Artist: ' . $this->_album->user->display_name . "\r\n" . + 'URL: ' . $this->_album->url . "\r\n" . + "\r\n" . + $this->_album->description . "\r\n" . + "\r\n" . + "\r\n" . + 'Tracks' . "\r\n" . + "\r\n"; + + foreach ($this->_album->tracks as $track) { + if (!$track->is_downloadable) { + continue; + } + + $zip->addLargeFile($track->getFileFor($this->_format), + $directory . $track->getDownloadFilenameFor($this->_format)); + $notes .= + $track->track_number . '. ' . $track->title . "\r\n" . + $track->description . "\r\n" . + "\r\n"; + } + + $zip->addFile($notes, $directory . 'Album Notes.txt'); + $zip->finalize(); + } +} \ No newline at end of file diff --git a/app/Commands/AddTrackToPlaylistCommand.php b/app/Commands/AddTrackToPlaylistCommand.php new file mode 100644 index 00000000..cd514001 --- /dev/null +++ b/app/Commands/AddTrackToPlaylistCommand.php @@ -0,0 +1,46 @@ +_playlist = Playlist::find($playlistId); + $this->_track = Track::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null && $this->_playlist && $this->_track && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $songIndex = $this->_playlist->tracks()->count() + 1; + $this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]); + + Playlist::whereId($this->_playlist->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = ' . $this->_playlist->id . ')') + ]); + + return CommandResponse::succeed(['message' => 'Track added!']); + } +} \ No newline at end of file diff --git a/app/Commands/CommandBase.php b/app/Commands/CommandBase.php new file mode 100644 index 00000000..850f571e --- /dev/null +++ b/app/Commands/CommandBase.php @@ -0,0 +1,33 @@ +_listeners[] = $listener; + } + + protected function notify($message, $progress) + { + foreach ($this->_listeners as $listener) { + $listener($message, $progress); + } + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return CommandResponse + */ + public abstract function execute(); +} \ No newline at end of file diff --git a/app/Commands/CommandResponse.php b/app/Commands/CommandResponse.php new file mode 100644 index 00000000..b1616e74 --- /dev/null +++ b/app/Commands/CommandResponse.php @@ -0,0 +1,58 @@ +_didFail = true; + $response->_validator = $validator; + + return $response; + } + + public static function succeed($response = null) + { + $cmdResponse = new CommandResponse(); + $cmdResponse->_didFail = false; + $cmdResponse->_response = $response; + + return $cmdResponse; + } + + private $_validator; + private $_response; + private $_didFail; + + private function __construct() + { + } + + /** + * @return bool + */ + public function didFail() + { + return $this->_didFail; + } + + /** + * @return mixed + */ + public function getResponse() + { + return $this->_response; + } + + /** + * @return Validator + */ + public function getValidator() + { + return $this->_validator; + } +} \ No newline at end of file diff --git a/app/Commands/CreateAlbumCommand.php b/app/Commands/CreateAlbumCommand.php new file mode 100644 index 00000000..244fb686 --- /dev/null +++ b/app/Commands/CreateAlbumCommand.php @@ -0,0 +1,72 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'cover_id' => 'exists:images,id', + 'track_ids' => 'exists:tracks,id' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $album = new Album(); + $album->user_id = Auth::user()->id; + $album->title = $this->_input['title']; + $album->description = $this->_input['description']; + + if (isset($this->_input['cover_id'])) { + $album->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $album->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') { + $album->cover_id = null; + } + } + } + + $trackIds = explode(',', $this->_input['track_ids']); + $album->save(); + $album->syncTrackIds($trackIds); + + return CommandResponse::succeed(['id' => $album->id]); + } +} \ No newline at end of file diff --git a/app/Commands/CreateCommentCommand.php b/app/Commands/CreateCommentCommand.php new file mode 100644 index 00000000..83440a87 --- /dev/null +++ b/app/Commands/CreateCommentCommand.php @@ -0,0 +1,79 @@ +_input = $input; + $this->_id = $id; + $this->_type = $type; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'content' => 'required', + 'track_id' => 'exists:tracks,id', + 'albums_id' => 'exists:albums,id', + 'playlist_id' => 'exists:playlists,id', + 'profile_id' => 'exists:users,id', + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $comment = new Comment(); + $comment->user_id = Auth::user()->id; + $comment->content = $this->_input['content']; + + if ($this->_type == 'track') { + $column = 'track_id'; + } else { + if ($this->_type == 'user') { + $column = 'profile_id'; + } else { + if ($this->_type == 'album') { + $column = 'album_id'; + } else { + if ($this->_type == 'playlist') { + $column = 'playlist_id'; + } else { + App::abort(500); + } + } + } + } + + $comment->$column = $this->_id; + $comment->save(); + + return CommandResponse::succeed(Comment::mapPublic($comment)); + } +} \ No newline at end of file diff --git a/app/Commands/CreatePlaylistCommand.php b/app/Commands/CreatePlaylistCommand.php new file mode 100644 index 00000000..267420bf --- /dev/null +++ b/app/Commands/CreatePlaylistCommand.php @@ -0,0 +1,69 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'is_public' => 'required', + 'is_pinned' => 'required' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $playlist = new Playlist(); + $playlist->user_id = Auth::user()->id; + $playlist->title = $this->_input['title']; + $playlist->description = $this->_input['description']; + $playlist->is_public = $this->_input['is_public'] == 'true'; + + $playlist->save(); + + if ($this->_input['is_pinned'] == 'true') { + $playlist->pin(Auth::user()->id); + } + + return CommandResponse::succeed([ + 'id' => $playlist->id, + 'title' => $playlist->title, + 'slug' => $playlist->slug, + 'created_at' => $playlist->created_at, + 'description' => $playlist->description, + 'url' => $playlist->url, + 'is_pinned' => $this->_input['is_pinned'] == 'true', + 'is_public' => $this->_input['is_public'] == 'true' + ]); + } +} \ No newline at end of file diff --git a/app/Commands/DeleteAlbumCommand.php b/app/Commands/DeleteAlbumCommand.php new file mode 100644 index 00000000..79ee865f --- /dev/null +++ b/app/Commands/DeleteAlbumCommand.php @@ -0,0 +1,46 @@ +_albumId = $albumId; + $this->_album = ALbum::find($albumId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_album && $user != null && $this->_album->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + foreach ($this->_album->tracks as $track) { + $track->album_id = null; + $track->track_number = null; + $track->updateTags(); + $track->save(); + } + + $this->_album->delete(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/DeletePlaylistCommand.php b/app/Commands/DeletePlaylistCommand.php new file mode 100644 index 00000000..f06821a8 --- /dev/null +++ b/app/Commands/DeletePlaylistCommand.php @@ -0,0 +1,43 @@ +_playlistId = $playlistId; + $this->_playlist = Playlist::find($playlistId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + foreach ($this->_playlist->pins as $pin) { + $pin->delete(); + } + + $this->_playlist->delete(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/DeleteTrackCommand.php b/app/Commands/DeleteTrackCommand.php new file mode 100644 index 00000000..bf0ebcff --- /dev/null +++ b/app/Commands/DeleteTrackCommand.php @@ -0,0 +1,46 @@ +_trackId = $trackId; + $this->_track = Track::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $this->_track && $user != null && $this->_track->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + if ($this->_track->album_id != null) { + $album = $this->_track->album; + $this->_track->album_id = null; + $this->_track->track_number = null; + $this->_track->delete(); + $album->updateTrackNumbers(); + } else { + $this->_track->delete(); + } + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/EditAlbumCommand.php b/app/Commands/EditAlbumCommand.php new file mode 100644 index 00000000..b2c96ba1 --- /dev/null +++ b/app/Commands/EditAlbumCommand.php @@ -0,0 +1,79 @@ +_input = $input; + $this->_albumId = $trackId; + $this->_album = Album::find($trackId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_album && $user != null && $this->_album->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'cover_id' => 'exists:images,id', + 'track_ids' => 'exists:tracks,id' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $this->_album->title = $this->_input['title']; + $this->_album->description = $this->_input['description']; + + if (isset($this->_input['cover_id'])) { + $this->_album->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $this->_album->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') { + $this->_album->cover_id = null; + } + } + } + + $trackIds = explode(',', $this->_input['track_ids']); + $this->_album->syncTrackIds($trackIds); + $this->_album->save(); + + Album::whereId($this->_album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $this->_album->id . ')') + ]); + + return CommandResponse::succeed(['real_cover_url' => $this->_album->getCoverUrl(Image::NORMAL)]); + } +} \ No newline at end of file diff --git a/app/Commands/EditPlaylistCommand.php b/app/Commands/EditPlaylistCommand.php new file mode 100644 index 00000000..46f7d4ef --- /dev/null +++ b/app/Commands/EditPlaylistCommand.php @@ -0,0 +1,77 @@ +_input = $input; + $this->_playlistId = $playlistId; + $this->_playlist = Playlist::find($playlistId); + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $rules = [ + 'title' => 'required|min:3|max:50', + 'is_public' => 'required', + 'is_pinned' => 'required' + ]; + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $this->_playlist->title = $this->_input['title']; + $this->_playlist->description = $this->_input['description']; + $this->_playlist->is_public = $this->_input['is_public'] == 'true'; + + $this->_playlist->save(); + + $pin = PinnedPlaylist::whereUserId(Auth::user()->id)->wherePlaylistId($this->_playlistId)->first(); + if ($pin && $this->_input['is_pinned'] != 'true') { + $pin->delete(); + } else { + if (!$pin && $this->_input['is_pinned'] == 'true') { + $this->_playlist->pin(Auth::user()->id); + } + } + + return CommandResponse::succeed([ + 'id' => $this->_playlist->id, + 'title' => $this->_playlist->title, + 'slug' => $this->_playlist->slug, + 'created_at' => $this->_playlist->created_at, + 'description' => $this->_playlist->description, + 'url' => $this->_playlist->url, + 'is_pinned' => $this->_input['is_pinned'] == 'true', + 'is_public' => $this->_input['is_public'] == 'true' + ]); + } +} \ No newline at end of file diff --git a/app/Commands/EditTrackCommand.php b/app/Commands/EditTrackCommand.php new file mode 100644 index 00000000..a509e03c --- /dev/null +++ b/app/Commands/EditTrackCommand.php @@ -0,0 +1,161 @@ +_trackId = $trackId; + $this->_track = Track::find($trackId); + $this->_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + $user = \Auth::user(); + + return $this->_track && $user != null && $this->_track->user_id == $user->id; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $isVocal = (isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true') ? true : false; + + $rules = [ + 'title' => 'required|min:3|max:80', + 'released_at' => 'before:' . (date('Y-m-d', + time() + (86400 * 2))) . (isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? '|date' : ''), + 'license_id' => 'required|exists:licenses,id', + 'genre_id' => 'required|exists:genres,id', + 'cover' => 'image|mimes:png|min_width:350|min_height:350', + 'track_type_id' => 'required|exists:track_types,id', + 'songs' => 'required_when:track_type,2|exists:songs,id', + 'cover_id' => 'exists:images,id', + 'album_id' => 'exists:albums,id' + ]; + + if ($isVocal) { + $rules['lyrics'] = 'required'; + } + + if (isset($this->_input['track_type_id']) && $this->_input['track_type_id'] == 2) { + $rules['show_song_ids'] = 'required|exists:show_songs,id'; + } + + $validator = \Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $track = $this->_track; + $track->title = $this->_input['title']; + $track->released_at = isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? strtotime($this->_input['released_at']) : null; + $track->description = isset($this->_input['description']) ? $this->_input['description'] : ''; + $track->lyrics = isset($this->_input['lyrics']) ? $this->_input['lyrics'] : ''; + $track->license_id = $this->_input['license_id']; + $track->genre_id = $this->_input['genre_id']; + $track->track_type_id = $this->_input['track_type_id']; + $track->is_explicit = $this->_input['is_explicit'] == 'true'; + $track->is_downloadable = $this->_input['is_downloadable'] == 'true'; + $track->is_listed = $this->_input['is_listed'] == 'true'; + $track->is_vocal = $isVocal; + + if (isset($this->_input['album_id']) && strlen(trim($this->_input['album_id']))) { + if ($track->album_id != null && $track->album_id != $this->_input['album_id']) { + $this->removeTrackFromAlbum($track); + } + + if ($track->album_id != $this->_input['album_id']) { + $album = Album::find($this->_input['album_id']); + $track->track_number = $album->tracks()->count() + 1; + $track->album_id = $this->_input['album_id']; + + Album::whereId($album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') + ]); + } + } else { + if ($track->album_id != null) { + $this->removeTrackFromAlbum($track); + } + + $track->track_number = null; + $track->album_id = null; + } + + if ($track->track_type_id == 2) { + $track->showSongs()->sync(explode(',', $this->_input['show_song_ids'])); + } else { + $track->showSongs()->sync([]); + } + + if ($track->published_at == null) { + $track->published_at = new \DateTime(); + + DB::table('tracks')->whereUserId($track->user_id)->update(['is_latest' => false]); + $track->is_latest = true; + } + + if (isset($this->_input['cover_id'])) { + $track->cover_id = $this->_input['cover_id']; + } else { + if (isset($this->_input['cover'])) { + $cover = $this->_input['cover']; + $track->cover_id = Image::upload($cover, Auth::user())->id; + } else { + if ($this->_input['remove_cover'] == 'true') { + $track->cover_id = null; + } + } + } + + $track->updateTags(); + $track->save(); + + User::whereId($this->_track->user_id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE deleted_at IS NULL AND published_at IS NOT NULL AND user_id = ' . $this->_track->user_id . ')') + ]); + + return CommandResponse::succeed(['real_cover_url' => $track->getCoverUrl(Image::NORMAL)]); + } + + private function removeTrackFromAlbum($track) + { + $album = $track->album; + $index = 0; + + foreach ($album->tracks as $track) { + if ($track->id == $this->_trackId) { + continue; + } + + $track->track_number = ++$index; + $track->updateTags(); + $track->save(); + } + + Album::whereId($album->id)->update([ + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') + ]); + } +} \ No newline at end of file diff --git a/app/Commands/SaveAccountSettingsCommand.php b/app/Commands/SaveAccountSettingsCommand.php new file mode 100644 index 00000000..830d3834 --- /dev/null +++ b/app/Commands/SaveAccountSettingsCommand.php @@ -0,0 +1,88 @@ +_input = $input; + } + + /** + * @return bool + */ + public function authorize() + { + return Auth::user() != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $user = Auth::user(); + + $rules = [ + 'display_name' => 'required|min:3|max:26', + 'bio' => 'textarea_length:250' + ]; + + if ($this->_input['sync_names'] == 'true') { + $this->_input['display_name'] = $user->mlpforums_name; + } + + if ($this->_input['uses_gravatar'] == 'true') { + $rules['gravatar'] = 'email'; + } else { + $rules['avatar'] = 'image|mimes:png|min_width:350|min_height:350'; + $rules['avatar_id'] = 'exists:images,id'; + } + + $validator = Validator::make($this->_input, $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + if ($this->_input['uses_gravatar'] != 'true') { + if ($user->avatar_id == null && !isset($this->_input['avatar']) && !isset($this->_input['avatar_id'])) { + $validator->messages()->add('avatar', + 'You must upload or select an avatar if you are not using gravatar!'); + + return CommandResponse::fail($validator); + } + } + + $user->bio = $this->_input['bio']; + $user->display_name = $this->_input['display_name']; + $user->sync_names = $this->_input['sync_names'] == 'true'; + $user->can_see_explicit_content = $this->_input['can_see_explicit_content'] == 'true'; + $user->uses_gravatar = $this->_input['uses_gravatar'] == 'true'; + + if ($user->uses_gravatar) { + $user->avatar_id = null; + $user->gravatar = $this->_input['gravatar']; + } else { + if (isset($this->_input['avatar_id'])) { + $user->avatar_id = $this->_input['avatar_id']; + } else { + if (isset($this->_input['avatar'])) { + $user->avatar_id = Image::upload($this->_input['avatar'], $user)->id; + } + } + } + + $user->save(); + + return CommandResponse::succeed(); + } +} \ No newline at end of file diff --git a/app/Commands/ToggleFavouriteCommand.php b/app/Commands/ToggleFavouriteCommand.php new file mode 100644 index 00000000..54bcb4f0 --- /dev/null +++ b/app/Commands/ToggleFavouriteCommand.php @@ -0,0 +1,75 @@ +_resourceId = $resourceId; + $this->_resourceType = $resourceType; + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $typeId = $this->_resourceType . '_id'; + $existing = Favourite::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); + $isFavourited = false; + + if ($existing) { + $existing->delete(); + } else { + $fav = new Favourite(); + $fav->$typeId = $this->_resourceId; + $fav->user_id = Auth::user()->id; + $fav->created_at = time(); + $fav->save(); + $isFavourited = true; + } + + $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); + $resourceUser->is_favourited = $isFavourited; + $resourceUser->save(); + + $resourceTable = $this->_resourceType . 's'; + + // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db + // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created + // for the same resource at the same time, the cached values will still be correct with this method. + + DB::table($resourceTable)->whereId($this->_resourceId)->update([ + 'favourite_count' => + DB::raw('( + SELECT + COUNT(id) + FROM + favourites + WHERE ' . + $typeId . ' = ' . $this->_resourceId . ')') + ]); + + return CommandResponse::succeed(['is_favourited' => $isFavourited]); + } +} \ No newline at end of file diff --git a/app/Commands/ToggleFollowingCommand.php b/app/Commands/ToggleFollowingCommand.php new file mode 100644 index 00000000..10c07f6e --- /dev/null +++ b/app/Commands/ToggleFollowingCommand.php @@ -0,0 +1,57 @@ +_resourceId = $resourceId; + $this->_resourceType = $resourceType; + } + + /** + * @return bool + */ + public function authorize() + { + $user = Auth::user(); + + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $typeId = $this->_resourceType . '_id'; + $existing = Follower::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); + $isFollowed = false; + + if ($existing) { + $existing->delete(); + } else { + $follow = new Follower(); + $follow->$typeId = $this->_resourceId; + $follow->user_id = Auth::user()->id; + $follow->created_at = time(); + $follow->save(); + $isFollowed = true; + } + + $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); + $resourceUser->is_followed = $isFollowed; + $resourceUser->save(); + + return CommandResponse::succeed(['is_followed' => $isFollowed]); + } +} \ No newline at end of file diff --git a/app/Commands/UploadTrackCommand.php b/app/Commands/UploadTrackCommand.php new file mode 100644 index 00000000..41d8938f --- /dev/null +++ b/app/Commands/UploadTrackCommand.php @@ -0,0 +1,154 @@ +_allowLossy = $allowLossy; + $this->_allowShortTrack = $allowShortTrack; + } + + /** + * @return bool + */ + public function authorize() + { + return \Auth::user() != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $user = \Auth::user(); + $trackFile = \Input::file('track'); + $audio = \AudioCache::get($trackFile->getPathname()); + + $validator = \Validator::make(['track' => $trackFile], [ + 'track' => + 'required|' + . ($this->_allowLossy ? '' : 'audio_format:'. implode(',', $this->_losslessFormats).'|') + . ($this->_allowShortTrack ? '' : 'min_duration:30|') + . 'audio_channels:1,2|' + . 'sample_rate:44100,48000,88200,96000,176400,192000' + ]); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + $track = new Track(); + + try { + $track->user_id = $user->id; + $track->title = pathinfo($trackFile->getClientOriginalName(), PATHINFO_FILENAME); + $track->duration = $audio->getDuration(); + $track->is_listed = true; + + $track->save(); + + $destination = $track->getDirectory(); + $track->ensureDirectoryExists(); + + $source = $trackFile->getPathname(); + $index = 0; + + $processes = []; + + // Lossy uploads need to be identified and set as the master file + // without being re-encoded. + $audioObject = AudioCache::get($source); + $isLossyUpload = !in_array($audioObject->getAudioCodec(), $this->_losslessFormats); + + if ($isLossyUpload) { + if ($audioObject->getAudioCodec() === 'mp3') { + $masterFormat = 'MP3'; + + } else if (Str::startsWith($audioObject->getAudioCodec(), 'aac')) { + $masterFormat = 'AAC'; + + } else if ($audioObject->getAudioCodec() === 'vorbis') { + $masterFormat = 'OGG Vorbis'; + + } else { + $validator->messages()->add('track', 'The track does not contain audio in a known lossy format.'); + return CommandResponse::fail($validator); + } + + $trackFile = new TrackFile(); + $trackFile->is_master = true; + $trackFile->format = $masterFormat; + $trackFile->track_id = $track->id; + $trackFile->save(); + + // Lossy masters are copied into the datastore - no re-encoding involved. + File::copy($source, $trackFile->getFile()); + } + + foreach (Track::$Formats as $name => $format) { + // Don't bother with lossless transcodes of lossy uploads, and + // don't re-encode the lossy master. + if ($isLossyUpload && ($format['is_lossless'] || $name === $masterFormat)) { + continue; + } + + $trackFile = new TrackFile(); + $trackFile->is_master = $name === 'FLAC' ? true : false; + $trackFile->format = $name; + $track->trackFiles()->save($trackFile); + + $target = $destination . '/' . $trackFile->getFilename(); //$track->getFilenameFor($name); + + $command = $format['command']; + $command = str_replace('{$source}', '"' . $source . '"', $command); + $command = str_replace('{$target}', '"' . $target . '"', $command); + + Log::info('Encoding ' . $track->id . ' into ' . $target); + $this->notify('Encoding ' . $name, $index / count(Track::$Formats) * 100); + + $pipes = []; + $proc = proc_open($command, [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'a']], $pipes); + $processes[] = $proc; + } + + foreach ($processes as $proc) { + proc_close($proc); + } + + $track->updateTags(); + + } catch (\Exception $e) { + $track->delete(); + throw $e; + } + + return CommandResponse::succeed([ + 'id' => $track->id, + 'name' => $track->name + ]); + } +} \ No newline at end of file diff --git a/app/Comment.php b/app/Comment.php new file mode 100644 index 00000000..51f3b8d5 --- /dev/null +++ b/app/Comment.php @@ -0,0 +1,81 @@ +belongsTo('App\User'); + } + + public function track() + { + return $this->belongsTo('App\Track'); + } + + public function album() + { + return $this->belongsTo('App\Album'); + } + + public function playlist() + { + return $this->belongsTo('App\Playlist'); + } + + public function profile() + { + return $this->belongsTo('App\User', 'profile_id'); + } + + public static function mapPublic($comment) + { + return [ + 'id' => $comment->id, + 'created_at' => $comment->created_at, + 'content' => $comment->content, + 'user' => [ + 'name' => $comment->user->display_name, + 'id' => $comment->user->id, + 'url' => $comment->user->url, + 'avatars' => [ + 'normal' => $comment->user->getAvatarUrl(Image::NORMAL), + 'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL), + 'small' => $comment->user->getAvatarUrl(Image::SMALL), + ] + ] + ]; + } + + public function getResourceAttribute() + { + if ($this->track_id !== null) { + return $this->track; + } else { + if ($this->album_id !== null) { + return $this->album; + } else { + if ($this->playlist_id !== null) { + return $this->playlist; + } else { + if ($this->profile_id !== null) { + return $this->profile; + } else { + return null; + } + } + } + } + } +} \ No newline at end of file diff --git a/app/Console/Commands/ClassifyMLPMA.php b/app/Console/Commands/ClassifyMLPMA.php new file mode 100644 index 00000000..d1866d49 --- /dev/null +++ b/app/Console/Commands/ClassifyMLPMA.php @@ -0,0 +1,221 @@ +orderBy('id') + ->get(); + + $this->comment('Importing tracks...'); + + $totalTracks = sizeof($tracks); + + $fileToStartAt = (int)$this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files..." . PHP_EOL); + + $tracks = array_slice($tracks, $fileToStartAt); + $this->currentTrack = $fileToStartAt; + + foreach ($tracks as $track) { + $this->currentTrack++; + $this->comment('[' . $this->currentTrack . '/' . $totalTracks . '] Classifying track [' . $track->filename . ']...'); + + $parsedTags = json_decode($track->parsed_tags, true); + + + //========================================================================================================== + // Original, show song remix, fan song remix, show audio remix, or ponified song? + //========================================================================================================== + $sanitizedTrackTitle = $parsedTags['title']; + $sanitizedTrackTitle = str_replace(['-', '+', '~', 'ft.', '*', '(', ')', '.'], ' ', $sanitizedTrackTitle); + + $queriedTitle = DB::connection()->getPdo()->quote($sanitizedTrackTitle); + $officialSongs = ShowSong::select(['id', 'title']) + ->whereRaw(" + MATCH (title) + AGAINST ($queriedTitle IN BOOLEAN MODE) + ") + ->get(); + + + // If it has "Ingram" in the name, it's definitely an official song remix. + if (Str::contains(Str::lower($track->filename), 'ingram')) { + $this->info('This is an official song remix!'); + + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs, true, + $parsedTags); + + + // If it has "remix" in the name, it's definitely a remix. + } else { + if (Str::contains(Str::lower($sanitizedTrackTitle), 'remix')) { + $this->info('This is some kind of remix!'); + + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs, false, + $parsedTags); + + // No idea what this is. Have the pony at the terminal figure it out! + } else { + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs, false, + $parsedTags); + } + } + + + //========================================================================================================== + // Attach the data and publish the track! + //========================================================================================================== + + $track = Track::find($track->track_id); + + $track->track_type_id = $trackType; + $track->published_at = $parsedTags['released_at']; + $track->save(); + + if (sizeof($linkedSongIds) > 0) { + $track->showSongs()->sync($linkedSongIds); + } + + echo PHP_EOL; + } + + } + + /** + * Determines what type of track the given file is. If unable to guess, the user + * is asked to identify it interactively. + * + * @param string $filename + * @param ShowSong[] $officialSongs + * @param bool|false $isRemixOfOfficialTrack + * @return array + */ + protected function classifyTrack($filename, $officialSongs, $isRemixOfOfficialTrack = false, $tags) + { + $trackTypeId = null; + $linkedSongIds = []; + + + foreach ($officialSongs as $song) { + $this->comment('=> Matched official song: [' . $song->id . '] ' . $song->title); + } + + + if ($isRemixOfOfficialTrack && sizeof($officialSongs) === 1) { + $linkedSongIds = [$officialSongs[0]->id]; + + } else { + if ($isRemixOfOfficialTrack && sizeof($officialSongs) > 1) { + $this->question('Multiple official songs matched! Please enter the ID of the correct one.'); + + } else { + if (sizeof($officialSongs) > 0) { + $this->question('This looks like a remix of an official song!'); + $this->question('Press "r" if the match above is right!'); + + } else { + $this->question('Exactly what kind of track is this?'); + + } + } + $this->question('If this is a medley, multiple song ID\'s can be separated by commas. '); + $this->question(' '); + $this->question(' ' . $filename . ' '); + $this->question(' '); + $this->question(' Title: ' . $tags['title'] . ' '); + $this->question(' Album: ' . $tags['album'] . ' '); + $this->question(' Artist: ' . $tags['artist'] . ' '); + $this->question(' '); + $this->question(' r = official song remix (accept all "guessed" matches) '); + $this->question(' # = official song remix (enter the ID(s) of the show song(s)) '); + $this->question(' a = show audio remix '); + $this->question(' f = fan track remix '); + $this->question(' p = ponified track '); + $this->question(' o = original track '); + $this->question(' '); + $input = $this->ask('[r/#/a/f/p/o]: '); + + switch ($input) { + case 'r': + $trackTypeId = TrackType::OFFICIAL_TRACK_REMIX; + foreach ($officialSongs as $officialSong) { + $linkedSongIds[] = (int)$officialSong->id; + } + break; + + case 'a': + $trackTypeId = TrackType::OFFICIAL_AUDIO_REMIX; + break; + + case 'f': + $trackTypeId = TrackType::FAN_TRACK_REMIX; + break; + + case 'p': + $trackTypeId = TrackType::PONIFIED_TRACK; + break; + + case 'o': + $trackTypeId = TrackType::ORIGINAL_TRACK; + break; + + default: + $trackTypeId = TrackType::OFFICIAL_TRACK_REMIX; + $linkedSongIds = explode(',', $input); + $linkedSongIds = array_map(function ($item) { + return (int)$item; + }, $linkedSongIds); + } + } + + return [$trackTypeId, $linkedSongIds]; + } +} diff --git a/app/Console/Commands/ImportMLPMA.php b/app/Console/Commands/ImportMLPMA.php new file mode 100644 index 00000000..ca4fc8a2 --- /dev/null +++ b/app/Console/Commands/ImportMLPMA.php @@ -0,0 +1,498 @@ +error('Import aborted!'); + $this->error('Resume it from here using: --startAt=' . $this->currentFile); + $this->isInterrupted = true; + } + + /** + * Execute the console command. + * + * @return void + */ + public function handle() + { + pcntl_signal(SIGINT, [$this, 'handleInterrupt']); + + $mlpmaPath = Config::get('ponyfm.files_directory') . 'mlpma'; + $tmpPath = Config::get('ponyfm.files_directory') . 'tmp'; + + if (!File::exists($tmpPath)) { + File::makeDirectory($tmpPath); + } + + $UNKNOWN_GENRE = Genre::firstOrCreate([ + 'name' => 'Unknown', + 'slug' => 'unknown' + ]); + + $this->comment('Enumerating MLP Music Archive source files...'); + $files = File::allFiles($mlpmaPath); + $this->info(sizeof($files) . ' files found!'); + + $this->comment('Enumerating artists...'); + $artists = File::directories($mlpmaPath); + $this->info(sizeof($artists) . ' artists found!'); + + $this->comment('Importing tracks...'); + + $totalFiles = sizeof($files); + + $fileToStartAt = (int)$this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files..." . PHP_EOL); + + $files = array_slice($files, $fileToStartAt); + $this->currentFile = $fileToStartAt; + + foreach ($files as $file) { + $this->currentFile++; + + pcntl_signal_dispatch(); + if ($this->isInterrupted) { + break; + } + + $this->comment('[' . $this->currentFile . '/' . $totalFiles . '] Importing track [' . $file->getFilename() . ']...'); + + if (in_array($file->getExtension(), $this->ignoredExtensions)) { + $this->comment('This is not an audio file! Skipping...' . PHP_EOL); + continue; + } + + + // Has this track already been imported? + $importedTrack = DB::table('mlpma_tracks') + ->where('filename', '=', $file->getFilename()) + ->first(); + + if ($importedTrack) { + $this->comment('This track has already been imported! Skipping...' . PHP_EOL); + continue; + } + + + //========================================================================================================== + // Extract the original tags. + //========================================================================================================== + $getId3 = new getID3; + + // all tags read by getID3, including the cover art + $allTags = $getId3->analyze($file->getPathname()); + + // tags specific to a file format (ID3 or Atom), pre-normalization but with cover art removed + $rawTags = []; + + // normalized tags used by Pony.fm + $parsedTags = []; + + if (Str::lower($file->getExtension()) === 'mp3') { + list($parsedTags, $rawTags) = $this->getId3Tags($allTags); + + } elseif (Str::lower($file->getExtension()) === 'm4a') { + list($parsedTags, $rawTags) = $this->getAtomTags($allTags); + + } elseif (Str::lower($file->getExtension()) === 'ogg') { + list($parsedTags, $rawTags) = $this->getVorbisTags($allTags); + + } elseif (Str::lower($file->getExtension()) === 'flac') { + list($parsedTags, $rawTags) = $this->getVorbisTags($allTags); + + } + + //========================================================================================================== + // Determine the release date. + //========================================================================================================== + $modifiedDate = Carbon::createFromTimeStampUTC(File::lastModified($file->getPathname())); + $taggedYear = $parsedTags['year']; + + $this->info('Modification year: ' . $modifiedDate->year); + $this->info('Tagged year: ' . $taggedYear); + + if ($taggedYear !== null && $modifiedDate->year === $taggedYear) { + $releasedAt = $modifiedDate; + } elseif ($taggedYear !== null && Str::length((string)$taggedYear) !== 4) { + $this->error('This track\'s tagged year makes no sense! Using the track\'s last modified date...'); + $releasedAt = $modifiedDate; + } elseif ($taggedYear !== null && $modifiedDate->year !== $taggedYear) { + $this->error('Release years don\'t match! Using the tagged year...'); + $releasedAt = Carbon::create($taggedYear); + + } else { + // $taggedYear is null + $this->error('This track isn\'t tagged with its release year! Using the track\'s last modified date...'); + $releasedAt = $modifiedDate; + } + + // This is later used by the classification/publishing script to determine the publication date. + $parsedTags['released_at'] = $releasedAt->toDateTimeString(); + + //========================================================================================================== + // Does this track have vocals? + //========================================================================================================== + $isVocal = $parsedTags['lyrics'] !== null; + + + //========================================================================================================== + // Fill in the title tag if it's missing. + //========================================================================================================== + if (!$parsedTags['title']) { + $parsedTags['title'] = $file->getBasename('.' . $file->getExtension()); + } + + + //========================================================================================================== + // Determine the genre. + //========================================================================================================== + $genreName = $parsedTags['genre']; + $genreSlug = Str::slug($genreName); + $this->info('Genre: ' . $genreName); + + if ($genreName && $genreSlug !== '') { + $genre = Genre::where('name', '=', $genreName)->first(); + if ($genre) { + $genreId = $genre->id; + + } else { + $genre = new Genre(); + $genre->name = $genreName; + $genre->slug = $genreSlug; + $genre->save(); + $genreId = $genre->id; + $this->comment('Created a new genre!'); + } + + } else { + $genreId = $UNKNOWN_GENRE->id; // "Unknown" genre ID + } + + + //========================================================================================================== + // Determine which artist account this file belongs to using the containing directory. + //========================================================================================================== + $this->info('Path to file: ' . $file->getRelativePath()); + $path_components = explode(DIRECTORY_SEPARATOR, $file->getRelativePath()); + $artist_name = $path_components[0]; + $album_name = array_key_exists(1, $path_components) ? $path_components[1] : null; + + $this->info('Artist: ' . $artist_name); + $this->info('Album: ' . $album_name); + + $artist = User::where('display_name', '=', $artist_name)->first(); + + if (!$artist) { + $artist = new User; + $artist->display_name = $artist_name; + $artist->email = null; + $artist->is_archived = true; + + $artist->slug = Str::slug($artist_name); + + $slugExists = User::where('slug', '=', $artist->slug)->first(); + if ($slugExists) { + $this->error('Horsefeathers! The slug ' . $artist->slug . ' is already taken!'); + $artist->slug = $artist->slug . '-' . Str::random(4); + } + + $artist->save(); + } + + //========================================================================================================== + // Extract the cover art, if any exists. + //========================================================================================================== + + $this->comment('Extracting cover art!'); + $coverId = null; + if (array_key_exists('comments', $allTags) && array_key_exists('picture', $allTags['comments'])) { + $image = $allTags['comments']['picture'][0]; + + if ($image['image_mime'] === 'image/png') { + $extension = 'png'; + + } elseif ($image['image_mime'] === 'image/jpeg') { + $extension = 'jpg'; + + } elseif ($image['image_mime'] === 'image/gif') { + $extension = 'gif'; + + } else { + $this->error('Unknown cover art format!'); + } + + // write temporary image file + $imageFilename = $file->getFilename() . ".cover.$extension"; + $imageFilePath = "$tmpPath/" . $imageFilename; + File::put($imageFilePath, $image['data']); + + + $imageFile = new UploadedFile($imageFilePath, $imageFilename, $image['image_mime']); + + $cover = Image::upload($imageFile, $artist); + $coverId = $cover->id; + + } else { + $this->comment('No cover art found!'); + } + + + //========================================================================================================== + // Is this part of an album? + //========================================================================================================== + + $albumId = null; + $albumName = $parsedTags['album']; + + if ($albumName !== null) { + $album = Album::where('user_id', '=', $artist->id) + ->where('title', '=', $albumName) + ->first(); + + if (!$album) { + $album = new Album; + + $album->title = $albumName; + $album->user_id = $artist->id; + $album->cover_id = $coverId; + + $album->save(); + } + + $albumId = $album->id; + } + + + //========================================================================================================== + // Save this track. + //========================================================================================================== + // "Upload" the track to Pony.fm + $this->comment('Transcoding the track!'); + Auth::loginUsingId($artist->id); + + $trackFile = new UploadedFile($file->getPathname(), $file->getFilename(), $allTags['mime_type']); + Input::instance()->files->add(['track' => $trackFile]); + + $upload = new UploadTrackCommand(true, true); + $result = $upload->execute(); + + if ($result->didFail()) { + $this->error(json_encode($result->getValidator()->messages()->getMessages(), JSON_PRETTY_PRINT)); + + } else { + // Save metadata. + $track = Track::find($result->getResponse()['id']); + + $track->title = $parsedTags['title']; + $track->cover_id = $coverId; + $track->album_id = $albumId; + $track->genre_id = $genreId; + $track->track_number = $parsedTags['track_number']; + $track->released_at = $releasedAt; + $track->description = $parsedTags['comments']; + $track->is_downloadable = true; + $track->lyrics = $parsedTags['lyrics']; + $track->is_vocal = $isVocal; + $track->license_id = 2; + $track->save(); + + // If we made it to here, the track is intact! Log the import. + DB::table('mlpma_tracks') + ->insert([ + 'track_id' => $result->getResponse()['id'], + 'path' => $file->getRelativePath(), + 'filename' => $file->getFilename(), + 'extension' => $file->getExtension(), + 'imported_at' => Carbon::now(), + 'parsed_tags' => json_encode($parsedTags), + 'raw_tags' => json_encode($rawTags), + ]); + } + + echo PHP_EOL . PHP_EOL; + } + } + + /** + * @param array $rawTags + * @return array + */ + protected function getId3Tags($rawTags) + { + if (array_key_exists('tags', $rawTags) && array_key_exists('id3v2', $rawTags['tags'])) { + $tags = $rawTags['tags']['id3v2']; + } elseif (array_key_exists('tags', $rawTags) && array_key_exists('id3v1', $rawTags['tags'])) { + $tags = $rawTags['tags']['id3v1']; + } else { + $tags = []; + } + + + $comment = null; + + if (isset($tags['comment'])) { + // The "comment" tag comes in with a badly encoded string index + // so its array key has to be used implicitly. + $key = array_keys($tags['comment'])[0]; + + // The comment may have a null byte at the end. trim() removes it. + $comment = trim($tags['comment'][$key]); + + // Replace the malformed comment with the "fixed" one. + unset($tags['comment'][$key]); + $tags['comment'][0] = $comment; + } + + return [ + [ + 'title' => isset($tags['title']) ? $tags['title'][0] : null, + 'artist' => isset($tags['artist']) ? $tags['artist'][0] : null, + 'band' => isset($tags['band']) ? $tags['band'][0] : null, + 'genre' => isset($tags['genre']) ? $tags['genre'][0] : null, + 'track_number' => isset($tags['track_number']) ? $tags['track_number'][0] : null, + 'album' => isset($tags['album']) ? $tags['album'][0] : null, + 'year' => isset($tags['year']) ? (int)$tags['year'][0] : null, + 'comments' => $comment, + 'lyrics' => isset($tags['unsynchronised_lyric']) ? $tags['unsynchronised_lyric'][0] : null, + ], + $tags + ]; + } + + /** + * @param array $rawTags + * @return array + */ + protected function getAtomTags($rawTags) + { + if (array_key_exists('tags', $rawTags) && array_key_exists('quicktime', $rawTags['tags'])) { + $tags = $rawTags['tags']['quicktime']; + } else { + $tags = []; + } + + $trackNumber = null; + if (isset($tags['track_number'])) { + $trackNumberComponents = explode('/', $tags['track_number'][0]); + $trackNumber = $trackNumberComponents[0]; + } + + return [ + [ + 'title' => isset($tags['title']) ? $tags['title'][0] : null, + 'artist' => isset($tags['artist']) ? $tags['artist'][0] : null, + 'band' => isset($tags['band']) ? $tags['band'][0] : null, + 'album_artist' => isset($tags['album_artist']) ? $tags['album_artist'][0] : null, + 'genre' => isset($tags['genre']) ? $tags['genre'][0] : null, + 'track_number' => $trackNumber, + 'album' => isset($tags['album']) ? $tags['album'][0] : null, + 'year' => isset($tags['year']) ? (int)$tags['year'][0] : null, + 'comments' => isset($tags['comments']) ? $tags['comments'][0] : null, + 'lyrics' => isset($tags['lyrics']) ? $tags['lyrics'][0] : null, + ], + $tags + ]; + } + + /** + * @param array $rawTags + * @return array + */ + protected function getVorbisTags($rawTags) + { + if (array_key_exists('tags', $rawTags) && array_key_exists('vorbiscomment', $rawTags['tags'])) { + $tags = $rawTags['tags']['vorbiscomment']; + } else { + $tags = []; + } + + $trackNumber = null; + if (isset($tags['track_number'])) { + $trackNumberComponents = explode('/', $tags['track_number'][0]); + $trackNumber = $trackNumberComponents[0]; + } + + return [ + [ + 'title' => isset($tags['title']) ? $tags['title'][0] : null, + 'artist' => isset($tags['artist']) ? $tags['artist'][0] : null, + 'band' => isset($tags['band']) ? $tags['band'][0] : null, + 'album_artist' => isset($tags['album_artist']) ? $tags['album_artist'][0] : null, + 'genre' => isset($tags['genre']) ? $tags['genre'][0] : null, + 'track_number' => $trackNumber, + 'album' => isset($tags['album']) ? $tags['album'][0] : null, + 'year' => isset($tags['year']) ? (int)$tags['year'][0] : null, + 'comments' => isset($tags['comments']) ? $tags['comments'][0] : null, + 'lyrics' => isset($tags['lyrics']) ? $tags['lyrics'][0] : null, + ], + $tags + ]; + } + +} diff --git a/app/Console/Commands/Inspire.php b/app/Console/Commands/Inspire.php new file mode 100644 index 00000000..db9ab854 --- /dev/null +++ b/app/Console/Commands/Inspire.php @@ -0,0 +1,33 @@ +comment(PHP_EOL.Inspiring::quote().PHP_EOL); + } +} diff --git a/app/Console/Commands/MigrateOldData.php b/app/Console/Commands/MigrateOldData.php new file mode 100644 index 00000000..e4cae80e --- /dev/null +++ b/app/Console/Commands/MigrateOldData.php @@ -0,0 +1,382 @@ +disableQueryLog(); + + $oldDb = DB::connection('old'); + + $this->call('migrate:refresh'); + + $oldUsers = $oldDb->table('users')->get(); + $this->info('Syncing Users'); + foreach ($oldUsers as $user) { + $displayName = $user->display_name; + if (!$displayName) { + $displayName = $user->username; + } + + if (!$displayName) { + $displayName = $user->mlpforums_name; + } + + if (!$displayName) { + continue; + } + + DB::table('users')->insert([ + 'id' => $user->id, + 'display_name' => $displayName, + 'email' => $user->email, + 'created_at' => $user->created_at, + 'updated_at' => $user->updated_at, + 'slug' => $user->slug, + 'bio' => $user->bio, + 'sync_names' => $user->sync_names, + 'can_see_explicit_content' => $user->can_see_explicit_content, + 'mlpforums_name' => $user->mlpforums_name, + 'uses_gravatar' => $user->uses_gravatar, + 'gravatar' => $user->gravatar, + 'avatar_id' => null + ]); + + $coverId = null; + if (!$user->uses_gravatar) { + try { + $coverFile = $this->getIdDirectory('users', $user->id) . '/' . $user->id . '_.png'; + $coverId = Image::upload(new UploadedFile($coverFile, + $user->id . '_.png'), $user->id)->id; + DB::table('users')->where('id', $user->id)->update(['avatar_id' => $coverId]); + } catch (\Exception $e) { + $this->error('Could copy user avatar ' . $user->id . ' because ' . $e->getMessage()); + DB::table('users')->where('id', $user->id)->update(['uses_gravatar' => true]); + } + } + } + + $this->info('Syncing Genres'); + $oldGenres = $oldDb->table('genres')->get(); + foreach ($oldGenres as $genre) { + DB::table('genres')->insert([ + 'id' => $genre->id, + 'name' => $genre->title, + 'slug' => $genre->slug + ]); + } + + $this->info('Syncing Albums'); + $oldAlbums = $oldDb->table('albums')->get(); + foreach ($oldAlbums as $playlist) { + $logViews = $oldDb->table('album_log_views')->whereAlbumId($playlist->id)->get(); + $logDownload = $oldDb->table('album_log_downloads')->whereAlbumId($playlist->id)->get(); + + DB::table('albums')->insert([ + 'title' => $playlist->title, + 'description' => $playlist->description, + 'created_at' => $playlist->created_at, + 'updated_at' => $playlist->updated_at, + 'deleted_at' => $playlist->deleted_at, + 'slug' => $playlist->slug, + 'id' => $playlist->id, + 'user_id' => $playlist->user_id, + 'view_count' => 0, + 'download_count' => 0 + ]); + + foreach ($logViews as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::VIEW, + 'album_id' => $logItem->album_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address, + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for album ' . $playlist->id . ' because ' . $e->getMessage()); + } + } + + foreach ($logDownload as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::DOWNLOAD, + 'album_id' => $logItem->album_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address, + 'track_format_id' => $logItem->track_file_format_id - 1 + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for album ' . $playlist->id . ' because ' . $e->getMessage()); + } + } + } + + $this->info('Syncing Tracks'); + $oldTracks = $oldDb->table('tracks')->get(); + foreach ($oldTracks as $track) { + $coverId = null; + if ($track->cover) { + try { + $coverFile = $this->getIdDirectory('tracks', + $track->id) . '/' . $track->id . '_' . $track->cover . '.png'; + $coverId = Image::upload(new UploadedFile($coverFile, + $track->id . '_' . $track->cover . '.png'), $track->user_id)->id; + } catch (\Exception $e) { + $this->error('Could copy track cover ' . $track->id . ' because ' . $e->getMessage()); + } + } + + $trackLogViews = $oldDb->table('track_log_views')->whereTrackId($track->id)->get(); + $trackLogPlays = $oldDb->table('track_log_plays')->whereTrackId($track->id)->get(); + $trackLogDownload = $oldDb->table('track_log_downloads')->whereTrackId($track->id)->get(); + + DB::table('tracks')->insert([ + 'id' => $track->id, + 'title' => $track->title, + 'slug' => $track->slug, + 'description' => $track->description, + 'lyrics' => $track->lyrics, + 'created_at' => $track->created_at, + 'deleted_at' => $track->deleted_at, + 'updated_at' => $track->updated_at, + 'released_at' => $track->released_at, + 'published_at' => $track->published_at, + 'genre_id' => $track->genre_id, + 'is_explicit' => $track->explicit, + 'is_downloadable' => $track->downloadable, + 'is_vocal' => $track->is_vocal, + 'track_type_id' => $track->track_type_id, + 'track_number' => $track->track_number, + 'user_id' => $track->user_id, + 'album_id' => $track->album_id, + 'cover_id' => $coverId, + 'license_id' => $track->license_id, + 'duration' => $track->duration, + 'view_count' => 0, + 'play_count' => 0, + 'download_count' => 0 + ]); + + foreach ($trackLogViews as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::VIEW, + 'track_id' => $logItem->track_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); + } + } + + foreach ($trackLogPlays as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::PLAY, + 'track_id' => $logItem->track_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); + } + } + + foreach ($trackLogDownload as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::DOWNLOAD, + 'track_id' => $logItem->track_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address, + 'track_format_id' => $logItem->track_file_format_id - 1 + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); + } + } + } + + $oldShowSongs = $oldDb->table('song_track')->get(); + foreach ($oldShowSongs as $song) { + try { + DB::table('show_song_track')->insert([ + 'id' => $song->id, + 'show_song_id' => $song->song_id, + 'track_id' => $song->track_id + ]); + } catch (\Exception $e) { + $this->error('Could insert show track item for ' . $song->track_id . ' because ' . $e->getMessage()); + } + } + + $this->info('Syncing Playlists'); + $oldPlaylists = $oldDb->table('playlists')->get(); + foreach ($oldPlaylists as $playlist) { + $logViews = $oldDb->table('playlist_log_views')->wherePlaylistId($playlist->id)->get(); + $logDownload = $oldDb->table('playlist_log_downloads')->wherePlaylistId($playlist->id)->get(); + + DB::table('playlists')->insert([ + 'title' => $playlist->title, + 'description' => $playlist->description, + 'created_at' => $playlist->created_at, + 'updated_at' => $playlist->updated_at, + 'deleted_at' => $playlist->deleted_at, + 'slug' => $playlist->slug, + 'id' => $playlist->id, + 'user_id' => $playlist->user_id, + 'is_public' => true, + 'view_count' => 0, + 'download_count' => 0, + ]); + + foreach ($logViews as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::VIEW, + 'playlist_id' => $logItem->playlist_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address, + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for playlist ' . $playlist->id . ' because ' . $e->getMessage()); + } + } + + foreach ($logDownload as $logItem) { + try { + DB::table('resource_log_items')->insert([ + 'user_id' => $logItem->user_id, + 'log_type' => ResourceLogItem::DOWNLOAD, + 'playlist_id' => $logItem->playlist_id, + 'created_at' => $logItem->created_at, + 'ip_address' => $logItem->ip_address, + 'track_format_id' => $logItem->track_file_format_id - 1 + ]); + } catch (\Exception $e) { + $this->error('Could insert log item for playlist ' . $playlist->id . ' because ' . $e->getMessage()); + } + } + } + + $this->info('Syncing Playlist Tracks'); + $oldPlaylistTracks = $oldDb->table('playlist_track')->get(); + foreach ($oldPlaylistTracks as $playlistTrack) { + DB::table('playlist_track')->insert([ + 'id' => $playlistTrack->id, + 'created_at' => $playlistTrack->created_at, + 'updated_at' => $playlistTrack->updated_at, + 'position' => $playlistTrack->position, + 'playlist_id' => $playlistTrack->playlist_id, + 'track_id' => $playlistTrack->track_id + ]); + } + + $this->info('Syncing Comments'); + $oldComments = $oldDb->table('comments')->get(); + foreach ($oldComments as $comment) { + try { + DB::table('comments')->insert([ + 'id' => $comment->id, + 'user_id' => $comment->user_id, + 'created_at' => $comment->created_at, + 'deleted_at' => $comment->deleted_at, + 'updated_at' => $comment->updated_at, + 'content' => $comment->content, + 'track_id' => $comment->track_id, + 'album_id' => $comment->album_id, + 'playlist_id' => $comment->playlist_id, + 'profile_id' => $comment->profile_id + ]); + } catch (Exception $e) { + $this->error('Could not sync comment ' . $comment->id . ' because ' . $e->getMessage()); + } + } + + $this->info('Syncing Favourites'); + $oldFavs = $oldDb->table('favourites')->get(); + foreach ($oldFavs as $fav) { + try { + DB::table('favourites')->insert([ + 'id' => $fav->id, + 'user_id' => $fav->user_id, + 'created_at' => $fav->created_at, + 'track_id' => $fav->track_id, + 'album_id' => $fav->album_id, + 'playlist_id' => $fav->playlist_id, + ]); + } catch (Exception $e) { + $this->error('Could not sync favourite ' . $fav->id . ' because ' . $e->getMessage()); + } + } + + $this->info('Syncing Followers'); + $oldFollowers = $oldDb->table('user_follower')->get(); + foreach ($oldFollowers as $follower) { + try { + DB::table('followers')->insert([ + 'id' => $follower->id, + 'user_id' => $follower->follower_id, + 'artist_id' => $follower->user_id, + 'created_at' => $follower->created_at, + ]); + } catch (Exception $e) { + $this->error('Could not sync follower ' . $follower->id . ' because ' . $e->getMessage()); + } + } + } + + private function getIdDirectory($type, $id) + { + $dir = (string)(floor($id / 100) * 100); + + return \Config::get('ponyfm.files_directory') . '/' . $type . '/' . $dir; + } + +} diff --git a/app/Console/Commands/RebuildTags.php b/app/Console/Commands/RebuildTags.php new file mode 100644 index 00000000..e379ca6b --- /dev/null +++ b/app/Console/Commands/RebuildTags.php @@ -0,0 +1,53 @@ +argument('trackId')) { + $track = Track::findOrFail($this->argument('trackId')); + $tracks = [$track]; + } else { + $tracks = Track::whereNotNull('published_at')->get(); + } + + foreach($tracks as $track) { + $this->comment('Rewriting tags for track #'.$track->id.'...'); + $track->updateTags(); + } + } +} diff --git a/app/Console/Commands/RefreshCache.php b/app/Console/Commands/RefreshCache.php new file mode 100644 index 00000000..88593c3d --- /dev/null +++ b/app/Console/Commands/RefreshCache.php @@ -0,0 +1,232 @@ +disableQueryLog(); + + DB::table('tracks')->update(['comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.track_id = tracks.id AND deleted_at IS NULL)')]); + + DB::table('albums')->update([ + 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.album_id = albums.id AND deleted_at IS NULL)'), + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = albums.id)') + ]); + + DB::table('playlists')->update([ + 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.playlist_id = playlists.id AND deleted_at IS NULL)'), + 'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = playlists.id)') + ]); + + DB::table('users')->update([ + 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.profile_id = users.id AND deleted_at IS NULL)'), + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE deleted_at IS NULL AND published_at IS NOT NULL AND user_id = users.id)') + ]); + + $users = DB::table('users')->get(); + $cacheItems = []; + $resources = [ + 'album' => [], + 'playlist' => [], + 'track' => [] + ]; + + foreach ($users as $user) { + $cacheItems[$user->id] = [ + 'album' => [], + 'playlist' => [], + 'track' => [], + ]; + } + + $logItems = DB::table('resource_log_items')->get(); + foreach ($logItems as $item) { + $type = ''; + $id = 0; + + if ($item->album_id) { + $type = 'album'; + $id = $item->album_id; + } else { + if ($item->playlist_id) { + $type = 'playlist'; + $id = $item->playlist_id; + } else { + if ($item->track_id) { + $type = 'track'; + $id = $item->track_id; + } + } + } + + $resource = $this->getCacheItem($resources, $type, $id); + + if ($item->user_id != null) { + $userResource = $this->getUserCacheItem($cacheItems, $item->user_id, $type, $id); + + if ($item->log_type == ResourceLogItem::DOWNLOAD) { + $userResource['download_count']++; + } else { + if ($item->log_type == ResourceLogItem::VIEW) { + $userResource['view_count']++; + } else { + if ($item->log_type == ResourceLogItem::PLAY) { + $userResource['play_count']++; + } + } + } + + $cacheItems[$item->user_id][$type][$id] = $userResource; + } + + if ($item->log_type == ResourceLogItem::DOWNLOAD) { + $resource['download_count']++; + } else { + if ($item->log_type == ResourceLogItem::VIEW) { + $resource['view_count']++; + } else { + if ($item->log_type == ResourceLogItem::PLAY) { + $resource['play_count']++; + } + } + } + + $resources[$type][$id] = $resource; + } + + $pins = DB::table('pinned_playlists')->get(); + foreach ($pins as $pin) { + $userResource = $this->getUserCacheItem($cacheItems, $pin->user_id, 'playlist', $pin->playlist_id); + $userResource['is_pinned'] = true; + $cacheItems[$pin->user_id]['playlist'][$pin->playlist_id] = $userResource; + } + + $favs = DB::table('favourites')->get(); + foreach ($favs as $fav) { + $type = ''; + $id = 0; + + if ($fav->album_id) { + $type = 'album'; + $id = $fav->album_id; + } else { + if ($fav->playlist_id) { + $type = 'playlist'; + $id = $fav->playlist_id; + } else { + if ($fav->track_id) { + $type = 'track'; + $id = $fav->track_id; + } + } + } + + $userResource = $this->getUserCacheItem($cacheItems, $fav->user_id, $type, $id); + $userResource['is_favourited'] = true; + $cacheItems[$fav->user_id][$type][$id] = $userResource; + + $resource = $this->getCacheItem($resources, $type, $id); + $resource['favourite_count']++; + $resources[$type][$id] = $resource; + } + + foreach (DB::table('followers')->get() as $follower) { + $userResource = $this->getUserCacheItem($cacheItems, $follower->user_id, 'artist', $follower->artist_id); + $userResource['is_followed'] = true; + $cacheItems[$follower->user_id]['artist'][$follower->artist_id] = $userResource; + } + + foreach ($resources as $name => $resourceArray) { + foreach ($resourceArray as $id => $resource) { + DB::table($name . 's')->whereId($id)->update($resource); + } + } + + DB::table('resource_users')->delete(); + foreach ($cacheItems as $cacheItem) { + foreach ($cacheItem as $resources) { + foreach ($resources as $resource) { + DB::table('resource_users')->insert($resource); + } + } + } + } + + private function getCacheItem(&$resources, $type, $id) + { + if (!isset($resources[$type][$id])) { + $item = [ + 'view_count' => 0, + 'download_count' => 0, + 'favourite_count' => 0, + ]; + + if ($type == 'track') { + $item['play_count'] = 0; + } + + $resources[$type][$id] = $item; + + return $item; + } + + return $resources[$type][$id]; + } + + private function getUserCacheItem(&$items, $userId, $type, $id) + { + if (!isset($items[$userId][$type][$id])) { + $item = [ + 'is_followed' => false, + 'is_favourited' => false, + 'is_pinned' => false, + 'view_count' => 0, + 'play_count' => 0, + 'download_count' => 0, + 'user_id' => $userId + ]; + + $item[$type . '_id'] = $id; + + $items[$userId][$type][$id] = $item; + + return $item; + } + + return $items[$userId][$type][$id]; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php new file mode 100644 index 00000000..6e569828 --- /dev/null +++ b/app/Console/Kernel.php @@ -0,0 +1,32 @@ +belongsTo('App\User'); + } + + public function track() + { + return $this->belongsTo('App\Track'); + } + + public function album() + { + return $this->belongsTo('App\Album'); + } + + public function playlist() + { + return $this->belongsTo('App\Playlist'); + } + + /** + * Return the resource associated with this favourite. + * + * @return Resource|NULL + */ + public function getResourceAttribute() + { + if ($this->track_id) { + return $this->track; + } else { + if ($this->album_id) { + return $this->album; + } else { + if ($this->playlist_id) { + return $this->playlist; + } // no resource - this should never happen under real circumstances + else { + return null; + } + } + } + } + + public function getTypeAttribute() + { + return get_class($this->resource); + } +} \ No newline at end of file diff --git a/app/Follower.php b/app/Follower.php new file mode 100644 index 00000000..94f55059 --- /dev/null +++ b/app/Follower.php @@ -0,0 +1,12 @@ +slug != $slug) { + return Redirect::action('AlbumsController@getAlbum', [$id, $album->slug]); + } + + return View::make('albums.show'); + } + + public function getShortlink($id) + { + $album = Album::find($id); + if (!$album) { + App::abort(404); + } + + return Redirect::action('AlbumsController@getTrack', [$id, $album->slug]); + } + + public function getDownload($id, $extension) + { + $album = Album::with('tracks', 'user')->find($id); + if (!$album) { + 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('album', $id, ResourceLogItem::DOWNLOAD, $format['index']); + $downloader = new AlbumDownloader($album, $formatName); + $downloader->download(); + } +} \ No newline at end of file diff --git a/app/controllers/Api/Mobile/TracksController.php b/app/Http/Controllers/Api/Mobile/TracksController.php similarity index 88% rename from app/controllers/Api/Mobile/TracksController.php rename to app/Http/Controllers/Api/Mobile/TracksController.php index d6933a84..781c08d8 100644 --- a/app/controllers/Api/Mobile/TracksController.php +++ b/app/Http/Controllers/Api/Mobile/TracksController.php @@ -1,6 +1,10 @@ -published() + ->whereHash($hash)->first(); + + if (!$track) { + return Response::json(['message' => 'Track not found.'], 403); + } + + $comments = []; + foreach ($track->comments as $comment) { + $comments[] = [ + 'id' => $comment->id, + 'created_at' => $comment->created_at, + 'content' => $comment->content, + 'user' => [ + 'name' => $comment->user->display_name, + 'id' => $comment->user->id, + 'url' => $comment->user->url, + 'avatars' => [ + 'normal' => $comment->user->getAvatarUrl(Image::NORMAL), + 'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL), + 'small' => $comment->user->getAvatarUrl(Image::SMALL), + ] + ] + ]; + } + + return Response::json([ + 'id' => $track->id, + 'title' => $track->title, + 'description' => $track->description, + 'lyrics' => $track->lyrics, + 'user' => [ + 'id' => $track->user->id, + 'name' => $track->user->display_name, + 'url' => $track->user->url, + 'avatars' => [ + 'thumbnail' => $track->user->getAvatarUrl(Image::THUMBNAIL), + 'small' => $track->user->getAvatarUrl(Image::SMALL), + 'normal' => $track->user->getAvatarUrl(Image::NORMAL) + ] + ], + 'stats' => [ + 'views' => $track->view_count, + 'plays' => $track->play_count, + 'downloads' => $track->download_count, + 'comments' => $track->comment_count, + 'favourites' => $track->favourite_count + ], + 'url' => $track->url, + 'is_vocal' => !!$track->is_vocal, + 'is_explicit' => !!$track->is_explicit, + 'is_downloadable' => !!$track->is_downloadable, + 'published_at' => $track->published_at, + 'duration' => $track->duration, + 'genre' => $track->genre != null + ? + [ + 'id' => $track->genre->id, + 'name' => $track->genre->name + ] : null, + 'type' => [ + 'id' => $track->track_type->id, + 'name' => $track->track_type->title + ], + 'covers' => [ + 'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL), + 'small' => $track->getCoverUrl(Image::SMALL), + 'normal' => $track->getCoverUrl(Image::NORMAL) + ], + 'comments' => $comments + ], 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/AccountController.php b/app/Http/Controllers/Api/Web/AccountController.php new file mode 100644 index 00000000..462a71c9 --- /dev/null +++ b/app/Http/Controllers/Api/Web/AccountController.php @@ -0,0 +1,34 @@ + $user->bio, + 'can_see_explicit_content' => $user->can_see_explicit_content == 1, + 'display_name' => $user->display_name, + 'sync_names' => $user->sync_names == 1, + 'mlpforums_name' => $user->mlpforums_name, + 'gravatar' => $user->gravatar ? $user->gravatar : $user->email, + 'avatar_url' => !$user->uses_gravatar ? $user->getAvatarUrl() : null, + 'uses_gravatar' => $user->uses_gravatar == 1 + ], 200); + } + + public function postSave() + { + return $this->execute(new SaveAccountSettingsCommand(Input::all())); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/AlbumsController.php b/app/Http/Controllers/Api/Web/AlbumsController.php new file mode 100644 index 00000000..961caba6 --- /dev/null +++ b/app/Http/Controllers/Api/Web/AlbumsController.php @@ -0,0 +1,147 @@ +execute(new CreateAlbumCommand(Input::all())); + } + + public function postEdit($id) + { + return $this->execute(new EditAlbumCommand($id, Input::all())); + } + + public function postDelete($id) + { + return $this->execute(new DeleteAlbumCommand($id)); + } + + public function getShow($id) + { + $album = Album::with([ + 'tracks' => function ($query) { + $query->userDetails(); + }, + 'tracks.cover', + 'tracks.genre', + 'tracks.user', + 'user', + 'comments', + 'comments.user' + ]) + ->userDetails() + ->find($id); + + if (!$album) { + App::abort(404); + } + + if (Input::get('log')) { + ResourceLogItem::logItem('album', $id, ResourceLogItem::VIEW); + $album->view_count++; + } + + $returned_album = Album::mapPublicAlbumShow($album); + if ($returned_album['is_downloadable'] == 0) { + unset($returned_album['formats']); + } + + return Response::json([ + 'album' => $returned_album + ], 200); + } + + public function getIndex() + { + $page = 1; + if (Input::has('page')) { + $page = Input::get('page'); + } + + $query = Album::summary() + ->with('user', 'user.avatar', 'cover') + ->userDetails() + ->orderBy('created_at', 'desc') + ->where('track_count', '>', 0); + + $count = $query->count(); + $perPage = 40; + + $query->skip(($page - 1) * $perPage)->take($perPage); + $albums = []; + + foreach ($query->get() as $album) { + $albums[] = Album::mapPublicAlbumSummary($album); + } + + return Response::json(["albums" => $albums, "current_page" => $page, "total_pages" => ceil($count / $perPage)], + 200); + } + + public function getOwned() + { + $query = Album::summary()->where('user_id', \Auth::user()->id)->orderBy('created_at', 'desc')->get(); + $albums = []; + foreach ($query as $album) { + $albums[] = [ + 'id' => $album->id, + 'title' => $album->title, + 'slug' => $album->slug, + 'created_at' => $album->created_at, + 'covers' => [ + 'small' => $album->getCoverUrl(Image::SMALL), + 'normal' => $album->getCoverUrl(Image::NORMAL) + ] + ]; + } + + return Response::json($albums, 200); + } + + public function getEdit($id) + { + $album = Album::with('tracks')->find($id); + if (!$album) { + return $this->notFound('Album ' . $id . ' not found!'); + } + + if ($album->user_id != Auth::user()->id) { + return $this->notAuthorized(); + } + + $tracks = []; + foreach ($album->tracks as $track) { + $tracks[] = [ + 'id' => $track->id, + 'title' => $track->title + ]; + } + + return Response::json([ + 'id' => $album->id, + 'title' => $album->title, + 'user_id' => $album->user_id, + 'slug' => $album->slug, + 'created_at' => $album->created_at, + 'published_at' => $album->published_at, + 'description' => $album->description, + 'cover_url' => $album->hasCover() ? $album->getCoverUrl(Image::NORMAL) : null, + 'real_cover_url' => $album->getCoverUrl(Image::NORMAL), + 'tracks' => $tracks + ], 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/ArtistsController.php b/app/Http/Controllers/Api/Web/ArtistsController.php new file mode 100644 index 00000000..a2a6e13f --- /dev/null +++ b/app/Http/Controllers/Api/Web/ArtistsController.php @@ -0,0 +1,197 @@ +first(); + if (!$user) { + App::abort(404); + } + + $favs = Favourite::whereUserId($user->id)->with([ + 'track.genre', + 'track.cover', + 'track.user', + 'album.cover', + 'album.user', + 'track' => function ($query) { + $query->userDetails(); + }, + 'album' => function ($query) { + $query->userDetails(); + } + ])->get(); + + $tracks = []; + $albums = []; + + foreach ($favs as $fav) { + if ($fav->type == 'App\Track') { + $tracks[] = Track::mapPublicTrackSummary($fav->track); + } else { + if ($fav->type == 'App\Album') { + $albums[] = Album::mapPublicAlbumSummary($fav->album); + } + } + } + + return Response::json([ + 'tracks' => $tracks, + 'albums' => $albums + ], 200); + } + + public function getContent($slug) + { + $user = User::whereSlug($slug)->first(); + if (!$user) { + App::abort(404); + } + + $query = Track::summary()->published()->listed()->explicitFilter()->with('genre', 'cover', + 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at'); + $tracks = []; + $singles = []; + + foreach ($query->get() as $track) { + if ($track->album_id != null) { + $tracks[] = Track::mapPublicTrackSummary($track); + } else { + $singles[] = Track::mapPublicTrackSummary($track); + } + } + + $query = Album::summary() + ->with('user') + ->orderBy('created_at', 'desc') + ->where('track_count', '>', 0) + ->whereUserId($user->id); + + $albums = []; + + foreach ($query->get() as $album) { + $albums[] = Album::mapPublicAlbumSummary($album); + } + + return Response::json(['singles' => $singles, 'albumTracks' => $tracks, 'albums' => $albums], 200); + } + + public function getShow($slug) + { + $user = User::whereSlug($slug) + ->userDetails() + ->with([ + 'comments' => function ($query) { + $query->with('user'); + } + ]) + ->first(); + if (!$user) { + App::abort(404); + } + + $trackQuery = Track::summary() + ->published() + ->explicitFilter() + ->listed() + ->with('genre', 'cover', 'user') + ->userDetails() + ->whereUserId($user->id) + ->whereNotNull('published_at') + ->orderBy('created_at', 'desc') + ->take(20); + + $latestTracks = []; + foreach ($trackQuery->get() as $track) { + $latestTracks[] = Track::mapPublicTrackSummary($track); + } + + $comments = []; + foreach ($user->comments as $comment) { + $comments[] = Comment::mapPublic($comment); + } + + $userData = [ + 'is_following' => false + ]; + + if ($user->users->count()) { + $userRow = $user->users[0]; + $userData = [ + 'is_following' => (bool)$userRow->is_followed + ]; + } + + return Response::json([ + 'artist' => [ + 'id' => (int)$user->id, + 'name' => $user->display_name, + 'slug' => $user->slug, + 'is_archived' => (bool)$user->is_archived, + 'avatars' => [ + 'small' => $user->getAvatarUrl(Image::SMALL), + 'normal' => $user->getAvatarUrl(Image::NORMAL) + ], + 'created_at' => $user->created_at, + 'followers' => [], + 'following' => [], + 'latest_tracks' => $latestTracks, + 'comments' => $comments, + 'bio' => $user->bio, + 'mlpforums_username' => $user->mlpforums_name, + 'message_url' => $user->message_url, + 'user_data' => $userData + ] + ], 200); + } + + public function getIndex() + { + $page = 1; + if (Input::has('page')) { + $page = Input::get('page'); + } + + $query = User::orderBy('created_at', 'desc') + ->where('track_count', '>', 0); + + $count = $query->count(); + $perPage = 40; + + $query->skip(($page - 1) * $perPage)->take($perPage); + $users = []; + + foreach ($query->get() as $user) { + $users[] = [ + 'id' => $user->id, + 'name' => $user->display_name, + 'slug' => $user->slug, + 'url' => $user->url, + 'is_archived' => $user->is_archived, + 'avatars' => [ + 'small' => $user->getAvatarUrl(Image::SMALL), + 'normal' => $user->getAvatarUrl(Image::NORMAL) + ], + 'created_at' => $user->created_at + ]; + } + + return Response::json(["artists" => $users, "current_page" => $page, "total_pages" => ceil($count / $perPage)], + 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/AuthController.php b/app/Http/Controllers/Api/Web/AuthController.php new file mode 100644 index 00000000..ce347a04 --- /dev/null +++ b/app/Http/Controllers/Api/Web/AuthController.php @@ -0,0 +1,13 @@ +execute(new CreateCommentCommand($type, $id, Input::all())); + } + + public function getIndex($type, $id) + { + $column = ''; + + if ($type == 'track') { + $column = 'track_id'; + } else { + if ($type == 'user') { + $column = 'profile_id'; + } else { + if ($type == 'album') { + $column = 'album_id'; + } else { + if ($type == 'playlist') { + $column = 'playlist_id'; + } else { + App::abort(500); + } + } + } + } + + $query = Comment::where($column, '=', $id)->orderBy('created_at', 'desc')->with('user'); + $comments = []; + + foreach ($query->get() as $comment) { + $comments[] = Comment::mapPublic($comment); + } + + return Response::json(['list' => $comments, 'count' => count($comments)]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/DashboardController.php b/app/Http/Controllers/Api/Web/DashboardController.php new file mode 100644 index 00000000..727cacfd --- /dev/null +++ b/app/Http/Controllers/Api/Web/DashboardController.php @@ -0,0 +1,47 @@ +with(['genre', 'user', 'cover', 'user.avatar']) + ->whereIsLatest(true) + ->listed() + ->userDetails() + ->explicitFilter() + ->published() + ->orderBy('published_at', 'desc') + ->take(30); + + $recentTracks = []; + + foreach ($recentQuery->get() as $track) { + $recentTracks[] = Track::mapPublicTrackSummary($track); + } + + return Response::json([ + 'recent_tracks' => $recentTracks, + 'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content), + 'news' => News::getNews(0, 10) + ], 200); + } + + public function postReadNews() + { + News::markPostAsRead(Input::get('url')); + + return Response::json([ + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/FavouritesController.php b/app/Http/Controllers/Api/Web/FavouritesController.php new file mode 100644 index 00000000..ef7ac6e9 --- /dev/null +++ b/app/Http/Controllers/Api/Web/FavouritesController.php @@ -0,0 +1,110 @@ +execute(new ToggleFavouriteCommand(Input::get('type'), Input::get('id'))); + } + + public function getTracks() + { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('track_id') + ->with([ + 'track' => function ($query) { + $query + ->userDetails() + ->published(); + }, + 'track.user', + 'track.genre', + 'track.cover', + 'track.album', + 'track.album.user' + ]); + + $tracks = []; + + foreach ($query->get() as $fav) { + if ($fav->track == null) // deleted track + { + continue; + } + + $tracks[] = Track::mapPublicTrackSummary($fav->track); + } + + return Response::json(["tracks" => $tracks], 200); + } + + public function getAlbums() + { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('album_id') + ->with([ + 'album' => function ($query) { + $query->userDetails(); + }, + 'album.user', + 'album.user.avatar', + 'album.cover' + ]); + + $albums = []; + + foreach ($query->get() as $fav) { + if ($fav->album == null) // deleted album + { + continue; + } + + $albums[] = Album::mapPublicAlbumSummary($fav->album); + } + + return Response::json(["albums" => $albums], 200); + } + + public function getPlaylists() + { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('playlist_id') + ->with([ + 'playlist' => function ($query) { + $query->userDetails(); + }, + 'playlist.user', + 'playlist.user.avatar', + 'playlist.tracks', + 'playlist.tracks.cover' + ]); + + $playlists = []; + + foreach ($query->get() as $fav) { + if ($fav->playlist == null) // deleted playlist + { + continue; + } + + $playlists[] = Playlist::mapPublicPlaylistSummary($fav->playlist); + } + + return Response::json(["playlists" => $playlists], 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/FollowController.php b/app/Http/Controllers/Api/Web/FollowController.php new file mode 100644 index 00000000..fa73bff8 --- /dev/null +++ b/app/Http/Controllers/Api/Web/FollowController.php @@ -0,0 +1,15 @@ +execute(new ToggleFollowingCommand(Input::get('type'), Input::get('id'))); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/ImagesController.php b/app/Http/Controllers/Api/Web/ImagesController.php new file mode 100644 index 00000000..77b57433 --- /dev/null +++ b/app/Http/Controllers/Api/Web/ImagesController.php @@ -0,0 +1,31 @@ +id); + $images = []; + foreach ($query->get() as $image) { + $images[] = [ + 'id' => $image->id, + 'urls' => [ + 'small' => $image->getUrl(Image::SMALL), + 'normal' => $image->getUrl(Image::NORMAL), + 'thumbnail' => $image->getUrl(Image::THUMBNAIL), + 'original' => $image->getUrl(Image::ORIGINAL) + ], + 'filename' => $image->filename + ]; + } + + return Response::json($images, 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/PlaylistsController.php b/app/Http/Controllers/Api/Web/PlaylistsController.php new file mode 100644 index 00000000..b9667221 --- /dev/null +++ b/app/Http/Controllers/Api/Web/PlaylistsController.php @@ -0,0 +1,143 @@ +execute(new CreatePlaylistCommand(Input::all())); + } + + public function postEdit($id) + { + return $this->execute(new EditPlaylistCommand($id, Input::all())); + } + + public function postDelete($id) + { + return $this->execute(new DeletePlaylistCommand($id, Input::all())); + } + + public function postAddTrack($id) + { + return $this->execute(new AddTrackToPlaylistCommand($id, Input::get('track_id'))); + } + + public function getIndex() + { + $page = 1; + if (Input::has('page')) { + $page = Input::get('page'); + } + + $query = Playlist::summary() + ->with('user', 'user.avatar', 'tracks', 'tracks.cover', 'tracks.user', 'tracks.album', 'tracks.album.user') + ->userDetails() + ->orderBy('created_at', 'desc') + ->where('track_count', '>', 0) + ->whereIsPublic(true); + + $count = $query->count(); + $perPage = 40; + + $query->skip(($page - 1) * $perPage)->take($perPage); + $playlists = []; + + foreach ($query->get() as $playlist) { + $playlists[] = Playlist::mapPublicPlaylistSummary($playlist); + } + + return Response::json([ + "playlists" => $playlists, + "current_page" => $page, + "total_pages" => ceil($count / $perPage) + ], 200); + } + + public function getShow($id) + { + $playlist = Playlist::with([ + 'tracks.user', + 'tracks.genre', + 'tracks.cover', + 'tracks.album', + 'tracks' => function ($query) { + $query->userDetails(); + }, + 'comments', + 'comments.user' + ])->userDetails()->find($id); + if (!$playlist || !$playlist->canView(Auth::user())) { + App::abort('404'); + } + + if (Input::get('log')) { + ResourceLogItem::logItem('playlist', $id, ResourceLogItem::VIEW); + $playlist->view_count++; + } + + return Response::json(Playlist::mapPublicPlaylistShow($playlist), 200); + } + + public function getPinned() + { + $query = Playlist + ::userDetails() + ->with('tracks', 'tracks.cover', 'tracks.user', 'user') + ->join('pinned_playlists', function ($join) { + $join->on('playlist_id', '=', 'playlists.id'); + }) + ->where('pinned_playlists.user_id', '=', Auth::user()->id) + ->orderBy('title', 'asc') + ->select('playlists.*') + ->get(); + + $playlists = []; + foreach ($query as $playlist) { + $mapped = Playlist::mapPublicPlaylistSummary($playlist); + $mapped['description'] = $playlist->description; + $mapped['is_pinned'] = true; + $playlists[] = $mapped; + } + + return Response::json($playlists, 200); + } + + public function getOwned() + { + $query = Playlist::summary()->with('pins', 'tracks', 'tracks.cover')->where('user_id', + \Auth::user()->id)->orderBy('title', 'asc')->get(); + $playlists = []; + foreach ($query as $playlist) { + $playlists[] = [ + 'id' => $playlist->id, + 'title' => $playlist->title, + 'slug' => $playlist->slug, + 'created_at' => $playlist->created_at, + 'description' => $playlist->description, + 'url' => $playlist->url, + 'covers' => [ + 'small' => $playlist->getCoverUrl(Image::SMALL), + 'normal' => $playlist->getCoverUrl(Image::NORMAL) + ], + 'is_pinned' => $playlist->hasPinFor(Auth::user()->id), + 'is_public' => $playlist->is_public == 1 + ]; + } + + return Response::json($playlists, 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/ProfilerController.php b/app/Http/Controllers/Api/Web/ProfilerController.php new file mode 100644 index 00000000..1a2c81b2 --- /dev/null +++ b/app/Http/Controllers/Api/Web/ProfilerController.php @@ -0,0 +1,29 @@ + ProfileRequest::load($request)->toArray()], 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/TaxonomiesController.php b/app/Http/Controllers/Api/Web/TaxonomiesController.php new file mode 100644 index 00000000..1bc6f26d --- /dev/null +++ b/app/Http/Controllers/Api/Web/TaxonomiesController.php @@ -0,0 +1,26 @@ + License::all()->toArray(), + 'genres' => Genre::select('genres.*', + DB::raw('(SELECT COUNT(id) FROM tracks WHERE tracks.genre_id = genres.id AND tracks.published_at IS NOT NULL) AS track_count'))->orderBy('name')->get()->toArray(), + 'track_types' => TrackType::select('track_types.*', + DB::raw('(SELECT COUNT(id) FROM tracks WHERE tracks.track_type_id = track_types.id AND tracks.published_at IS NOT NULL) AS track_count'))->get()->toArray(), + 'show_songs' => ShowSong::select('title', 'id', 'slug', + DB::raw('(SELECT COUNT(tracks.id) FROM show_song_track INNER JOIN tracks ON tracks.id = show_song_track.track_id WHERE show_song_track.show_song_id = show_songs.id AND tracks.published_at IS NOT NULL) AS track_count'))->get()->toArray() + ], 200); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/Web/TracksController.php b/app/Http/Controllers/Api/Web/TracksController.php new file mode 100644 index 00000000..ebfc334f --- /dev/null +++ b/app/Http/Controllers/Api/Web/TracksController.php @@ -0,0 +1,159 @@ +execute(new UploadTrackCommand()); + } + + public function postDelete($id) + { + return $this->execute(new DeleteTrackCommand($id)); + } + + public function postEdit($id) + { + return $this->execute(new EditTrackCommand($id, Input::all())); + } + + public function getShow($id) + { + $track = Track::userDetails()->withComments()->find($id); + if (!$track || !$track->canView(Auth::user())) { + return $this->notFound('Track not found!'); + } + + if (Input::get('log')) { + ResourceLogItem::logItem('track', $id, ResourceLogItem::VIEW); + $track->view_count++; + } + + $returned_track = Track::mapPublicTrackShow($track); + if ($returned_track['is_downloadable'] != 1) { + unset($returned_track['formats']); + } + + return Response::json(['track' => $returned_track], 200); + } + + public function getIndex() + { + $page = 1; + $perPage = 45; + + if (Input::has('page')) { + $page = Input::get('page'); + } + + $query = Track::summary() + ->userDetails() + ->listed() + ->explicitFilter() + ->published() + ->with('user', 'genre', 'cover', 'album', 'album.user'); + + $this->applyFilters($query); + + $totalCount = $query->count(); + $query->take($perPage)->skip($perPage * ($page - 1)); + + $tracks = []; + $ids = []; + + foreach ($query->get(['tracks.*']) as $track) { + $tracks[] = Track::mapPublicTrackSummary($track); + $ids[] = $track->id; + } + + return Response::json([ + "tracks" => $tracks, + "current_page" => $page, + "total_pages" => ceil($totalCount / $perPage) + ], 200); + } + + public function getOwned() + { + $query = Track::summary()->where('user_id', \Auth::user()->id)->orderBy('created_at', 'desc'); + + $tracks = []; + foreach ($query->get() as $track) { + $tracks[] = Track::mapPrivateTrackSummary($track); + } + + return Response::json($tracks, 200); + } + + public function getEdit($id) + { + $track = Track::with('showSongs')->find($id); + if (!$track) { + return $this->notFound('Track ' . $id . ' not found!'); + } + + if ($track->user_id != Auth::user()->id) { + return $this->notAuthorized(); + } + + return Response::json(Track::mapPrivateTrackShow($track), 200); + } + + private function applyFilters($query) + { + if (Input::has('order')) { + $order = \Input::get('order'); + $parts = explode(',', $order); + $query->orderBy($parts[0], $parts[1]); + } + + if (Input::has('is_vocal')) { + $isVocal = \Input::get('is_vocal'); + if ($isVocal == 'true') { + $query->whereIsVocal(true); + } else { + $query->whereIsVocal(false); + } + } + + if (Input::has('in_album')) { + if (Input::get('in_album') == 'true') { + $query->whereNotNull('album_id'); + } else { + $query->whereNull('album_id'); + } + } + + if (Input::has('genres')) { + $query->whereIn('genre_id', Input::get('genres')); + } + + if (Input::has('types')) { + $query->whereIn('track_type_id', Input::get('types')); + } + + if (Input::has('songs')) { + $query->join('show_song_track', function ($join) { + $join->on('tracks.id', '=', 'show_song_track.track_id'); + }); + $query->whereIn('show_song_track.show_song_id', Input::get('songs')); + } + + return $query; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/ApiControllerBase.php b/app/Http/Controllers/ApiControllerBase.php new file mode 100644 index 00000000..00e62f24 --- /dev/null +++ b/app/Http/Controllers/ApiControllerBase.php @@ -0,0 +1,35 @@ +authorize()) { + return $this->notAuthorized(); + } + + $result = $command->execute(); + if ($result->didFail()) { + return Response::json([ + 'message' => 'Validation failed', + 'errors' => $result->getValidator()->messages()->getMessages() + ], 400); + } + + return Response::json($result->getResponse(), 200); + } + + public function notAuthorized() + { + return Response::json(['message' => 'You may not do this!'], 403); + } + + public function notFound($message) + { + return Response::json(['message' => $message], 403); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/ArtistsController.php b/app/Http/Controllers/ArtistsController.php new file mode 100644 index 00000000..2f29d6b3 --- /dev/null +++ b/app/Http/Controllers/ArtistsController.php @@ -0,0 +1,35 @@ +first(); + if (!$user) { + App::abort('404'); + } + + return View::make('artists.profile'); + } + + public function getShortlink($id) + { + $user = User::find($id); + if (!$user) { + App::abort('404'); + } + + return Redirect::action('ArtistsController@getProfile', [$id]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 00000000..dd3a31a2 --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,115 @@ +poniverse = new Poniverse(Config::get('poniverse.client_id'), Config::get('poniverse.secret')); + $this->poniverse->setRedirectUri(URL::to('/auth/oauth')); + } + + public function getLogin() + { + if (Auth::guest()) { + return Redirect::to($this->poniverse->getAuthenticationUrl('login')); + } + + return Redirect::to('/'); + } + + public function postLogout() + { + Auth::logout(); + + return Redirect::to('/'); + } + + public function getOAuth() + { + $code = $this->poniverse->getClient()->getAccessToken( + Config::get('poniverse.urls')['token'], + 'authorization_code', + [ + 'code' => Input::query('code'), + 'redirect_uri' => URL::to('/auth/oauth') + ]); + + if ($code['code'] != 200) { + if ($code['code'] == 400 && $code['result']['error_description'] == 'The authorization code has expired' && !isset($this->request['login_attempt'])) { + return Redirect::to($this->poniverse->getAuthenticationUrl('login_attempt')); + } + + return Redirect::to('/')->with('message', + 'Unfortunately we are having problems attempting to log you in at the moment. Please try again at a later time.'); + } + + $this->poniverse->setAccessToken($code['result']['access_token']); + $poniverseUser = $this->poniverse->getUser(); + $token = DB::table('oauth2_tokens')->where('external_user_id', '=', $poniverseUser['id'])->where('service', '=', + 'poniverse')->first(); + + $setData = [ + 'access_token' => $code['result']['access_token'], + 'expires' => date('Y-m-d H:i:s', strtotime("+" . $code['result']['expires_in'] . " Seconds", time())), + 'type' => $code['result']['token_type'], + ]; + + if (isset($code['result']['refresh_token']) && !empty($code['result']['refresh_token'])) { + $setData['refresh_token'] = $code['result']['refresh_token']; + } + + if ($token) { + //User already exists, update access token and refresh token if provided. + DB::table('oauth2_tokens')->where('id', '=', $token->id)->update($setData); + + return $this->loginRedirect(User::find($token->user_id)); + } + + //Check by email to see if they already have an account + $localMember = User::where('email', '=', $poniverseUser['email'])->first(); + + if ($localMember) { + return $this->loginRedirect($localMember); + } + + $user = new User; + + $user->mlpforums_name = $poniverseUser['username']; + $user->display_name = $poniverseUser['display_name']; + $user->email = $poniverseUser['email']; + $user->created_at = gmdate("Y-m-d H:i:s", time()); + $user->uses_gravatar = 1; + + $user->save(); + + //We need to insert a new token row :O + + $setData['user_id'] = $user->id; + $setData['external_user_id'] = $poniverseUser['id']; + $setData['service'] = 'poniverse'; + + DB::table('oauth2_tokens')->insert($setData); + + return $this->loginRedirect($user); + } + + protected function loginRedirect($user, $rememberMe = true) + { + Auth::login($user, $rememberMe); + + return Redirect::to('/'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/ContentController.php b/app/Http/Controllers/ContentController.php new file mode 100644 index 00000000..fd7182de --- /dev/null +++ b/app/Http/Controllers/ContentController.php @@ -0,0 +1,23 @@ +getFile($coverType['id']); + + if (!is_file($filename)) { + $redirect = URL::to('/images/icons/profile_' . Image::$ImageTypes[$coverType['id']]['name'] . '.png'); + + return Redirect::to($redirect); + } + + if (Config::get('app.sendfile')) { + $response->header('X-Sendfile', $filename); + } else { + $response->header('X-Accel-Redirect', $filename); + } + + $response->header('Content-Disposition', 'filename="' . $filename . '"'); + $response->header('Content-Type', 'image/png'); + + $lastModified = filemtime($filename); + + $response->header('Last-Modified', $lastModified); + $response->header('Cache-Control', 'max-age=' . (60 * 60 * 24 * 7)); + + return $response; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/PlaylistsController.php b/app/Http/Controllers/PlaylistsController.php new file mode 100644 index 00000000..13ee0dac --- /dev/null +++ b/app/Http/Controllers/PlaylistsController.php @@ -0,0 +1,70 @@ +canView(Auth::user())) { + App::abort(404); + } + + if ($playlist->slug != $slug) { + return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->slug]); + } + + return View::make('playlists.show'); + } + + public function getShortlink($id) + { + $playlist = Playlist::find($id); + if (!$playlist || !$playlist->canView(Auth::user())) { + App::abort(404); + } + + return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->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/Http/Controllers/TracksController.php b/app/Http/Controllers/TracksController.php new file mode 100644 index 00000000..cf5dc384 --- /dev/null +++ b/app/Http/Controllers/TracksController.php @@ -0,0 +1,153 @@ +published() + ->userDetails() + ->with( + 'user', + 'user.avatar', + 'genre' + )->first(); + + if (!$track || !$track->canView(Auth::user())) { + App::abort(404); + } + + $userData = [ + 'stats' => [ + 'views' => 0, + 'plays' => 0, + 'downloads' => 0 + ], + 'is_favourited' => false + ]; + + if ($track->users->count()) { + $userRow = $track->users[0]; + $userData = [ + 'stats' => [ + 'views' => $userRow->view_count, + 'plays' => $userRow->play_count, + 'downloads' => $userRow->download_count, + ], + 'is_favourited' => $userRow->is_favourited + ]; + } + + return View::make('tracks.embed', ['track' => $track, 'user' => $userData]); + } + + public function getTrack($id, $slug) + { + $track = Track::find($id); + if (!$track || !$track->canView(Auth::user())) { + App::abort(404); + } + + if ($track->slug != $slug) { + return Redirect::action('TracksController@getTrack', [$id, $track->slug]); + } + + return View::make('tracks.show'); + } + + public function getShortlink($id) + { + $track = Track::find($id); + if (!$track || !$track->canView(Auth::user())) { + App::abort(404); + } + + return Redirect::action('TracksController@getTrack', [$id, $track->slug]); + } + + public function getStream($id, $extension) + { + $track = Track::find($id); + if (!$track || !$track->canView(Auth::user())) { + App::abort(404); + } + + $trackFile = TrackFile::findOrFailByExtension($track->id, $extension); + ResourceLogItem::logItem('track', $id, ResourceLogItem::PLAY, $trackFile->getFormat()['index']); + + $response = Response::make('', 200); + $filename = $trackFile->getFile(); + + if (Config::get('app.sendfile')) { + $response->header('X-Sendfile', $filename); + } else { + $response->header('X-Accel-Redirect', $filename); + } + + $time = gmdate(filemtime($filename)); + + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $time == $_SERVER['HTTP_IF_MODIFIED_SINCE']) { + header('HTTP/1.0 304 Not Modified'); + exit(); + } + + $response->header('Last-Modified', $time); + $response->header('Content-Type', $trackFile->getFormat()['mime_type']); + + return $response; + } + + public function getDownload($id, $extension) + { + $track = Track::find($id); + if (!$track || !$track->canView(Auth::user())) { + App::abort(404); + } + + $trackFile = TrackFile::findOrFailByExtension($track->id, $extension); + ResourceLogItem::logItem('track', $id, ResourceLogItem::DOWNLOAD, $trackFile->getFormat()['index']); + + $response = Response::make('', 200); + $filename = $trackFile->getFile(); + + if (Config::get('app.sendfile')) { + $response->header('X-Sendfile', $filename); + $response->header('Content-Disposition', + 'attachment; filename="' . $trackFile->getDownloadFilename() . '"'); + } else { + $response->header('X-Accel-Redirect', $filename); + $response->header('Content-Disposition', + 'attachment; filename="' . $trackFile->getDownloadFilename() . '"'); + } + + $time = gmdate(filemtime($filename)); + + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $time == $_SERVER['HTTP_IF_MODIFIED_SINCE']) { + header('HTTP/1.0 304 Not Modified'); + exit(); + } + + $response->header('Last-Modified', $time); + $response->header('Content-Type', $trackFile->getFormat()['mime_type']); + + return $response; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/UploaderController.php b/app/Http/Controllers/UploaderController.php new file mode 100644 index 00000000..1d2d0089 --- /dev/null +++ b/app/Http/Controllers/UploaderController.php @@ -0,0 +1,13 @@ +getAvatarFile($coverType['id']), 'image/png', 'cover.png'); + } +} \ No newline at end of file diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php new file mode 100644 index 00000000..8436e93b --- /dev/null +++ b/app/Http/Kernel.php @@ -0,0 +1,34 @@ + \App\Http\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'csrf' => \App\Http\Middleware\VerifyCsrfHeader::class, + ]; +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php new file mode 100644 index 00000000..ffd3849d --- /dev/null +++ b/app/Http/Middleware/Authenticate.php @@ -0,0 +1,42 @@ +auth = $auth; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + if ($this->auth->guest()) { + return redirect()->guest('login'); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 00000000..3aa15f8d --- /dev/null +++ b/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ +auth = $auth; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + if ($this->auth->check()) { + return redirect('/home'); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/VerifyCsrfHeader.php b/app/Http/Middleware/VerifyCsrfHeader.php new file mode 100644 index 00000000..6a74f596 --- /dev/null +++ b/app/Http/Middleware/VerifyCsrfHeader.php @@ -0,0 +1,28 @@ +input('_token') && Session::token() != $request->header('X-Token')) { + throw new TokenMismatchException; + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 00000000..a2c35414 --- /dev/null +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ +where('id', '\d+'); +Route::get('a{id}/dl.{extension}', 'AlbumsController@getDownload' ); + +Route::get('artists', 'ArtistsController@getIndex'); +Route::get('playlists', 'PlaylistsController@getIndex'); + +Route::get('/register', 'AccountController@getRegister'); +Route::get('/login', 'AuthController@getLogin'); +Route::get('/auth/oauth', 'AuthController@getOAuth'); + +Route::get('/about', function() { return View::make('pages.about'); }); +Route::get('/faq', function() { return View::make('pages.faq'); }); + +Route::get('i{id}/{type}.png', 'ImagesController@getImage')->where('id', '\d+'); + +Route::get('u{id}/avatar_{type}.png', 'UsersController@getAvatar')->where('id', '\d+'); + +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/v1'], function() { + Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); + Route::post('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); +}); + +Route::group(['prefix' => 'api/web'], function() { + Route::get('/taxonomies/all', 'Api\Web\TaxonomiesController@getAll'); + + Route::get('/playlists/show/{id}', 'Api\Web\PlaylistsController@getShow'); + + Route::get('/tracks', 'Api\Web\TracksController@getIndex'); + Route::get('/tracks/{id}', 'Api\Web\TracksController@getShow')->where('id', '\d+'); + + Route::get('/albums', 'Api\Web\AlbumsController@getIndex'); + Route::get('/albums/{id}', 'Api\Web\AlbumsController@getShow')->where('id', '\d+'); + + Route::get('/playlists', 'Api\Web\PlaylistsController@getIndex'); + Route::get('/playlists/{id}', 'Api\Web\PlaylistsController@getShow')->where('id', '\d+'); + + Route::get('/comments/{type}/{id}', 'Api\Web\CommentsController@getIndex')->where('id', '\d+'); + + Route::get('/artists', 'Api\Web\ArtistsController@getIndex'); + Route::get('/artists/{slug}', 'Api\Web\ArtistsController@getShow'); + Route::get('/artists/{slug}/content', 'Api\Web\ArtistsController@getContent'); + Route::get('/artists/{slug}/favourites', 'Api\Web\ArtistsController@getFavourites'); + + Route::get('/dashboard', 'Api\Web\DashboardController@getIndex'); + + Route::group(['before' => 'auth|csrf'], function() { + Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload'); + Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete'); + Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@postEdit'); + + Route::post('/albums/create', 'Api\Web\AlbumsController@postCreate'); + Route::post('/albums/delete/{id}', 'Api\Web\AlbumsController@postDelete'); + Route::post('/albums/edit/{id}', 'Api\Web\AlbumsController@postEdit'); + + Route::post('/playlists/create', 'Api\Web\PlaylistsController@postCreate'); + Route::post('/playlists/delete/{id}', 'Api\Web\PlaylistsController@postDelete'); + Route::post('/playlists/edit/{id}', 'Api\Web\PlaylistsController@postEdit'); + Route::post('/playlists/{id}/add-track', 'Api\Web\PlaylistsController@postAddTrack'); + + Route::post('/comments/{type}/{id}', 'Api\Web\CommentsController@postCreate')->where('id', '\d+'); + + Route::post('/account/settings/save', 'Api\Web\AccountController@postSave'); + + Route::post('/favourites/toggle', 'Api\Web\FavouritesController@postToggle'); + + Route::post('/follow/toggle', 'Api\Web\FollowController@postToggle'); + + Route::post('/dashboard/read-news', 'Api\Web\DashboardController@postReadNews'); + }); + + Route::group(['before' => 'auth'], function() { + Route::get('/account/settings', 'Api\Web\AccountController@getSettings'); + + Route::get('/images/owned', 'Api\Web\ImagesController@getOwned'); + + Route::get('/tracks/owned', 'Api\Web\TracksController@getOwned'); + Route::get('/tracks/edit/{id}', 'Api\Web\TracksController@getEdit'); + + Route::get('/albums/owned', 'Api\Web\AlbumsController@getOwned'); + Route::get('/albums/edit/{id}', 'Api\Web\AlbumsController@getEdit'); + + Route::get('/playlists/owned', 'Api\Web\PlaylistsController@getOwned'); + Route::get('/playlists/pinned', 'Api\Web\PlaylistsController@getPinned'); + + Route::get('/favourites/tracks', 'Api\Web\FavouritesController@getTracks'); + Route::get('/favourites/albums', 'Api\Web\FavouritesController@getAlbums'); + Route::get('/favourites/playlists', 'Api\Web\FavouritesController@getPlaylists'); + }); + + Route::group(['before' => 'csrf'], function(){ + Route::post('/auth/logout', 'Api\Web\AuthController@postLogout'); + }); +}); + +Route::group(['prefix' => 'account'], function() { + Route::group(['before' => 'auth'], function(){ + Route::get('/favourites/tracks', 'FavouritesController@getTracks'); + Route::get('/favourites/albums', 'FavouritesController@getAlbums'); + Route::get('/favourites/playlists', 'FavouritesController@getPlaylists'); + + Route::get('/tracks', 'ContentController@getTracks'); + Route::get('/tracks/edit/{id}', 'ContentController@getTracks'); + Route::get('/albums', 'ContentController@getAlbums'); + Route::get('/albums/edit/{id}', 'ContentController@getAlbums'); + Route::get('/albums/create', 'ContentController@getAlbums'); + Route::get('/playlists', 'ContentController@getPlaylists'); + + Route::get('/uploader', 'UploaderController@getIndex'); + + Route::get('/', 'AccountController@getIndex'); + }); +}); + +Route::get('u{id}', 'ArtistsController@getShortlink')->where('id', '\d+'); +Route::get('users/{id}-{slug}', 'ArtistsController@getShortlink')->where('id', '\d+'); +Route::get('{slug}', 'ArtistsController@getProfile'); +Route::get('{slug}/content', 'ArtistsController@getProfile'); +Route::get('{slug}/favourites', 'ArtistsController@getProfile'); + +Route::get('/', 'HomeController@getIndex'); + +Route::group(['domain' => 'api.pony.fm'], function() { + Route::get('tracks/latest', ['uses' => 'Api\Mobile\TracksController@latest']); + Route::get('tracks/popular', [ 'uses' => 'Api\Mobile\TracksController@popular']); + /* Route::get('tracks/id', [ 'uses' => 'Api\Mobile\TracksController@track']); + Route::get('user', ['uses' => 'Api\Mobile\UserController@user']);*/ +}); diff --git a/app/Image.php b/app/Image.php new file mode 100644 index 00000000..14ba1e52 --- /dev/null +++ b/app/Image.php @@ -0,0 +1,117 @@ + ['id' => self::NORMAL, 'name' => 'normal', 'width' => 350, 'height' => 350], + self::ORIGINAL => ['id' => self::ORIGINAL, 'name' => 'original', 'width' => null, 'height' => null], + self::SMALL => ['id' => self::SMALL, 'name' => 'small', 'width' => 100, 'height' => 100], + self::THUMBNAIL => ['id' => self::THUMBNAIL, 'name' => 'thumbnail', 'width' => 50, 'height' => 50] + ]; + + public static function getImageTypeFromName($name) + { + foreach (self::$ImageTypes as $cover) { + if ($cover['name'] != $name) { + continue; + } + + return $cover; + } + + return null; + } + + public static function upload(UploadedFile $file, $user) + { + $userId = $user; + if ($user instanceof User) { + $userId = $user->id; + } + + $hash = md5_file($file->getPathname()); + $image = Image::whereHash($hash)->whereUploadedBy($userId)->first(); + + if ($image) { + return $image; + } + + $image = new Image(); + try { + $image->uploaded_by = $userId; + $image->size = $file->getSize(); + $image->filename = $file->getClientOriginalName(); + $image->extension = $file->getClientOriginalExtension(); + $image->mime = $file->getMimeType(); + $image->hash = $hash; + $image->save(); + + $image->ensureDirectoryExists(); + foreach (self::$ImageTypes as $coverType) { + $command = 'convert 2>&1 "' . $file->getPathname() . '" -background transparent -flatten +matte -strip -quality 95 -format png '; + if (isset($coverType['width']) && isset($coverType['height'])) { + $command .= '-thumbnail ' . $coverType['width'] . 'x' . $coverType['height'] . '^ -gravity center -extent ' . $coverType['width'] . 'x' . $coverType['height'] . ' '; + } + + $command .= '"' . $image->getFile($coverType['id']) . '"'; + External::execute($command); + } + + return $image; + } catch (\Exception $e) { + $image->delete(); + throw $e; + } + } + + protected $table = 'images'; + + public function getUrl($type = self::NORMAL) + { + $type = self::$ImageTypes[$type]; + + return URL::to('i' . $this->id . '/' . $type['name'] . '.png'); + } + + public function getFile($type = self::NORMAL) + { + return $this->getDirectory() . '/' . $this->getFilename($type); + } + + public function getFilename($type = self::NORMAL) + { + $typeInfo = self::$ImageTypes[$type]; + + return $this->id . '_' . $typeInfo['name'] . '.png'; + } + + public function getDirectory() + { + $dir = (string)(floor($this->id / 100) * 100); + + return Config::get('ponyfm.files_directory') . '/images/' . $dir; + } + + public function ensureDirectoryExists() + { + $destination = $this->getDirectory(); + umask(0); + + if (!is_dir($destination)) { + mkdir($destination, 0777, true); + } + } +} diff --git a/app/Jobs/Job.php b/app/Jobs/Job.php new file mode 100644 index 00000000..d99ae7e8 --- /dev/null +++ b/app/Jobs/Job.php @@ -0,0 +1,21 @@ +'; + } + + $scripts = self::mergeGlobs(self::getScriptsForArea($area)); + $retVal = ""; + + foreach ($scripts as $script) { + $filename = self::replaceExtensionWith($script, ".coffee", ".js"); + $retVal .= ""; + } + + return $retVal; + } + + public static function styleIncludes($area = 'app') + { + if (!Config::get("app.debug")) { + return ''; + } + + $styles = self::mergeGlobs(self::getStylesForArea($area)); + $retVal = ""; + + foreach ($styles as $style) { + $filename = self::replaceExtensionWith($style, ".less", ".css"); + $retVal .= ""; + } + + return $retVal; + } + + private static function replaceExtensionWith($filename, $fromExtension, $toExtension) + { + $fromLength = strlen($fromExtension); + + return substr($filename, -$fromLength) == $fromExtension + ? substr($filename, 0, strlen($filename) - $fromLength) . $toExtension + : $filename; + } + + /** Merges an array of paths that are passed into "glob" into a list of unique filenames. + * Note that this method assumes the globs should be relative to the "app" folder of this project */ + private static function mergeGlobs($globs) + { + $files = []; + $filesFound = []; + foreach ($globs as $glob) { + foreach (glob("../resources/assets/" . $glob, GLOB_BRACE) as $file) { + if (isset($filesFound[$file])) { + continue; + } + + $filesFound[$file] = true; + $files[] = substr($file, 20); // chop off ../app/ + } + } + return $files; + } + + private static function getScriptsForArea($area) + { + if ($area == 'app') { + return [ + "scripts/base/jquery-2.0.2.js", + "scripts/base/angular.js", + "scripts/base/*.{coffee,js}", + "scripts/shared/*.{coffee,js}", + "scripts/app/*.{coffee,js}", + "scripts/app/services/*.{coffee,js}", + "scripts/app/filters/*.{coffee,js}", + "scripts/app/directives/*.{coffee,js}", + "scripts/app/controllers/*.{coffee,js}", + "scripts/**/*.{coffee,js}" + ]; + } else { + if ($area == 'embed') { + return [ + "scripts/base/jquery-2.0.2.js", + "scripts/base/jquery.viewport.js", + "scripts/base/underscore.js", + "scripts/base/moment.js", + "scripts/base/jquery.timeago.js", + "scripts/base/soundmanager2-nodebug.js", + "scripts/embed/*.coffee" + ]; + } + } + + throw new Exception(); + } + + private static function getStylesForArea($area) + { + if ($area == 'app') { + return [ + "styles/base/jquery-ui.css", + "styles/base/colorbox.css", + "styles/app.less", + "styles/profiler.less" + ]; + } else { + if ($area == 'embed') { + return [ + "styles/embed.less" + ]; + } + } + + throw new Exception(); + } +} \ No newline at end of file diff --git a/app/Library/AudioCache.php b/app/Library/AudioCache.php new file mode 100644 index 00000000..fdf8f627 --- /dev/null +++ b/app/Library/AudioCache.php @@ -0,0 +1,19 @@ +_lastModified = $lastModified; + parent::__construct([], '', '', []); + } + + public function load(FilterInterface $additionalFilter = null) + { + } + + public function getLastModified() + { + return $this->_lastModified; + } +} diff --git a/app/Library/External.php b/app/Library/External.php new file mode 100644 index 00000000..0bd4e642 --- /dev/null +++ b/app/Library/External.php @@ -0,0 +1,16 @@ + + */ +class File extends \Illuminate\Support\Facades\File +{ + + public static function inline($path, $mime, $name = null) + { + if (is_null($name)) { + $name = basename($path); + } + + $response = Response::make(static::get($path)); + + $response->header('Content-Type', $mime); + $response->header('Content-Disposition', 'inline; filename="' . $name . '"'); + $response->header('Content-Transfer-Encoding', 'binary'); + $response->header('Expires', 0); + $response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); + $response->header('Pragma', 'public'); + $response->header('Content-Length', filesize($path)); + + return $response; + } + +} diff --git a/app/Library/Gravatar.php b/app/Library/Gravatar.php new file mode 100644 index 00000000..67c08de1 --- /dev/null +++ b/app/Library/Gravatar.php @@ -0,0 +1,30 @@ +format('c'); + } + + $title = date('c', strtotime($timestamp)); + $content = date('F d, o \@ g:i:s a', strtotime($timestamp)); + + return '' . $content . ''; + } +} \ No newline at end of file diff --git a/app/Library/IpsHasher.php b/app/Library/IpsHasher.php new file mode 100644 index 00000000..e103b2f8 --- /dev/null +++ b/app/Library/IpsHasher.php @@ -0,0 +1,35 @@ + $options['salt']]) === $hashedValue; + } + + public function needsRehash($hashedValue, array $options = array()) + { + return false; + } + + static public function ips_sanitize($value) + { + $value = str_replace('&', '&', $value); + $value = str_replace('\\', '\', $value); + $value = str_replace('!', '!', $value); + $value = str_replace('$', '$', $value); + $value = str_replace('"', '"', $value); + $value = str_replace('<', '<', $value); + $value = str_replace('>', '>', $value); + $value = str_replace('\'', ''', $value); + + return $value; + } +} \ No newline at end of file diff --git a/app/Library/PFMAuth.php b/app/Library/PFMAuth.php new file mode 100644 index 00000000..fd77170c --- /dev/null +++ b/app/Library/PFMAuth.php @@ -0,0 +1,26 @@ +getPathname()); + + return in_array($file->getAudioCodec(), $parameters); + } + + + /** + * Validate the sample rate of the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateSampleRate($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioSampleRate(), $parameters); + } + + + /** + * Validate the number of channels in the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateAudioChannels($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioChannels(), $parameters); + } + + + /** + * Validate the bit rate of the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateAudioBitrate($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioBitRate(), $parameters); + } + + + /** + * Validate the duration of the audio file, in seconds. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateMinDuration($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is an array containing one value: the minimum duration + $file = AudioCache::get($value->getPathname()); + + return $file->getDuration() >= (float)$parameters[0]; + } + + + /** + * Require a field when the value of another field matches a certain value. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + /** OLD CODE + * public function validate_required_when($attribute, $value, $parameters) + * { + * if ( Input::get($parameters[0]) === $parameters[1] && static::required($attribute, $value) ){ + * return true; + * + * } else { + * return false; + * } + * } + **/ + + // custom required_when validator + public function validateRequiredWhen($attribute, $value, $parameters) + { + if (Input::get($parameters[0]) == $parameters[1]) { + return $this->validate_required($attribute, $value); + } + + return true; + } + + + // custom image width validator + public function validateMinWidth($attribute, $value, $parameters) + { + return getimagesize($value->getPathname())[0] >= $parameters[0]; + } + + // custom image height validator + public function validateMinHeight($attribute, $value, $parameters) + { + return getimagesize($value->getPathname())[1] >= $parameters[0]; + } + + public function validateTextareaLength($attribute, $value, $parameters) + { + return strlen(str_replace("\r\n", "\n", $value)) <= $parameters[0]; + } +} \ No newline at end of file diff --git a/app/library/Poniverse/Poniverse.php b/app/Library/Poniverse/Poniverse.php similarity index 100% rename from app/library/Poniverse/Poniverse.php rename to app/Library/Poniverse/Poniverse.php diff --git a/app/library/Poniverse/autoloader.php b/app/Library/Poniverse/autoloader.php similarity index 100% rename from app/library/Poniverse/autoloader.php rename to app/Library/Poniverse/autoloader.php diff --git a/app/library/Poniverse/httpful/.gitignore b/app/Library/Poniverse/httpful/.gitignore similarity index 100% rename from app/library/Poniverse/httpful/.gitignore rename to app/Library/Poniverse/httpful/.gitignore diff --git a/app/library/Poniverse/httpful/.travis.yml b/app/Library/Poniverse/httpful/.travis.yml similarity index 100% rename from app/library/Poniverse/httpful/.travis.yml rename to app/Library/Poniverse/httpful/.travis.yml diff --git a/app/library/Poniverse/httpful/LICENSE.txt b/app/Library/Poniverse/httpful/LICENSE.txt similarity index 100% rename from app/library/Poniverse/httpful/LICENSE.txt rename to app/Library/Poniverse/httpful/LICENSE.txt diff --git a/app/library/Poniverse/httpful/README.md b/app/Library/Poniverse/httpful/README.md similarity index 100% rename from app/library/Poniverse/httpful/README.md rename to app/Library/Poniverse/httpful/README.md diff --git a/app/library/Poniverse/httpful/bootstrap.php b/app/Library/Poniverse/httpful/bootstrap.php similarity index 100% rename from app/library/Poniverse/httpful/bootstrap.php rename to app/Library/Poniverse/httpful/bootstrap.php diff --git a/app/library/Poniverse/httpful/build b/app/Library/Poniverse/httpful/build similarity index 100% rename from app/library/Poniverse/httpful/build rename to app/Library/Poniverse/httpful/build diff --git a/app/library/Poniverse/httpful/composer.json b/app/Library/Poniverse/httpful/composer.json similarity index 100% rename from app/library/Poniverse/httpful/composer.json rename to app/Library/Poniverse/httpful/composer.json diff --git a/app/library/Poniverse/httpful/examples/freebase.php b/app/Library/Poniverse/httpful/examples/freebase.php similarity index 100% rename from app/library/Poniverse/httpful/examples/freebase.php rename to app/Library/Poniverse/httpful/examples/freebase.php diff --git a/app/library/Poniverse/httpful/examples/github.php b/app/Library/Poniverse/httpful/examples/github.php similarity index 100% rename from app/library/Poniverse/httpful/examples/github.php rename to app/Library/Poniverse/httpful/examples/github.php diff --git a/app/library/Poniverse/httpful/examples/override.php b/app/Library/Poniverse/httpful/examples/override.php similarity index 100% rename from app/library/Poniverse/httpful/examples/override.php rename to app/Library/Poniverse/httpful/examples/override.php diff --git a/app/library/Poniverse/httpful/examples/showclix.php b/app/Library/Poniverse/httpful/examples/showclix.php similarity index 100% rename from app/library/Poniverse/httpful/examples/showclix.php rename to app/Library/Poniverse/httpful/examples/showclix.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Bootstrap.php b/app/Library/Poniverse/httpful/src/Httpful/Bootstrap.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Bootstrap.php rename to app/Library/Poniverse/httpful/src/Httpful/Bootstrap.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Exception/ConnectionErrorException.php b/app/Library/Poniverse/httpful/src/Httpful/Exception/ConnectionErrorException.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Exception/ConnectionErrorException.php rename to app/Library/Poniverse/httpful/src/Httpful/Exception/ConnectionErrorException.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/CsvHandler.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/CsvHandler.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/CsvHandler.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/CsvHandler.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/FormHandler.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/FormHandler.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/FormHandler.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/FormHandler.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/JsonHandler.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/JsonHandler.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/JsonHandler.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/JsonHandler.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/README.md b/app/Library/Poniverse/httpful/src/Httpful/Handlers/README.md similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/README.md rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/README.md diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/XHtmlHandler.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/XHtmlHandler.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/XHtmlHandler.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/XHtmlHandler.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Handlers/XmlHandler.php b/app/Library/Poniverse/httpful/src/Httpful/Handlers/XmlHandler.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Handlers/XmlHandler.php rename to app/Library/Poniverse/httpful/src/Httpful/Handlers/XmlHandler.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Http.php b/app/Library/Poniverse/httpful/src/Httpful/Http.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Http.php rename to app/Library/Poniverse/httpful/src/Httpful/Http.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Httpful.php b/app/Library/Poniverse/httpful/src/Httpful/Httpful.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Httpful.php rename to app/Library/Poniverse/httpful/src/Httpful/Httpful.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Mime.php b/app/Library/Poniverse/httpful/src/Httpful/Mime.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Mime.php rename to app/Library/Poniverse/httpful/src/Httpful/Mime.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Request.php b/app/Library/Poniverse/httpful/src/Httpful/Request.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Request.php rename to app/Library/Poniverse/httpful/src/Httpful/Request.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Response.php b/app/Library/Poniverse/httpful/src/Httpful/Response.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Response.php rename to app/Library/Poniverse/httpful/src/Httpful/Response.php diff --git a/app/library/Poniverse/httpful/src/Httpful/Response/Headers.php b/app/Library/Poniverse/httpful/src/Httpful/Response/Headers.php similarity index 100% rename from app/library/Poniverse/httpful/src/Httpful/Response/Headers.php rename to app/Library/Poniverse/httpful/src/Httpful/Response/Headers.php diff --git a/app/library/Poniverse/httpful/tests/Httpful/HttpfulTest.php b/app/Library/Poniverse/httpful/tests/Httpful/HttpfulTest.php similarity index 100% rename from app/library/Poniverse/httpful/tests/Httpful/HttpfulTest.php rename to app/Library/Poniverse/httpful/tests/Httpful/HttpfulTest.php diff --git a/app/library/Poniverse/httpful/tests/phpunit.xml b/app/Library/Poniverse/httpful/tests/phpunit.xml similarity index 100% rename from app/library/Poniverse/httpful/tests/phpunit.xml rename to app/Library/Poniverse/httpful/tests/phpunit.xml diff --git a/app/library/Poniverse/oauth2/Client.php b/app/Library/Poniverse/oauth2/Client.php similarity index 100% rename from app/library/Poniverse/oauth2/Client.php rename to app/Library/Poniverse/oauth2/Client.php diff --git a/app/library/Poniverse/oauth2/GrantType/AuthorizationCode.php b/app/Library/Poniverse/oauth2/GrantType/AuthorizationCode.php similarity index 100% rename from app/library/Poniverse/oauth2/GrantType/AuthorizationCode.php rename to app/Library/Poniverse/oauth2/GrantType/AuthorizationCode.php diff --git a/app/library/Poniverse/oauth2/GrantType/ClientCredentials.php b/app/Library/Poniverse/oauth2/GrantType/ClientCredentials.php similarity index 100% rename from app/library/Poniverse/oauth2/GrantType/ClientCredentials.php rename to app/Library/Poniverse/oauth2/GrantType/ClientCredentials.php diff --git a/app/library/Poniverse/oauth2/GrantType/IGrantType.php b/app/Library/Poniverse/oauth2/GrantType/IGrantType.php similarity index 100% rename from app/library/Poniverse/oauth2/GrantType/IGrantType.php rename to app/Library/Poniverse/oauth2/GrantType/IGrantType.php diff --git a/app/library/Poniverse/oauth2/GrantType/Password.php b/app/Library/Poniverse/oauth2/GrantType/Password.php similarity index 100% rename from app/library/Poniverse/oauth2/GrantType/Password.php rename to app/Library/Poniverse/oauth2/GrantType/Password.php diff --git a/app/library/Poniverse/oauth2/GrantType/RefreshToken.php b/app/Library/Poniverse/oauth2/GrantType/RefreshToken.php similarity index 100% rename from app/library/Poniverse/oauth2/GrantType/RefreshToken.php rename to app/Library/Poniverse/oauth2/GrantType/RefreshToken.php diff --git a/app/library/Poniverse/oauth2/README b/app/Library/Poniverse/oauth2/README similarity index 100% rename from app/library/Poniverse/oauth2/README rename to app/Library/Poniverse/oauth2/README diff --git a/app/library/Poniverse/oauth2/composer.json b/app/Library/Poniverse/oauth2/composer.json similarity index 100% rename from app/library/Poniverse/oauth2/composer.json rename to app/Library/Poniverse/oauth2/composer.json diff --git a/app/library/ZipStream.php b/app/Library/ZipStream.php similarity index 100% rename from app/library/ZipStream.php rename to app/Library/ZipStream.php diff --git a/app/License.php b/app/License.php new file mode 100644 index 00000000..734551b8 --- /dev/null +++ b/app/License.php @@ -0,0 +1,10 @@ +cache = false; + $feed->set_feed_url('http://mlpforums.com/blog/rss/404-ponyfm-development-blog/'); + $feed->init(); + $feed->handle_content_type(); + + $posts = $feed->get_items($start, $end); + $postHashes = []; + + foreach ($posts as $post) { + $postHashes[] = self::calculateHash($post->get_permalink()); + } + + if (count($postHashes) == 0) { + return []; + } + + $seenRecords = Auth::check() ? self::where('user_id', '=', Auth::user()->id)->whereIn('post_hash', + $postHashes)->get() : []; + $seenHashes = []; + + foreach ($seenRecords as $record) { + $seenHashes[$record->post_hash] = 1; + } + + $postsReturn = []; + + // This date is around when the last blog post was posted as of now. + // I put in a cutoff so that blog posts made before this update is pushed are always marked as 'read' + $readCutoffDate = mktime(null, null, null, 4, 28, 2013); + + foreach ($posts as $post) { + $autoRead = $post->get_date('U') < $readCutoffDate; + $postsReturn[] = [ + 'title' => $post->get_title(), + 'date' => $post->get_date('j F Y g:i a'), + 'url' => $post->get_permalink(), + 'read' => $autoRead || isset($seenHashes[self::calculateHash($post->get_permalink())]) + ]; + } + + return $postsReturn; + } + + public static function markPostAsRead($postUrl) + { + $postHash = self::calculateHash($postUrl); + $news = new News(); + $news->user_id = Auth::user()->id; + $news->post_hash = $postHash; + $news->save(); + } + + private static function calculateHash($postPermalink) + { + return md5($postPermalink); + } +} \ No newline at end of file diff --git a/app/PinnedPlaylist.php b/app/PinnedPlaylist.php new file mode 100644 index 00000000..1fc9b81b --- /dev/null +++ b/app/PinnedPlaylist.php @@ -0,0 +1,20 @@ +belongsTo('App\User'); + } + + public function playlist() + { + return $this->belongsTo('App\Playlist'); + } +} \ No newline at end of file diff --git a/app/Playlist.php b/app/Playlist.php new file mode 100644 index 00000000..63785991 --- /dev/null +++ b/app/Playlist.php @@ -0,0 +1,220 @@ +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; + $data['share'] = [ + 'url' => URL::to('/p' . $playlist->id), + 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($playlist->url) . '&name=' . urlencode($playlist->title) . '&description=' . urlencode($playlist->description), + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $playlist->title . ' by ' . $playlist->user->display_name . ' on Pony.fm' + ]; + + return $data; + } + + public static function mapPublicPlaylistSummary($playlist) + { + $userData = [ + 'stats' => [ + 'views' => 0, + 'downloads' => 0 + ], + 'is_favourited' => false + ]; + + if (Auth::check() && $playlist->users->count()) { + $userRow = $playlist->users[0]; + $userData = [ + 'stats' => [ + 'views' => (int) $userRow->view_count, + 'downloads' => (int) $userRow->download_count, + ], + 'is_favourited' => (bool) $userRow->is_favourited + ]; + } + + return [ + 'id' => (int) $playlist->id, + 'track_count' => $playlist->track_count, + 'title' => $playlist->title, + 'slug' => $playlist->slug, + 'created_at' => $playlist->created_at, + 'is_public' => (bool) $playlist->is_public, + 'stats' => [ + 'views' => (int) $playlist->view_count, + 'downloads' => (int) $playlist->download_count, + 'comments' => (int) $playlist->comment_count, + 'favourites' => (int) $playlist->favourite_count + ], + 'covers' => [ + 'small' => $playlist->getCoverUrl(Image::SMALL), + 'normal' => $playlist->getCoverUrl(Image::NORMAL) + ], + 'url' => $playlist->url, + 'user' => [ + 'id' => (int) $playlist->user->id, + 'name' => $playlist->user->display_name, + 'url' => $playlist->user->url, + ], + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $playlist->user_id, + 'edit' => Auth::check() && Auth::user()->id == $playlist->user_id + ] + ]; + } + + public function tracks() + { + return $this + ->belongsToMany('App\Track') + ->withPivot('position') + ->withTimestamps() + ->orderBy('position', 'asc'); + } + + public function users() + { + return $this->hasMany('App\ResourceUser'); + } + + public function comments() + { + return $this->hasMany('App\Comment')->orderBy('created_at', 'desc'); + } + + public function pins() + { + return $this->hasMany('App\PinnedPlaylist'); + } + + public function user() + { + return $this->belongsTo('App\User'); + } + + public function hasPinFor($userId) + { + foreach ($this->pins as $pin) { + if ($pin->user_id == $userId) { + return true; + } + } + + return false; + } + + public function canView($user) + { + return $this->is_public || ($user != null && $user->id == $this->user_id); + } + + public function getUrlAttribute() + { + 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; + 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) + { + if ($this->tracks->count() == 0) { + return $this->user->getAvatarUrl($type); + } + + return $this->tracks[0]->getCoverUrl($type); + } + + public function pin($userId) + { + $pin = new PinnedPlaylist(); + $pin->playlist_id = $this->id; + $pin->user_id = $userId; + $pin->save(); + } + + private function getCacheKey($key) + { + return 'playlist-' . $this->id . '-' . $key; + } +} \ No newline at end of file diff --git a/app/PlaylistDownloader.php b/app/PlaylistDownloader.php new file mode 100644 index 00000000..6194f3ba --- /dev/null +++ b/app/PlaylistDownloader.php @@ -0,0 +1,60 @@ +_playlist = $playlist; + $this->_format = $format; + } + + function download() + { + $zip = new ZipStream($this->_playlist->user->display_name . ' - ' . $this->_playlist->title . '.zip'); + $zip->setComment( + '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') . '.' + ); + + $notes = + '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" . + "\r\n" . + "\r\n" . + 'Tracks' . "\r\n" . + "\r\n"; + + $m3u = ''; + $index = 1; + foreach ($this->_playlist->tracks as $track) { + if (!$track->is_downloadable) { + continue; + } + + $trackTarget = $track->downloadDirectory . '/' . $track->getDownloadFilenameFor($this->_format); + $zip->addLargeFile($track->getFileFor($this->_format), $trackTarget); + $notes .= + $index . '. ' . $track->title . "\r\n" . + $track->description . "\r\n" . + "\r\n"; + + $m3u .= '#EXTINF:' . $track->duration . ',' . $track->title . "\r\n"; + $m3u .= '../' . $trackTarget . "\r\n"; + + $index++; + } + + $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/ProfileRequest.php b/app/ProfileRequest.php new file mode 100644 index 00000000..bf134ce1 --- /dev/null +++ b/app/ProfileRequest.php @@ -0,0 +1,75 @@ +_data = json_decode($data); + + return $req; + } + + public static function create() + { + $req = new ProfileRequest(); + $req->_id = uniqid(); + + return $req; + } + + private function __construct() + { + $this->_data = ['log' => []]; + } + + public function toArray() + { + return $this->_data; + } + + public function toString() + { + return json_encode($this->_data); + } + + public function getId() + { + return $this->_id; + } + + public function after($request, $response) + { + $this->_data['queries'] = []; + foreach (DB::getQueryLog() as $query) { + if (starts_with($query['query'], 'select * from `cache` where')) { + continue; + } + + if (starts_with($query['query'], 'delete from `cache` where')) { + continue; + } + + if (starts_with($query['query'], 'insert into `cache`')) { + continue; + } + + $this->_data['queries'][] = $query; + } + } + + public function log($level, $message, $context) + { + $this->_data['log'][] = [ + 'level' => $level, + 'message' => $message + ]; + } +} \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100644 index 00000000..ac62f504 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,43 @@ + [ + 'App\Listeners\EventListener', + ], + ]; + + /** + * Register any other events for your application. + * + * @param \Illuminate\Contracts\Events\Dispatcher $events + * @return void + */ + public function boot(DispatcherContract $events) + { + parent::boot($events); + + // + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php new file mode 100644 index 00000000..d50b1c0f --- /dev/null +++ b/app/Providers/RouteServiceProvider.php @@ -0,0 +1,44 @@ +group(['namespace' => $this->namespace], function ($router) { + require app_path('Http/routes.php'); + }); + } +} diff --git a/app/ResourceLogItem.php b/app/ResourceLogItem.php new file mode 100644 index 00000000..d361923a --- /dev/null +++ b/app/ResourceLogItem.php @@ -0,0 +1,84 @@ +{$resourceIdColumn} = $resourceId; + $logItem->created_at = time(); + $logItem->log_type = $logType; + $logItem->track_format_id = $formatId; + $logItem->ip_address = Request::getClientIp(); + + if (Auth::check()) { + $logItem->user_id = Auth::user()->id; + } + + $logItem->save(); + + $resourceTable = $resourceType . 's'; + $countColumn = ''; + + if ($logType == self::VIEW) { + $countColumn = 'view_count'; + } else { + if ($logType == self::DOWNLOAD) { + $countColumn = 'download_count'; + } else { + if ($logType == self::PLAY) { + $countColumn = 'play_count'; + } + } + } + + // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db + // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created + // for the same resource at the same time, the cached values will still be correct with this method. + + DB::table($resourceTable)->whereId($resourceId)->update([ + $countColumn => + DB::raw('(SELECT + COUNT(id) + FROM + resource_log_items + WHERE ' . + $resourceIdColumn . ' = ' . $resourceId . ' + AND + log_type = ' . $logType . ')') + ]); + + if (Auth::check()) { + $resourceUserId = ResourceUser::getId(Auth::user()->id, $resourceType, $resourceId); + DB::table('resource_users')->whereId($resourceUserId)->update([ + $countColumn => + DB::raw('(SELECT + COUNT(id) + FROM + resource_log_items + WHERE + user_id = ' . Auth::user()->id . ' + AND ' . + $resourceIdColumn . ' = ' . $resourceId . ' + AND + log_type = ' . $logType . ')') + ]); + } + } +} \ No newline at end of file diff --git a/app/ResourceUser.php b/app/ResourceUser.php new file mode 100644 index 00000000..2c22b314 --- /dev/null +++ b/app/ResourceUser.php @@ -0,0 +1,38 @@ +where('user_id', '=', $userId)->first(); + if ($existing) { + return $existing; + } + + $item = new ResourceUser(); + $item->{$resourceIdColumn} = $resourceId; + $item->user_id = $userId; + + return $item; + } + + public static function getId($userId, $resourceType, $resourceId) + { + $item = self::get($userId, $resourceType, $resourceId); + if ($item->exists) { + return $item->id; + } + + $item->save(); + + return $item->id; + } +} \ No newline at end of file diff --git a/app/ShowSong.php b/app/ShowSong.php new file mode 100644 index 00000000..293581c4 --- /dev/null +++ b/app/ShowSong.php @@ -0,0 +1,10 @@ + [ + 'index' => 0, + 'is_lossless' => true, + 'extension' => 'flac', + 'tag_format' => 'metaflac', + 'tag_method' => 'updateTagsWithGetId3', + 'mime_type' => 'audio/flac', + 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec flac -aq 8 -f flac {$target}' + ], + 'MP3' => [ + 'index' => 1, + 'is_lossless' => false, + 'extension' => 'mp3', + 'tag_format' => 'id3v2.3', + 'tag_method' => 'updateTagsWithGetId3', + 'mime_type' => 'audio/mpeg', + 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libmp3lame -ab 320k -f mp3 {$target}' + ], + 'OGG Vorbis' => [ + 'index' => 2, + 'is_lossless' => false, + 'extension' => 'ogg', + 'tag_format' => 'vorbiscomment', + 'tag_method' => 'updateTagsWithGetId3', + 'mime_type' => 'audio/ogg', + 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libvorbis -aq 7 -f ogg {$target}' + ], + 'AAC' => [ + 'index' => 3, + 'is_lossless' => false, + 'extension' => 'm4a', + 'tag_format' => 'AtomicParsley', + 'tag_method' => 'updateTagsWithAtomicParsley', + 'mime_type' => 'audio/mp4', + 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libfaac -ab 256k -f mp4 {$target}' + ], + 'ALAC' => [ + 'index' => 4, + 'is_lossless' => true, + 'extension' => 'alac.m4a', + 'tag_format' => 'AtomicParsley', + 'tag_method' => 'updateTagsWithAtomicParsley', + 'mime_type' => 'audio/mp4', + 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec alac {$target}' + ], + ]; + + public static function summary() + { + return self::select('id', 'title', 'user_id', 'slug', 'is_vocal', 'is_explicit', 'created_at', 'published_at', + 'duration', 'is_downloadable', 'genre_id', 'track_type_id', 'cover_id', 'album_id', 'comment_count', + 'download_count', 'view_count', 'play_count', 'favourite_count'); + } + + public function scopeUserDetails($query) + { + if (Auth::check()) { + $query->with([ + 'users' => function ($query) { + $query->whereUserId(Auth::user()->id); + } + ]); + } + } + + public function scopePublished($query) + { + $query->whereNotNull('published_at'); + } + + public function scopeListed($query) + { + $query->whereIsListed(true); + } + + public function scopeExplicitFilter($query) + { + if (!Auth::check() || !Auth::user()->can_see_explicit_content) { + $query->whereIsExplicit(false); + } + } + + public function scopeWithComments($query) + { + $query->with([ + 'comments' => function ($query) { + $query->with('user'); + } + ]); + } + + public static function popular($count, $allowExplicit = false) + { + $trackIds = Cache::remember('popular_tracks' . $count . '-' . ($allowExplicit ? 'explicit' : 'safe'), 5, + function () use ($allowExplicit, $count) { + $query = static + ::published() + ->listed() + ->join(DB::raw(' + ( SELECT `track_id`, `created_at` + FROM `resource_log_items` + WHERE track_id IS NOT NULL AND log_type = 3 AND `created_at` > now() - INTERVAL 1 DAY + ) AS ranged_plays'), + 'tracks.id', '=', 'ranged_plays.track_id') + ->groupBy('id') + ->orderBy('plays', 'desc') + ->take($count); + + if (!$allowExplicit) { + $query->whereIsExplicit(false); + } + + $results = []; + + foreach ($query->get(['*', DB::raw('count(*) as plays')]) as $track) { + $results[] = $track->id; + } + + return $results; + }); + + if (!count($trackIds)) { + return []; + } + + $tracks = Track::summary() + ->userDetails() + ->explicitFilter() + ->published() + ->with('user', 'genre', 'cover', 'album', 'album.user') + ->whereIn('id', $trackIds); + + $processed = []; + foreach ($tracks->get() as $track) { + $processed[] = Track::mapPublicTrackSummary($track); + } + + return $processed; + } + + public static function mapPublicTrackShow($track) + { + $returnValue = self::mapPublicTrackSummary($track); + $returnValue['description'] = $track->description; + $returnValue['lyrics'] = $track->lyrics; + + $comments = []; + + foreach ($track->comments as $comment) { + $comments[] = Comment::mapPublic($comment); + } + + $returnValue['comments'] = $comments; + + if ($track->album_id != null) { + $returnValue['album'] = [ + 'title' => $track->album->title, + 'url' => $track->album->url, + ]; + } + + $formats = []; + + foreach ($track->trackFiles as $trackFile) { + $formats[] = [ + 'name' => $trackFile->format, + 'extension' => $trackFile->extension, + 'url' => $trackFile->url, + 'size' => $trackFile->size + ]; + } + + $returnValue['share'] = [ + 'url' => URL::to('/t' . $track->id), + 'html' => '', + 'bbcode' => '[url=' . $track->url . '][img]' . $track->getCoverUrl() . '[/img][/url]', + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $track->title . ' by ' . $track->user->display_name . ' on Pony.fm' + ]; + + $returnValue['share']['tumblrUrl'] = 'http://www.tumblr.com/share/video?embed=' . urlencode($returnValue['share']['html']) . '&caption=' . urlencode($track->title); + + $returnValue['formats'] = $formats; + + return $returnValue; + } + + public static function mapPublicTrackSummary($track) + { + $userData = [ + 'stats' => [ + 'views' => 0, + 'plays' => 0, + 'downloads' => 0 + ], + 'is_favourited' => false + ]; + + if (Auth::check() && $track->users->count()) { + $userRow = $track->users[0]; + $userData = [ + 'stats' => [ + 'views' => (int) $userRow->view_count, + 'plays' => (int) $userRow->play_count, + 'downloads' => $userRow->download_count, + ], + 'is_favourited' => (bool) $userRow->is_favourited + ]; + } + + return [ + 'id' => (int) $track->id, + 'title' => $track->title, + 'user' => [ + 'id' => (int) $track->user->id, + 'name' => $track->user->display_name, + 'url' => $track->user->url + ], + 'stats' => [ + 'views' => (int) $track->view_count, + 'plays' => (int) $track->play_count, + 'downloads' => (int) $track->download_count, + 'comments' => (int) $track->comment_count, + 'favourites' => (int) $track->favourite_count + ], + 'url' => $track->url, + 'slug' => $track->slug, + 'is_vocal' => (bool) $track->is_vocal, + 'is_explicit' => (bool) $track->is_explicit, + 'is_downloadable' => (bool) $track->is_downloadable, + 'is_published' => (bool) $track->isPublished(), + 'published_at' => $track->published_at, + 'duration' => $track->duration, + 'genre' => $track->genre != null + ? + [ + 'id' => (int) $track->genre->id, + 'slug' => $track->genre->slug, + 'name' => $track->genre->name + ] : null, + 'track_type_id' => $track->track_type_id, + 'covers' => [ + 'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL), + 'small' => $track->getCoverUrl(Image::SMALL), + 'normal' => $track->getCoverUrl(Image::NORMAL) + ], + 'streams' => [ + 'mp3' => $track->getStreamUrl('MP3'), + 'aac' => (!Config::get('app.debug') || is_file($track->getFileFor('AAC'))) ? $track->getStreamUrl('AAC') : null, + 'ogg' => (Config::get('app.debug') || is_file($track->getFileFor('OGG Vorbis'))) ? $track->getStreamUrl('OGG Vorbis') : null + ], + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $track->user_id, + 'edit' => Auth::check() && Auth::user()->id == $track->user_id + ] + ]; + } + + public static function mapPrivateTrackShow($track) + { + $showSongs = []; + foreach ($track->showSongs as $showSong) { + $showSongs[] = ['id' => $showSong->id, 'title' => $showSong->title]; + } + + $returnValue = self::mapPrivateTrackSummary($track); + $returnValue['album_id'] = $track->album_id; + $returnValue['show_songs'] = $showSongs; + $returnValue['real_cover_url'] = $track->getCoverUrl(Image::NORMAL); + $returnValue['cover_url'] = $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null; + $returnValue['released_at'] = $track->released_at; + $returnValue['lyrics'] = $track->lyrics; + $returnValue['description'] = $track->description; + $returnValue['is_downloadable'] = !$track->isPublished() ? true : (bool)$track->is_downloadable; + $returnValue['license_id'] = $track->license_id != null ? $track->license_id : 3; + + return $returnValue; + } + + public static function mapPrivateTrackSummary($track) + { + return [ + 'id' => $track->id, + 'title' => $track->title, + 'user_id' => $track->user_id, + 'slug' => $track->slug, + 'is_vocal' => $track->is_vocal, + 'is_explicit' => $track->is_explicit, + 'is_downloadable' => $track->is_downloadable, + 'is_published' => $track->isPublished(), + 'created_at' => $track->created_at, + 'published_at' => $track->published_at, + 'duration' => $track->duration, + 'genre_id' => $track->genre_id, + 'track_type_id' => $track->track_type_id, + 'cover_url' => $track->getCoverUrl(Image::SMALL), + 'is_listed' => !!$track->is_listed + ]; + } + + protected $table = 'tracks'; + + public function genre() + { + return $this->belongsTo('App\Genre'); + } + + public function trackType() + { + return $this->belongsTo('App\TrackType', 'track_type_id'); + } + + public function comments() + { + return $this->hasMany('App\Comment')->orderBy('created_at', 'desc'); + } + + public function favourites() + { + return $this->hasMany('App\Favourite'); + } + + public function cover() + { + return $this->belongsTo('App\Image'); + } + + public function showSongs() + { + return $this->belongsToMany('App\ShowSong'); + } + + public function users() + { + return $this->hasMany('App\ResourceUser'); + } + + public function user() + { + return $this->belongsTo('App\User'); + } + + public function album() + { + return $this->belongsTo('App\Album'); + } + + public function trackFiles() + { + return $this->hasMany('App\TrackFile'); + } + + public function getYearAttribute() + { + return date('Y', strtotime($this->getReleaseDate())); + } + + public function setTitleAttribute($value) + { + $this->setTitleAttributeSlug($value);; + $this->updateHash(); + } + + public function getFilesize($formatName) + { + return Cache::remember($this->getCacheKey('filesize-' . $formatName), 1440, function () use ($formatName) { + $file = $this->getFileFor($formatName); + $size = 0; + + if (is_file($file)) { + $size = filesize($file); + } + + return $size; + }); + } + + public function canView($user) + { + if ($this->isPublished()) { + return true; + } + + return $this->user_id == $user->id; + } + + public function getUrlAttribute() + { + 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->released_at !== null) { + return $this->released_at; + } + + if ($this->published_at !== null) { + return Str::limit($this->published_at, 10, ''); + } + + return Str::limit($this->attributes['created_at'], 10, ''); + } + + public function ensureDirectoryExists() + { + $destination = $this->getDirectory(); + umask(0); + + if (!is_dir($destination)) { + mkdir($destination, 0777, true); + } + } + + public function hasCover() + { + return $this->cover_id != null; + } + + public function isPublished() + { + return $this->published_at != null && $this->deleted_at == null; + } + + public function getCoverUrl($type = Image::NORMAL) + { + if (!$this->hasCover()) { + if ($this->album_id != null) { + return $this->album->getCoverUrl($type); + } + + return $this->user->getAvatarUrl($type); + } + + return $this->cover->getUrl($type); + } + + public function getStreamUrl($format = 'MP3') + { + return URL::to('/t' . $this->id . '/stream.' . self::$Formats[$format]['extension']); + } + + public function getDirectory() + { + $dir = (string)(floor($this->id / 100) * 100); + + return \Config::get('ponyfm.files_directory') . '/tracks/' . $dir; + } + + public function getDates() + { + return ['created_at', 'deleted_at', 'published_at', 'released_at']; + } + + public function getFilenameFor($format) + { + if (!isset(self::$Formats[$format])) { + throw new Exception("$format is not a valid format!"); + } + + $format = self::$Formats[$format]; + + return "{$this->id}.{$format['extension']}"; + } + + public function getDownloadFilenameFor($format) + { + if (!isset(self::$Formats[$format])) { + throw new Exception("$format is not a valid format!"); + } + + $format = self::$Formats[$format]; + + return "{$this->title}.{$format['extension']}"; + } + + public function getFileFor($format) + { + if (!isset(self::$Formats[$format])) { + throw new Exception("$format is not a valid format!"); + } + + $format = self::$Formats[$format]; + + return "{$this->getDirectory()}/{$this->id}.{$format['extension']}"; + } + + public function getUrlFor($format) + { + if (!isset(self::$Formats[$format])) { + throw new Exception("$format is not a valid format!"); + } + + $format = self::$Formats[$format]; + + return URL::to('/t' . $this->id . '/dl.' . $format['extension']); + } + + public function updateHash() + { + $this->hash = md5(Helpers::sanitizeInputForHashing($this->user->display_name) . ' - ' . Helpers::sanitizeInputForHashing($this->title)); + } + + public function updateTags() + { + $this->trackFiles()->touch(); + + foreach ($this->trackFiles as $trackFile) { + $format = $trackFile->format; + $data = self::$Formats[$format]; + + $this->{$data['tag_method']}($format); + } + } + + /** @noinspection PhpUnusedPrivateMethodInspection */ + private function updateTagsWithAtomicParsley($format) + { + $command = 'AtomicParsley "' . $this->getFileFor($format) . '" '; + $command .= '--title ' . escapeshellarg($this->title) . ' '; + $command .= '--artist ' . escapeshellarg($this->user->display_name) . ' '; + $command .= '--year "' . $this->year . '" '; + $command .= '--genre ' . escapeshellarg($this->genre != null ? $this->genre->name : '') . ' '; + $command .= '--copyright ' . escapeshellarg('© ' . $this->year . ' ' . $this->user->display_name) . ' '; + $command .= '--comment "' . 'Downloaded from: https://pony.fm/' . '" '; + $command .= '--encodingTool "' . 'Pony.fm - https://pony.fm/' . '" '; + + if ($this->album_id !== null) { + $command .= '--album ' . escapeshellarg($this->album->title) . ' '; + $command .= '--tracknum ' . $this->track_number . ' '; + } + + if ($this->cover !== null) { + $command .= '--artwork ' . $this->cover->getFile() . ' '; + } + + $command .= '--overWrite'; + + External::execute($command); + } + + /** @noinspection PhpUnusedPrivateMethodInspection */ + private function updateTagsWithGetId3($format) + { + require_once(app_path() . '/Library/getid3/getid3/getid3.php'); + require_once(app_path() . '/Library/getid3/getid3/write.php'); + $tagWriter = new getid3_writetags; + + $tagWriter->overwrite_tags = true; + $tagWriter->tag_encoding = 'UTF-8'; + $tagWriter->remove_other_tags = true; + + $tagWriter->tag_data = [ + 'title' => [$this->title], + 'artist' => [$this->user->display_name], + 'year' => ['' . $this->year], + 'genre' => [$this->genre != null ? $this->genre->name : ''], + 'comment' => ['Downloaded from: https://pony.fm/'], + 'copyright' => ['© ' . $this->year . ' ' . $this->user->display_name], + 'publisher' => ['Pony.fm - https://pony.fm/'], + 'encoded_by' => ['https://pony.fm/'], +// 'url_artist' => [$this->user->url], +// 'url_source' => [$this->url], +// 'url_file' => [$this->url], + 'url_publisher' => ['https://pony.fm/'] + ]; + + if ($this->album_id !== null) { + $tagWriter->tag_data['album'] = [$this->album->title]; + $tagWriter->tag_data['track'] = [$this->track_number]; + } + + if ($format == 'MP3' && $this->cover_id != null && is_file($this->cover->getFile())) { + $tagWriter->tag_data['attached_picture'][0] = [ + 'data' => file_get_contents($this->cover->getFile()), + 'picturetypeid' => 2, + 'description' => 'cover', + 'mime' => 'image/png' + ]; + } + + $tagWriter->filename = $this->getFileFor($format); + $tagWriter->tagformats = [self::$Formats[$format]['tag_format']]; + + if ($tagWriter->WriteTags()) { + if (!empty($tagWriter->warnings)) { + Log::warning('Track #'.$this->id.': There were some warnings:
' . implode('

', $tagWriter->warnings)); + } + } else { + Log::error('Track #' . $this->id . ': Failed to write tags!
' . implode('

', $tagWriter->errors)); + } + } + + private function getCacheKey($key) + { + return 'track-' . $this->id . '-' . $key; + } +} diff --git a/app/TrackFile.php b/app/TrackFile.php new file mode 100644 index 00000000..741231a4 --- /dev/null +++ b/app/TrackFile.php @@ -0,0 +1,119 @@ +belongsTo('App\Track'); + } + + /** + * Look up and return a TrackFile by track ID and an extension. + * + * If the track does not have a TrackFile in the given extension's format, a 404 exception is thrown. + * + * @param int $trackId + * @param string $extension + * @return TrackFile + */ + public static function findOrFailByExtension($trackId, $extension) + { + // find the extension's format + $requestedFormatName = null; + foreach (Track::$Formats as $name => $format) { + if ($extension === $format['extension']) { + $requestedFormatName = $name; + break; + } + } + if ($requestedFormatName === null) { + App::abort(404); + } + + $trackFile = static:: + with('track') + ->where('track_id', $trackId) + ->where('format', $requestedFormatName) + ->first(); + + if ($trackFile === null) { + App::abort(404); + } else { + return $trackFile; + } + } + + public function getFormatAttribute($value) + { + return $value; + } + + public function getExtensionAttribute() + { + return Track::$Formats[$this->format]['extension']; + } + + public function getUrlAttribute() + { + return URL::to('/t' . $this->track_id . '/dl.' . $this->extension); + } + + public function getSizeAttribute($value) + { + return Helpers::formatBytes($this->getFilesize($this->getFile())); + } + + public function getFormat() + { + return Track::$Formats[$this->format]; + } + + protected function getFilesize() + { + return Cache::remember($this->getCacheKey('filesize'), 1440, function () { + $file = $this->getFile(); + $size = 0; + + if (is_file($file)) { + $size = filesize($file); + } + + return $size; + }); + } + + public function getDirectory() + { + $dir = (string)(floor($this->track_id / 100) * 100); + + return \Config::get('ponyfm.files_directory') . '/tracks/' . $dir; + } + + public function getFile() + { + return "{$this->getDirectory()}/{$this->track_id}.{$this->extension}"; + } + + public function getFilename() + { + return "{$this->track_id}.{$this->extension}"; + } + + public function getDownloadFilename() + { + return "{$this->track->title}.{$this->extension}"; + } + + private function getCacheKey($key) + { + return 'track_file-' . $this->id . '-' . $key; + } +} diff --git a/app/TrackType.php b/app/TrackType.php new file mode 100644 index 00000000..fc0437df --- /dev/null +++ b/app/TrackType.php @@ -0,0 +1,16 @@ +slug = Str::slug($value); + $this->attributes['title'] = $value; + } +} \ No newline at end of file diff --git a/app/User.php b/app/User.php new file mode 100644 index 00000000..7082ba94 --- /dev/null +++ b/app/User.php @@ -0,0 +1,147 @@ +with([ + 'users' => function ($query) { + $query->whereUserId(Auth::user()->id); + } + ]); + } + + return !$query; + } + + public function avatar() + { + return $this->belongsTo('App\Image'); + } + + public function users() + { + return $this->hasMany('App\ResourceUser', 'artist_id'); + } + + public function comments() + { + return $this->hasMany('App\Comment', 'profile_id')->orderBy('created_at', 'desc'); + } + + public function getIsArchivedAttribute() + { + return (bool)$this->attributes['is_archived']; + } + + public function getUrlAttribute() + { + return URL::to('/' . $this->slug); + } + + public function getMessageUrlAttribute() + { + return 'http://mlpforums.com/index.php?app=members&module=messaging§ion=send&do=form&fromMemberID=' . $this->id; + } + + public function getAuthIdentifier() + { + return $this->getKey(); + } + + public function getAuthPassword() + { + return $this->password_hash; + } + + public function getReminderEmail() + { + return $this->email; + } + + public function setDisplayNameAttribute($value) + { + $this->attributes['display_name'] = $value; + $this->attributes['slug'] = Str::slug($value); + } + + public function getAvatarUrl($type = Image::NORMAL) + { + if (!$this->uses_gravatar) { + return $this->avatar->getUrl($type); + } + + if ($this->email == "redacted@example.net") { + return Gravatar::getUrl($this->id . "", Image::$ImageTypes[$type]['width'], "identicon"); + } + + $email = $this->gravatar; + + if (!strlen($email)) { + $email = $this->email; + } + + return Gravatar::getUrl($email, Image::$ImageTypes[$type]['width']); + } + + public function getAvatarFile($type = Image::NORMAL) + { + if ($this->uses_gravatar) { + throw new Exception('Cannot get avatar file if this user is configured to use Gravatar!'); + } + + $imageType = Image::$ImageTypes[$type]; + + return URL::to('t' . $this->id . '/cover_' . $imageType['name'] . '.png?' . $this->cover_id); + } + + /** + * Get the token value for the "remember me" session. + * + * @return string + */ + public function getRememberToken() + { + return $this->remember_token; + } + + /** + * Set the token value for the "remember me" session. + * + * @param string $value + * @return void + */ + public function setRememberToken($value) + { + $this->remember_token = $value; + } + + /** + * Get the column name for the "remember me" token. + * + * @return string + */ + public function getRememberTokenName() + { + return "remember_token"; + } +} \ No newline at end of file diff --git a/app/commands/MigrateOldData.php b/app/commands/MigrateOldData.php deleted file mode 100644 index 5f470fd5..00000000 --- a/app/commands/MigrateOldData.php +++ /dev/null @@ -1,354 +0,0 @@ -disableQueryLog(); - - $oldDb = DB::connection('old'); - - $this->call('migrate:refresh'); - - $oldUsers = $oldDb->table('users')->get(); - $this->info('Syncing Users'); - foreach ($oldUsers as $user) { - $displayName = $user->display_name; - if (!$displayName) - $displayName = $user->username; - - if (!$displayName) - $displayName = $user->mlpforums_name; - - if (!$displayName) - continue; - - DB::table('users')->insert([ - 'id' => $user->id, - 'display_name' => $displayName, - 'email' => $user->email, - 'created_at' => $user->created_at, - 'updated_at' => $user->updated_at, - 'slug' => $user->slug, - 'bio' => $user->bio, - 'sync_names' => $user->sync_names, - 'can_see_explicit_content' => $user->can_see_explicit_content, - 'mlpforums_name' => $user->mlpforums_name, - 'uses_gravatar' => $user->uses_gravatar, - 'gravatar' => $user->gravatar, - 'avatar_id' => null - ]); - - $coverId = null; - if (!$user->uses_gravatar) { - try { - $coverFile = $this->getIdDirectory('users', $user->id) . '/' . $user->id . '_.png'; - $coverId = \Entities\Image::upload(new Symfony\Component\HttpFoundation\File\UploadedFile($coverFile, $user->id . '_.png'), $user->id)->id; - DB::table('users')->where('id', $user->id)->update(['avatar_id' => $coverId]); - } catch (\Exception $e) { - $this->error('Could copy user avatar ' . $user->id . ' because ' . $e->getMessage()); - DB::table('users')->where('id', $user->id)->update(['uses_gravatar' => true]); - } - } - } - - $this->info('Syncing Genres'); - $oldGenres = $oldDb->table('genres')->get(); - foreach ($oldGenres as $genre) { - DB::table('genres')->insert([ - 'id' => $genre->id, - 'name' => $genre->title, - 'slug' => $genre->slug - ]); - } - - $this->info('Syncing Albums'); - $oldAlbums = $oldDb->table('albums')->get(); - foreach ($oldAlbums as $playlist) { - $logViews = $oldDb->table('album_log_views')->whereAlbumId($playlist->id)->get(); - $logDownload = $oldDb->table('album_log_downloads')->whereAlbumId($playlist->id)->get(); - - DB::table('albums')->insert([ - 'title' => $playlist->title, - 'description' => $playlist->description, - 'created_at' => $playlist->created_at, - 'updated_at' => $playlist->updated_at, - 'deleted_at' => $playlist->deleted_at, - 'slug' => $playlist->slug, - 'id' => $playlist->id, - 'user_id' => $playlist->user_id, - 'view_count' => 0, - 'download_count' => 0 - ]); - - foreach ($logViews as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::VIEW, - 'album_id' => $logItem->album_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address, - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for album ' . $playlist->id . ' because ' . $e->getMessage()); - } - } - - foreach ($logDownload as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::DOWNLOAD, - 'album_id' => $logItem->album_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address, - 'track_format_id' => $logItem->track_file_format_id - 1 - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for album ' . $playlist->id . ' because ' . $e->getMessage()); - } - } - } - - $this->info('Syncing Tracks'); - $oldTracks = $oldDb->table('tracks')->get(); - foreach ($oldTracks as $track) { - $coverId = null; - if ($track->cover) { - try { - $coverFile = $this->getIdDirectory('tracks', $track->id) . '/' . $track->id . '_' . $track->cover . '.png'; - $coverId = \Entities\Image::upload(new Symfony\Component\HttpFoundation\File\UploadedFile($coverFile, $track->id . '_' . $track->cover . '.png'), $track->user_id)->id; - } catch (\Exception $e) { - $this->error('Could copy track cover ' . $track->id . ' because ' . $e->getMessage()); - } - } - - $trackLogViews = $oldDb->table('track_log_views')->whereTrackId($track->id)->get(); - $trackLogPlays = $oldDb->table('track_log_plays')->whereTrackId($track->id)->get(); - $trackLogDownload = $oldDb->table('track_log_downloads')->whereTrackId($track->id)->get(); - - DB::table('tracks')->insert([ - 'id' => $track->id, - 'title' => $track->title, - 'slug' => $track->slug, - 'description' => $track->description, - 'lyrics' => $track->lyrics, - 'created_at' => $track->created_at, - 'deleted_at' => $track->deleted_at, - 'updated_at' => $track->updated_at, - 'released_at' => $track->released_at, - 'published_at' => $track->published_at, - 'genre_id' => $track->genre_id, - 'is_explicit' => $track->explicit, - 'is_downloadable' => $track->downloadable, - 'is_vocal' => $track->is_vocal, - 'track_type_id' => $track->track_type_id, - 'track_number' => $track->track_number, - 'user_id' => $track->user_id, - 'album_id' => $track->album_id, - 'cover_id' => $coverId, - 'license_id' => $track->license_id, - 'duration' => $track->duration, - 'view_count' => 0, - 'play_count' => 0, - 'download_count' => 0 - ]); - - foreach ($trackLogViews as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::VIEW, - 'track_id' => $logItem->track_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); - } - } - - foreach ($trackLogPlays as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::PLAY, - 'track_id' => $logItem->track_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); - } - } - - foreach ($trackLogDownload as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::DOWNLOAD, - 'track_id' => $logItem->track_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address, - 'track_format_id' => $logItem->track_file_format_id - 1 - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for track ' . $track->id . ' because ' . $e->getMessage()); - } - } - } - - $oldShowSongs = $oldDb->table('song_track')->get(); - foreach ($oldShowSongs as $song) { - try { - DB::table('show_song_track')->insert([ - 'id' => $song->id, - 'show_song_id' => $song->song_id, - 'track_id' => $song->track_id - ]); - } catch (\Exception $e) { - $this->error('Could insert show track item for ' . $song->track_id . ' because ' . $e->getMessage()); - } - } - - $this->info('Syncing Playlists'); - $oldPlaylists = $oldDb->table('playlists')->get(); - foreach ($oldPlaylists as $playlist) { - $logViews = $oldDb->table('playlist_log_views')->wherePlaylistId($playlist->id)->get(); - $logDownload = $oldDb->table('playlist_log_downloads')->wherePlaylistId($playlist->id)->get(); - - DB::table('playlists')->insert([ - 'title' => $playlist->title, - 'description' => $playlist->description, - 'created_at' => $playlist->created_at, - 'updated_at' => $playlist->updated_at, - 'deleted_at' => $playlist->deleted_at, - 'slug' => $playlist->slug, - 'id' => $playlist->id, - 'user_id' => $playlist->user_id, - 'is_public' => true, - 'view_count' => 0, - 'download_count' => 0, - ]); - - foreach ($logViews as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::VIEW, - 'playlist_id' => $logItem->playlist_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address, - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for playlist ' . $playlist->id . ' because ' . $e->getMessage()); - } - } - - foreach ($logDownload as $logItem) { - try { - DB::table('resource_log_items')->insert([ - 'user_id' => $logItem->user_id, - 'log_type' => \Entities\ResourceLogItem::DOWNLOAD, - 'playlist_id' => $logItem->playlist_id, - 'created_at' => $logItem->created_at, - 'ip_address' => $logItem->ip_address, - 'track_format_id' => $logItem->track_file_format_id - 1 - ]); - } catch (\Exception $e) { - $this->error('Could insert log item for playlist ' . $playlist->id . ' because ' . $e->getMessage()); - } - } - } - - $this->info('Syncing Playlist Tracks'); - $oldPlaylistTracks = $oldDb->table('playlist_track')->get(); - foreach ($oldPlaylistTracks as $playlistTrack) { - DB::table('playlist_track')->insert([ - 'id' => $playlistTrack->id, - 'created_at' => $playlistTrack->created_at, - 'updated_at' => $playlistTrack->updated_at, - 'position' => $playlistTrack->position, - 'playlist_id' => $playlistTrack->playlist_id, - 'track_id' => $playlistTrack->track_id - ]); - } - - $this->info('Syncing Comments'); - $oldComments = $oldDb->table('comments')->get(); - foreach ($oldComments as $comment) { - try { - DB::table('comments')->insert([ - 'id' => $comment->id, - 'user_id' => $comment->user_id, - 'created_at' => $comment->created_at, - 'deleted_at' => $comment->deleted_at, - 'updated_at' => $comment->updated_at, - 'content' => $comment->content, - 'track_id' => $comment->track_id, - 'album_id' => $comment->album_id, - 'playlist_id' => $comment->playlist_id, - 'profile_id' => $comment->profile_id - ]); - } catch (Exception $e) { - $this->error('Could not sync comment ' . $comment->id . ' because ' . $e->getMessage()); - } - } - - $this->info('Syncing Favourites'); - $oldFavs = $oldDb->table('favourites')->get(); - foreach ($oldFavs as $fav) { - try { - DB::table('favourites')->insert([ - 'id' => $fav->id, - 'user_id' => $fav->user_id, - 'created_at' => $fav->created_at, - 'track_id' => $fav->track_id, - 'album_id' => $fav->album_id, - 'playlist_id' => $fav->playlist_id, - ]); - } catch (Exception $e) { - $this->error('Could not sync favourite ' . $fav->id . ' because ' . $e->getMessage()); - } - } - - $this->info('Syncing Followers'); - $oldFollowers = $oldDb->table('user_follower')->get(); - foreach ($oldFollowers as $follower) { - try { - DB::table('followers')->insert([ - 'id' => $follower->id, - 'user_id' => $follower->follower_id, - 'artist_id' => $follower->user_id, - 'created_at' => $follower->created_at, - ]); - } catch (Exception $e) { - $this->error('Could not sync follower ' . $follower->id . ' because ' . $e->getMessage()); - } - } - } - - private function getIdDirectory($type, $id) { - $dir = (string) ( floor( $id / 100 ) * 100 ); - return \Config::get('app.files_directory') . '/' . $type . '/' . $dir; - } - - protected function getArguments() { - return []; - } - - protected function getOptions() { - return []; - } - } \ No newline at end of file diff --git a/app/commands/RefreshCache.php b/app/commands/RefreshCache.php deleted file mode 100644 index 34a48f5d..00000000 --- a/app/commands/RefreshCache.php +++ /dev/null @@ -1,202 +0,0 @@ -disableQueryLog(); - - DB::table('tracks')->update(['comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.track_id = tracks.id AND deleted_at IS NULL)')]); - - DB::table('albums')->update([ - 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.album_id = albums.id AND deleted_at IS NULL)'), - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = albums.id)') - ]); - - DB::table('playlists')->update([ - 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.playlist_id = playlists.id AND deleted_at IS NULL)'), - 'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = playlists.id)') - ]); - - DB::table('users')->update([ - 'comment_count' => DB::raw('(SELECT COUNT(id) FROM comments WHERE comments.profile_id = users.id AND deleted_at IS NULL)'), - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE deleted_at IS NULL AND published_at IS NOT NULL AND user_id = users.id)') - ]); - - $users = DB::table('users')->get(); - $cacheItems = []; - $resources = [ - 'album' => [], - 'playlist' => [], - 'track' => [] - ]; - - foreach ($users as $user) { - $cacheItems[$user->id] = [ - 'album' => [], - 'playlist' => [], - 'track' => [], - ]; - } - - $logItems = DB::table('resource_log_items')->get(); - foreach ($logItems as $item) { - $type = ''; - $id = 0; - - if ($item->album_id) { - $type = 'album'; - $id = $item->album_id; - } - else if ($item->playlist_id) { - $type = 'playlist'; - $id = $item->playlist_id; - } - else if ($item->track_id) { - $type = 'track'; - $id = $item->track_id; - } - - $resource = $this->getCacheItem($resources, $type, $id); - - if ($item->user_id != null) { - $userResource = $this->getUserCacheItem($cacheItems, $item->user_id, $type, $id); - - if ($item->log_type == \Entities\ResourceLogItem::DOWNLOAD) { - $userResource['download_count']++; - } - else if ($item->log_type == \Entities\ResourceLogItem::VIEW) { - $userResource['view_count']++; - } - else if ($item->log_type == \Entities\ResourceLogItem::PLAY) { - $userResource['play_count']++; - } - - $cacheItems[$item->user_id][$type][$id] = $userResource; - } - - if ($item->log_type == \Entities\ResourceLogItem::DOWNLOAD) { - $resource['download_count']++; - } - else if ($item->log_type == \Entities\ResourceLogItem::VIEW) { - $resource['view_count']++; - } - else if ($item->log_type == \Entities\ResourceLogItem::PLAY) { - $resource['play_count']++; - } - - $resources[$type][$id] = $resource; - } - - $pins = DB::table('pinned_playlists')->get(); - foreach ($pins as $pin) { - $userResource = $this->getUserCacheItem($cacheItems, $pin->user_id, 'playlist', $pin->playlist_id); - $userResource['is_pinned'] = true; - $cacheItems[$pin->user_id]['playlist'][$pin->playlist_id] = $userResource; - } - - $favs = DB::table('favourites')->get(); - foreach ($favs as $fav) { - $type = ''; - $id = 0; - - if ($fav->album_id) { - $type = 'album'; - $id = $fav->album_id; - } - else if ($fav->playlist_id) { - $type = 'playlist'; - $id = $fav->playlist_id; - } - else if ($fav->track_id) { - $type = 'track'; - $id = $fav->track_id; - } - - $userResource = $this->getUserCacheItem($cacheItems, $fav->user_id, $type, $id); - $userResource['is_favourited'] = true; - $cacheItems[$fav->user_id][$type][$id] = $userResource; - - $resource = $this->getCacheItem($resources, $type, $id); - $resource['favourite_count']++; - $resources[$type][$id] = $resource; - } - - foreach (DB::table('followers')->get() as $follower) { - $userResource = $this->getUserCacheItem($cacheItems, $follower->user_id, 'artist', $follower->artist_id); - $userResource['is_followed'] = true; - $cacheItems[$follower->user_id]['artist'][$follower->artist_id] = $userResource; - } - - foreach ($resources as $name => $resourceArray) { - foreach ($resourceArray as $id => $resource) { - DB::table($name . 's')->whereId($id)->update($resource); - } - } - - DB::table('resource_users')->delete(); - foreach ($cacheItems as $cacheItem) { - foreach ($cacheItem as $resources) { - foreach ($resources as $resource) { - DB::table('resource_users')->insert($resource); - } - } - } - } - - private function getCacheItem(&$resources, $type, $id) { - if (!isset($resources[$type][$id])) { - $item = [ - 'view_count' => 0, - 'download_count' => 0, - 'favourite_count' => 0, - ]; - - if ($type == 'track') - $item['play_count'] = 0; - - $resources[$type][$id] = $item; - return $item; - } - - return $resources[$type][$id]; - } - - private function getUserCacheItem(&$items, $userId, $type, $id) { - if (!isset($items[$userId][$type][$id])) { - $item = [ - 'is_followed' => false, - 'is_favourited' => false, - 'is_pinned' => false, - 'view_count' => 0, - 'play_count' => 0, - 'download_count' => 0, - 'user_id' => $userId - ]; - - $item[$type . '_id'] = $id; - - $items[$userId][$type][$id] = $item; - return $item; - } - - return $items[$userId][$type][$id]; - } - - protected function getArguments() { - return []; - } - - protected function getOptions() { - return []; - } -} \ No newline at end of file diff --git a/app/config/auth.php b/app/config/auth.php deleted file mode 100644 index 79c15f02..00000000 --- a/app/config/auth.php +++ /dev/null @@ -1,63 +0,0 @@ - 'pfm', - - /* - |-------------------------------------------------------------------------- - | Authentication Model - |-------------------------------------------------------------------------- - | - | When using the "Eloquent" authentication driver, we need to know which - | Eloquent model should be used to retrieve your users. Of course, it - | is often just the "User" model but you may use whatever you like. - | - */ - - 'model' => 'User', - - /* - |-------------------------------------------------------------------------- - | Authentication Table - |-------------------------------------------------------------------------- - | - | When using the "Database" authentication driver, we need to know which - | table should be used to retrieve your users. We have chosen a basic - | default value but you may easily change it to any table you like. - | - */ - - 'table' => 'users', - - /* - |-------------------------------------------------------------------------- - | Password Reminder Settings - |-------------------------------------------------------------------------- - | - | Here you may set the settings for password reminders, including a view - | that should be used as your password reminder e-mail. You will also - | be able to set the name of the table that holds the reset tokens. - | - */ - - 'reminder' => array( - - 'email' => 'emails.auth.reminder', 'table' => 'password_reminders', - - ), - -); \ No newline at end of file diff --git a/app/config/cache.php b/app/config/cache.php deleted file mode 100644 index ce898423..00000000 --- a/app/config/cache.php +++ /dev/null @@ -1,89 +0,0 @@ - 'file', - - /* - |-------------------------------------------------------------------------- - | File Cache Location - |-------------------------------------------------------------------------- - | - | When using the "file" cache driver, we need a location where the cache - | files may be stored. A sensible default has been specified, but you - | are free to change it to any other place on disk that you desire. - | - */ - - 'path' => storage_path().'/cache', - - /* - |-------------------------------------------------------------------------- - | Database Cache Connection - |-------------------------------------------------------------------------- - | - | When using the "database" cache driver you may specify the connection - | that should be used to store the cached items. When this option is - | null the default database connection will be utilized for cache. - | - */ - - 'connection' => null, - - /* - |-------------------------------------------------------------------------- - | Database Cache Table - |-------------------------------------------------------------------------- - | - | When using the "database" cache driver we need to know the table that - | should be used to store the cached items. A default table name has - | been provided but you're free to change it however you deem fit. - | - */ - - 'table' => 'cache', - - /* - |-------------------------------------------------------------------------- - | Memcached Servers - |-------------------------------------------------------------------------- - | - | Now you may specify an array of your Memcached servers that should be - | used when utilizing the Memcached cache driver. All of the servers - | should contain a value for "host", "port", and "weight" options. - | - */ - - 'memcached' => array( - - array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100), - - ), - - /* - |-------------------------------------------------------------------------- - | Cache Key Prefix - |-------------------------------------------------------------------------- - | - | When utilizing a RAM based store such as APC or Memcached, there might - | be other applications utilizing the same cache. So, we'll specify a - | value to get prefixed to all our keys so we can avoid collisions. - | - */ - - 'prefix' => 'laravel', - -); diff --git a/app/config/compile.php b/app/config/compile.php deleted file mode 100644 index 54d7185b..00000000 --- a/app/config/compile.php +++ /dev/null @@ -1,18 +0,0 @@ - PDO::FETCH_CLASS, - - /* - |-------------------------------------------------------------------------- - | Default Database Connection Name - |-------------------------------------------------------------------------- - | - | Here you may specify which of the database connections below you wish - | to use as your default connection for all database work. Of course - | you may use many connections at once using the Database library. - | - */ - - 'default' => 'mysql', - - /* - |-------------------------------------------------------------------------- - | Database Connections - |-------------------------------------------------------------------------- - | - | Here are each of the database connections setup for your application. - | Of course, examples of configuring each database platform that is - | supported by Laravel is shown below to make development simple. - | - | - | All database work in Laravel is done through the PHP PDO facilities - | so make sure you have the driver for your particular database of - | choice installed on your machine before you begin development. - | - */ - - 'connections' => array( - - 'sqlite' => array( - 'driver' => 'sqlite', - 'database' => __DIR__.'/../database/production.sqlite', - 'prefix' => '', - ), - - 'mysql' => array( - 'driver' => 'mysql', - 'host' => 'localhost', - 'database' => 'database', - 'username' => 'root', - 'password' => '', - 'charset' => 'utf8', - 'collation' => 'utf8_unicode_ci', - 'prefix' => '', - ), - - 'pgsql' => array( - 'driver' => 'pgsql', - 'host' => 'localhost', - 'database' => 'database', - 'username' => 'root', - 'password' => '', - 'charset' => 'utf8', - 'prefix' => '', - 'schema' => 'public', - ), - - 'sqlsrv' => array( - 'driver' => 'sqlsrv', - 'host' => 'localhost', - 'database' => 'database', - 'username' => 'root', - 'password' => '', - 'prefix' => '', - ), - - ), - - /* - |-------------------------------------------------------------------------- - | Migration Repository Table - |-------------------------------------------------------------------------- - | - | This table keeps track of all the migrations that have already run for - | your application. Using this information, we can determine which of - | the migrations on disk have not actually be run in the databases. - | - */ - - 'migrations' => 'migrations', - - /* - |-------------------------------------------------------------------------- - | Redis Databases - |-------------------------------------------------------------------------- - | - | Redis is an open source, fast, and advanced key-value store that also - | provides a richer set of commands than a typical key-value systems - | such as APC or Memcached. Laravel makes it easy to dig right in. - | - */ - - 'redis' => array( - - 'cluster' => true, - - 'default' => array( - 'host' => '127.0.0.1', - 'port' => 6379, - 'database' => 0, - ), - - ), - -); diff --git a/app/config/mail.php b/app/config/mail.php deleted file mode 100644 index eb9e6406..00000000 --- a/app/config/mail.php +++ /dev/null @@ -1,111 +0,0 @@ - 'smtp', - - /* - |-------------------------------------------------------------------------- - | SMTP Host Address - |-------------------------------------------------------------------------- - | - | Here you may provide the host address of the SMTP server used by your - | applications. A default option is provided that is compatible with - | the Postmark mail service, which will provide reliable delivery. - | - */ - - 'host' => 'smtp.mailgun.org', - - /* - |-------------------------------------------------------------------------- - | SMTP Host Port - |-------------------------------------------------------------------------- - | - | This is the SMTP port used by your application to delivery e-mails to - | users of your application. Like the host we have set this value to - | stay compatible with the Postmark e-mail application by default. - | - */ - - 'port' => 587, - - /* - |-------------------------------------------------------------------------- - | Global "From" Address - |-------------------------------------------------------------------------- - | - | You may wish for all e-mails sent by your application to be sent from - | the same address. Here, you may specify a name and address that is - | used globally for all e-mails that are sent by your application. - | - */ - - 'from' => array('address' => null, 'name' => null), - - /* - |-------------------------------------------------------------------------- - | E-Mail Encryption Protocol - |-------------------------------------------------------------------------- - | - | Here you may specify the encryption protocol that should be used when - | the application send e-mail messages. A sensible default using the - | transport layer security protocol should provide great security. - | - */ - - 'encryption' => 'tls', - - /* - |-------------------------------------------------------------------------- - | SMTP Server Username - |-------------------------------------------------------------------------- - | - | If your SMTP server requires a username for authentication, you should - | set it here. This will get used to authenticate with your server on - | connection. You may also set the "password" value below this one. - | - */ - - 'username' => null, - - /* - |-------------------------------------------------------------------------- - | SMTP Server Password - |-------------------------------------------------------------------------- - | - | Here you may set the password required by your SMTP server to send out - | messages from your application. This will be given to the server on - | connection so that the application will be able to send messages. - | - */ - - 'password' => null, - - /* - |-------------------------------------------------------------------------- - | Sendmail System Path - |-------------------------------------------------------------------------- - | - | When using the "sendmail" driver to send e-mails, we will need to know - | the path to where Sendmail lives on this server. A default path has - | been provided here, which will work well on most of your systems. - | - */ - - 'sendmail' => '/usr/sbin/sendmail -bs', - -); diff --git a/app/config/poniverse.php b/app/config/poniverse.php deleted file mode 100644 index 09a5b33a..00000000 --- a/app/config/poniverse.php +++ /dev/null @@ -1,11 +0,0 @@ - 1, - 'urls' => [ - 'api' => '', - 'auth' => '', - 'token' => '' - ], - 'client_id' => 0, - 'secret' => '' - ]; \ No newline at end of file diff --git a/app/config/queue.php b/app/config/queue.php deleted file mode 100644 index 220998cb..00000000 --- a/app/config/queue.php +++ /dev/null @@ -1,60 +0,0 @@ - 'sync', - - /* - |-------------------------------------------------------------------------- - | Queue Connections - |-------------------------------------------------------------------------- - | - | Here you may configure the connection information for each server that - | is used by your application. A default configuration has been added - | for each back-end shipped with Laravel. You are free to add more. - | - */ - - 'connections' => array( - - 'sync' => array( - 'driver' => 'sync', - ), - - 'beanstalkd' => array( - 'driver' => 'beanstalkd', - 'host' => 'localhost', - 'queue' => 'default', - ), - - 'sqs' => array( - 'driver' => 'sqs', - 'key' => 'your-public-key', - 'secret' => 'your-secret-key', - 'queue' => 'your-queue-url', - 'region' => 'us-east-1', - ), - - 'iron' => array( - 'driver' => 'iron', - 'project' => 'your-project-id', - 'token' => 'your-token', - 'queue' => 'your-queue-name', - ), - - ), - -); diff --git a/app/config/session.php b/app/config/session.php deleted file mode 100644 index e11e98cd..00000000 --- a/app/config/session.php +++ /dev/null @@ -1,125 +0,0 @@ - 'native', - - /* - |-------------------------------------------------------------------------- - | Session Lifetime - |-------------------------------------------------------------------------- - | - | Here you may specify the number of minutes that you wish the session - | to be allowed to remain idle for it is expired. If you want them - | to immediately expire when the browser closes, set it to zero. - | - */ - - 'lifetime' => 120, - - /* - |-------------------------------------------------------------------------- - | Session File Location - |-------------------------------------------------------------------------- - | - | When using the native session driver, we need a location where session - | files may be stored. A default has been set for you but a different - | location may be specified. This is only needed for file sessions. - | - */ - - 'files' => storage_path().'/sessions', - - /* - |-------------------------------------------------------------------------- - | Session Database Connection - |-------------------------------------------------------------------------- - | - | When using the "database" session driver, you may specify the database - | connection that should be used to manage your sessions. This should - | correspond to a connection in your "database" configuration file. - | - */ - - 'connection' => null, - - /* - |-------------------------------------------------------------------------- - | Session Database Table - |-------------------------------------------------------------------------- - | - | When using the "database" session driver, you may specify the table we - | should use to manage the sessions. Of course, a sensible default is - | provided for you; however, you are free to change this as needed. - | - */ - - 'table' => 'sessions', - - /* - |-------------------------------------------------------------------------- - | Session Sweeping Lottery - |-------------------------------------------------------------------------- - | - | Some session drivers must manually sweep their storage location to get - | rid of old sessions from storage. Here are the chances that it will - | happen on a given request. By default, the odds are 2 out of 100. - | - */ - - 'lottery' => array(2, 100), - - /* - |-------------------------------------------------------------------------- - | Session Cookie Name - |-------------------------------------------------------------------------- - | - | Here you may change the name of the cookie used to identify a session - | instance by ID. The name specified here will get used every time a - | new session cookie is created by the framework for every driver. - | - */ - - 'cookie' => 'laravel_session', - - /* - |-------------------------------------------------------------------------- - | Session Cookie Path - |-------------------------------------------------------------------------- - | - | The session cookie path determines the path for which the cookie will - | be regarded as available. Typically, this will be the root path of - | your application but you are free to change this when necessary. - | - */ - - 'path' => '/', - - /* - |-------------------------------------------------------------------------- - | Session Cookie Domain - |-------------------------------------------------------------------------- - | - | Here you may change the domain of the cookie used to identify a session - | in your application. This will determine which domains the cookie is - | available to in your application. A sensible default has been set. - | - */ - - 'domain' => null, - -); diff --git a/app/config/testing/cache.php b/app/config/testing/cache.php deleted file mode 100644 index 16d3ae2f..00000000 --- a/app/config/testing/cache.php +++ /dev/null @@ -1,20 +0,0 @@ - 'array', - -); \ No newline at end of file diff --git a/app/config/testing/session.php b/app/config/testing/session.php deleted file mode 100644 index a18c1b9f..00000000 --- a/app/config/testing/session.php +++ /dev/null @@ -1,21 +0,0 @@ - 'array', - -); \ No newline at end of file diff --git a/app/config/view.php b/app/config/view.php deleted file mode 100644 index eba10a4c..00000000 --- a/app/config/view.php +++ /dev/null @@ -1,31 +0,0 @@ - array(__DIR__.'/../views'), - - /* - |-------------------------------------------------------------------------- - | Pagination View - |-------------------------------------------------------------------------- - | - | This view will be used to render the pagination link output, and can - | be easily customized here to show any view you like. A clean view - | compatible with Twitter's Bootstrap is given to you by default. - | - */ - - 'pagination' => 'pagination::slider', - -); diff --git a/app/config/workbench.php b/app/config/workbench.php deleted file mode 100644 index 56bee526..00000000 --- a/app/config/workbench.php +++ /dev/null @@ -1,31 +0,0 @@ - '', - - /* - |-------------------------------------------------------------------------- - | Workbench Author E-Mail Address - |-------------------------------------------------------------------------- - | - | Like the option above, your e-mail address is used when generating new - | workbench packages. The e-mail is placed in your composer.json file - | automatically after the package is created by the workbench tool. - | - */ - - 'email' => '', - -); \ No newline at end of file diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php deleted file mode 100644 index 5a085c0e..00000000 --- a/app/controllers/AccountController.php +++ /dev/null @@ -1,14 +0,0 @@ -slug != $slug) - return Redirect::action('AlbumsController@getAlbum', [$id, $album->slug]); - - return View::make('albums.show'); - } - - public function getShortlink($id) { - $album = Album::find($id); - if (!$album) - App::abort(404); - - return Redirect::action('AlbumsController@getTrack', [$id, $album->slug]); - } - - public function getDownload($id, $extension) { - $album = Album::with('tracks', 'user')->find($id); - if (!$album) - 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('album', $id, ResourceLogItem::DOWNLOAD, $format['index']); - $downloader = new AlbumDownloader($album, $formatName); - $downloader->download(); - } - } \ No newline at end of file diff --git a/app/controllers/Api/V1/TracksController.php b/app/controllers/Api/V1/TracksController.php deleted file mode 100644 index 5461656d..00000000 --- a/app/controllers/Api/V1/TracksController.php +++ /dev/null @@ -1,94 +0,0 @@ -published() - ->whereHash($hash)->first(); - - if (!$track) - return Response::json(['message' => 'Track not found.'], 403); - - $comments = []; - foreach ($track->comments as $comment) { - $comments[] = [ - 'id' => $comment->id, - 'created_at' => $comment->created_at, - 'content' => $comment->content, - 'user' => [ - 'name' => $comment->user->display_name, - 'id' => $comment->user->id, - 'url' => $comment->user->url, - 'avatars' => [ - 'normal' => $comment->user->getAvatarUrl(Image::NORMAL), - 'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL), - 'small' => $comment->user->getAvatarUrl(Image::SMALL), - ] - ] - ]; - } - - return Response::json([ - 'id' => $track->id, - 'title' => $track->title, - 'description' => $track->description, - 'lyrics' => $track->lyrics, - 'user' => [ - 'id' => $track->user->id, - 'name' => $track->user->display_name, - 'url' => $track->user->url, - 'avatars' => [ - 'thumbnail' => $track->user->getAvatarUrl(Image::THUMBNAIL), - 'small' => $track->user->getAvatarUrl(Image::SMALL), - 'normal' => $track->user->getAvatarUrl(Image::NORMAL) - ] - ], - 'stats' => [ - 'views' => $track->view_count, - 'plays' => $track->play_count, - 'downloads' => $track->download_count, - 'comments' => $track->comment_count, - 'favourites' => $track->favourite_count - ], - 'url' => $track->url, - 'is_vocal' => !!$track->is_vocal, - 'is_explicit' => !!$track->is_explicit, - 'is_downloadable' => !!$track->is_downloadable, - 'published_at' => $track->published_at, - 'duration' => $track->duration, - 'genre' => $track->genre != null - ? - [ - 'id' => $track->genre->id, - 'name' => $track->genre->name - ] : null, - 'type' => [ - 'id' => $track->track_type->id, - 'name' => $track->track_type->title - ], - 'covers' => [ - 'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL), - 'small' => $track->getCoverUrl(Image::SMALL), - 'normal' => $track->getCoverUrl(Image::NORMAL) - ], - 'comments' => $comments - ], 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/AccountController.php b/app/controllers/Api/Web/AccountController.php deleted file mode 100644 index a933d856..00000000 --- a/app/controllers/Api/Web/AccountController.php +++ /dev/null @@ -1,38 +0,0 @@ - $user->bio, - 'can_see_explicit_content' => $user->can_see_explicit_content == 1, - 'display_name' => $user->display_name, - 'sync_names' => $user->sync_names == 1, - 'mlpforums_name' => $user->mlpforums_name, - 'gravatar' => $user->gravatar ? $user->gravatar : $user->email, - 'avatar_url' => !$user->uses_gravatar ? $user->getAvatarUrl() : null, - 'uses_gravatar' => $user->uses_gravatar == 1 - ], 200); - } - - public function postSave() { - return $this->execute(new SaveAccountSettingsCommand(Input::all())); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/AlbumsController.php b/app/controllers/Api/Web/AlbumsController.php deleted file mode 100644 index ff8de5a2..00000000 --- a/app/controllers/Api/Web/AlbumsController.php +++ /dev/null @@ -1,131 +0,0 @@ -execute(new CreateAlbumCommand(Input::all())); - } - - public function postEdit($id) { - return $this->execute(new EditAlbumCommand($id, Input::all())); - } - - public function postDelete($id) { - return $this->execute(new DeleteAlbumCommand($id)); - } - - public function getShow($id) { - $album = Album::with([ - 'tracks' => function($query) { $query->userDetails(); }, - 'tracks.cover', - 'tracks.genre', - 'tracks.user', - 'user', - 'comments', - 'comments.user']) - ->userDetails() - ->find($id); - - if (!$album) - App::abort(404); - - if (Input::get('log')) { - ResourceLogItem::logItem('album', $id, ResourceLogItem::VIEW); - $album->view_count++; - } - - $returned_album = Album::mapPublicAlbumShow($album); - if($returned_album['is_downloadable'] == 0) { - unset($returned_album['formats']); - } - - return Response::json([ - 'album' => $returned_album - ], 200); - } - - public function getIndex() { - $page = 1; - if (Input::has('page')) - $page = Input::get('page'); - - $query = Album::summary() - ->with('user', 'user.avatar', 'cover') - ->userDetails() - ->orderBy('created_at', 'desc') - ->where('track_count', '>', 0); - - $count = $query->count(); - $perPage = 40; - - $query->skip(($page - 1) * $perPage)->take($perPage); - $albums = []; - - foreach ($query->get() as $album) { - $albums[] = Album::mapPublicAlbumSummary($album); - } - - return Response::json(["albums" => $albums, "current_page" => $page, "total_pages" => ceil($count / $perPage)], 200); - } - - public function getOwned() { - $query = Album::summary()->where('user_id', \Auth::user()->id)->orderBy('created_at', 'desc')->get(); - $albums = []; - foreach ($query as $album) { - $albums[] = [ - 'id' => $album->id, - 'title' => $album->title, - 'slug' => $album->slug, - 'created_at' => $album->created_at, - 'covers' => [ - 'small' => $album->getCoverUrl(Image::SMALL), - 'normal' => $album->getCoverUrl(Image::NORMAL) - ] - ]; - } - return Response::json($albums, 200); - } - - public function getEdit($id) { - $album = Album::with('tracks')->find($id); - if (!$album) - return $this->notFound('Album ' . $id . ' not found!'); - - if ($album->user_id != Auth::user()->id) - return $this->notAuthorized(); - - $tracks = []; - foreach ($album->tracks as $track) { - $tracks[] = [ - 'id' => $track->id, - 'title' => $track->title - ]; - } - - return Response::json([ - 'id' => $album->id, - 'title' => $album->title, - 'user_id' => $album->user_id, - 'slug' => $album->slug, - 'created_at' => $album->created_at, - 'published_at' => $album->published_at, - 'description' => $album->description, - 'cover_url' => $album->hasCover() ? $album->getCoverUrl(Image::NORMAL) : null, - 'real_cover_url' => $album->getCoverUrl(Image::NORMAL), - 'tracks' => $tracks - ], 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/ArtistsController.php b/app/controllers/Api/Web/ArtistsController.php deleted file mode 100644 index 3127fbf6..00000000 --- a/app/controllers/Api/Web/ArtistsController.php +++ /dev/null @@ -1,180 +0,0 @@ -first(); - if (!$user) - App::abort(404); - - $favs = Favourite::whereUserId($user->id)->with([ - 'track.genre', - 'track.cover', - 'track.user', - 'album.cover', - 'album.user', - 'track' => function($query) { $query->userDetails(); }, - 'album' => function($query) { $query->userDetails(); }])->get(); - - $tracks = []; - $albums = []; - - foreach ($favs as $fav) { - if ($fav->type == 'Entities\Track') { - $tracks[] = Track::mapPublicTrackSummary($fav->track); - } - else if ($fav->type == 'Entities\Album') { - $albums[] = Album::mapPublicAlbumSummary($fav->album); - } - } - - return Response::json([ - 'tracks' => $tracks, - 'albums' => $albums - ], 200); - } - - public function getContent($slug) { - $user = User::whereSlug($slug)->first(); - if (!$user) - App::abort(404); - - $query = Track::summary()->published()->listed()->explicitFilter()->with('genre', 'cover', 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at'); - $tracks = []; - $singles = []; - - foreach ($query->get() as $track) { - if ($track->album_id != null) - $tracks[] = Track::mapPublicTrackSummary($track); - else - $singles[] = Track::mapPublicTrackSummary($track); - } - - $query = Album::summary() - ->with('user') - ->orderBy('created_at', 'desc') - ->where('track_count', '>', 0) - ->whereUserId($user->id); - - $albums = []; - - foreach ($query->get() as $album) { - $albums[] = Album::mapPublicAlbumSummary($album); - } - - return Response::json(['singles' => $singles, 'albumTracks' => $tracks, 'albums' => $albums], 200); - } - - public function getShow($slug) { - $user = User::whereSlug($slug) - ->userDetails() - ->with(['comments' => function ($query) { $query->with('user'); }]) - ->first(); - if (!$user) - App::abort(404); - - $trackQuery = Track::summary() - ->published() - ->explicitFilter() - ->listed() - ->with('genre', 'cover', 'user') - ->userDetails() - ->whereUserId($user->id) - ->whereNotNull('published_at') - ->orderBy('created_at', 'desc') - ->take(20); - - $latestTracks = []; - foreach ($trackQuery->get() as $track) { - $latestTracks[] = Track::mapPublicTrackSummary($track); - } - - $comments = []; - foreach ($user->comments as $comment) { - $comments[] = Comment::mapPublic($comment); - } - - $userData = [ - 'is_following' => false - ]; - - if ($user->users->count()) { - $userRow = $user->users[0]; - $userData = [ - 'is_following' => (bool) $userRow->is_followed - ]; - } - - return Response::json([ - 'artist' => [ - 'id' => (int) $user->id, - 'name' => $user->display_name, - 'slug' => $user->slug, - 'is_archived' => (bool) $user->is_archived, - 'avatars' => [ - 'small' => $user->getAvatarUrl(Image::SMALL), - 'normal' => $user->getAvatarUrl(Image::NORMAL) - ], - 'created_at' => $user->created_at, - 'followers' => [], - 'following' => [], - 'latest_tracks' => $latestTracks, - 'comments' => $comments, - 'bio' => $user->bio, - 'mlpforums_username' => $user->mlpforums_name, - 'message_url' => $user->message_url, - 'user_data' => $userData - ] - ], 200); - } - - public function getIndex() { - $page = 1; - if (Input::has('page')) - $page = Input::get('page'); - - $query = User::orderBy('created_at', 'desc') - ->where('track_count', '>', 0); - - $count = $query->count(); - $perPage = 40; - - $query->skip(($page - 1) * $perPage)->take($perPage); - $users = []; - - foreach ($query->get() as $user) { - $users[] = [ - 'id' => $user->id, - 'name' => $user->display_name, - 'slug' => $user->slug, - 'url' => $user->url, - 'is_archived' => $user->is_archived, - 'avatars' => [ - 'small' => $user->getAvatarUrl(Image::SMALL), - 'normal' => $user->getAvatarUrl(Image::NORMAL) - ], - 'created_at' => $user->created_at - ]; - } - - return Response::json(["artists" => $users, "current_page" => $page, "total_pages" => ceil($count / $perPage)], 200); - } - } diff --git a/app/controllers/Api/Web/AuthController.php b/app/controllers/Api/Web/AuthController.php deleted file mode 100644 index 80d2de07..00000000 --- a/app/controllers/Api/Web/AuthController.php +++ /dev/null @@ -1,11 +0,0 @@ -execute(new CreateCommentCommand($type, $id, Input::all())); - } - - public function getIndex($type, $id) { - $column = ''; - - if ($type == 'track') - $column = 'track_id'; - else if ($type == 'user') - $column = 'profile_id'; - else if ($type == 'album') - $column = 'album_id'; - else if ($type == 'playlist') - $column = 'playlist_id'; - else - App::abort(500); - - $query = Comment::where($column, '=', $id)->orderBy('created_at', 'desc')->with('user'); - $comments = []; - - foreach ($query->get() as $comment) { - $comments[] = Comment::mapPublic($comment); - } - - return Response::json(['list' => $comments, 'count' => count($comments)]); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/DashboardController.php b/app/controllers/Api/Web/DashboardController.php deleted file mode 100644 index e664dccb..00000000 --- a/app/controllers/Api/Web/DashboardController.php +++ /dev/null @@ -1,45 +0,0 @@ -with(['genre', 'user', 'cover', 'user.avatar']) - ->whereIsLatest(true) - ->listed() - ->userDetails() - ->explicitFilter() - ->published() - ->orderBy('published_at', 'desc') - ->take(30); - - $recentTracks = []; - - foreach ($recentQuery->get() as $track) { - $recentTracks[] = Track::mapPublicTrackSummary($track); - } - - return Response::json([ - 'recent_tracks' => $recentTracks, - 'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content), - 'news' => News::getNews(0, 10)], 200); - } - - public function postReadNews() { - News::markPostAsRead(Input::get('url')); - return Response::json([ - ]); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/FavouritesController.php b/app/controllers/Api/Web/FavouritesController.php deleted file mode 100644 index fa435cf8..00000000 --- a/app/controllers/Api/Web/FavouritesController.php +++ /dev/null @@ -1,98 +0,0 @@ -execute(new ToggleFavouriteCommand(Input::get('type'), Input::get('id'))); - } - - public function getTracks() { - $query = Favourite - ::whereUserId(Auth::user()->id) - ->whereNotNull('track_id') - ->with([ - 'track' => function($query) { - $query - ->userDetails() - ->published(); - }, - 'track.user', - 'track.genre', - 'track.cover', - 'track.album', - 'track.album.user' - ]); - - $tracks = []; - - foreach ($query->get() as $fav) { - if ($fav->track == null) // deleted track - continue; - - $tracks[] = Track::mapPublicTrackSummary($fav->track); - } - - return Response::json(["tracks" => $tracks], 200); - } - - public function getAlbums() { - $query = Favourite - ::whereUserId(Auth::user()->id) - ->whereNotNull('album_id') - ->with([ - 'album' => function($query) { - $query->userDetails(); - }, - 'album.user', - 'album.user.avatar', - 'album.cover' - ]); - - $albums = []; - - foreach ($query->get() as $fav) { - if ($fav->album == null) // deleted album - continue; - - $albums[] = Album::mapPublicAlbumSummary($fav->album); - } - - return Response::json(["albums" => $albums], 200); - } - - public function getPlaylists() { - $query = Favourite - ::whereUserId(Auth::user()->id) - ->whereNotNull('playlist_id') - ->with([ - 'playlist' => function($query) { - $query->userDetails(); - }, - 'playlist.user', - 'playlist.user.avatar', - 'playlist.tracks', - 'playlist.tracks.cover' - ]); - - $playlists = []; - - foreach ($query->get() as $fav) { - if ($fav->playlist == null) // deleted playlist - continue; - - $playlists[] = Playlist::mapPublicPlaylistSummary($fav->playlist); - } - - return Response::json(["playlists" => $playlists], 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/FollowController.php b/app/controllers/Api/Web/FollowController.php deleted file mode 100644 index 3f859f72..00000000 --- a/app/controllers/Api/Web/FollowController.php +++ /dev/null @@ -1,13 +0,0 @@ -execute(new ToggleFollowingCommand(Input::get('type'), Input::get('id'))); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/ImagesController.php b/app/controllers/Api/Web/ImagesController.php deleted file mode 100644 index 6a0048fe..00000000 --- a/app/controllers/Api/Web/ImagesController.php +++ /dev/null @@ -1,34 +0,0 @@ -id); - $images = []; - foreach ($query->get() as $image) { - $images[] = [ - 'id' => $image->id, - 'urls' => [ - 'small' => $image->getUrl(Image::SMALL), - 'normal' => $image->getUrl(Image::NORMAL), - 'thumbnail' => $image->getUrl(Image::THUMBNAIL), - 'original' => $image->getUrl(Image::ORIGINAL) - ], - 'filename' => $image->filename - ]; - } - - return Response::json($images, 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/PlaylistsController.php b/app/controllers/Api/Web/PlaylistsController.php deleted file mode 100644 index 5134cac6..00000000 --- a/app/controllers/Api/Web/PlaylistsController.php +++ /dev/null @@ -1,118 +0,0 @@ -execute(new CreatePlaylistCommand(Input::all())); - } - - public function postEdit($id) { - return $this->execute(new EditPlaylistCommand($id, Input::all())); - } - - public function postDelete($id) { - return $this->execute(new DeletePlaylistCommand($id, Input::all())); - } - - public function postAddTrack($id) { - return $this->execute(new AddTrackToPlaylistCommand($id, Input::get('track_id'))); - } - - public function getIndex() { - $page = 1; - if (Input::has('page')) - $page = Input::get('page'); - - $query = Playlist::summary() - ->with('user', 'user.avatar', 'tracks', 'tracks.cover', 'tracks.user', 'tracks.album', 'tracks.album.user') - ->userDetails() - ->orderBy('created_at', 'desc') - ->where('track_count', '>', 0) - ->whereIsPublic(true); - - $count = $query->count(); - $perPage = 40; - - $query->skip(($page - 1) * $perPage)->take($perPage); - $playlists = []; - - foreach ($query->get() as $playlist) { - $playlists[] = Playlist::mapPublicPlaylistSummary($playlist); - } - - return Response::json(["playlists" => $playlists, "current_page" => $page, "total_pages" => ceil($count / $perPage)], 200); - } - - public function getShow($id) { - $playlist = Playlist::with(['tracks.user', 'tracks.genre', 'tracks.cover', 'tracks.album', 'tracks' => function($query) { $query->userDetails(); }, 'comments', 'comments.user'])->userDetails()->find($id); - if (!$playlist || !$playlist->canView(Auth::user())) - App::abort('404'); - - if (Input::get('log')) { - ResourceLogItem::logItem('playlist', $id, ResourceLogItem::VIEW); - $playlist->view_count++; - } - - return Response::json(Playlist::mapPublicPlaylistShow($playlist), 200); - } - - public function getPinned() { - $query = Playlist - ::userDetails() - ->with('tracks', 'tracks.cover', 'tracks.user', 'user') - ->join('pinned_playlists', function($join) { - $join->on('playlist_id', '=', 'playlists.id'); - }) - ->where('pinned_playlists.user_id', '=', Auth::user()->id) - ->orderBy('title', 'asc') - ->select('playlists.*') - ->get(); - - $playlists = []; - foreach ($query as $playlist) { - $mapped = Playlist::mapPublicPlaylistSummary($playlist); - $mapped['description'] = $playlist->description; - $mapped['is_pinned'] = true; - $playlists[] = $mapped; - } - - return Response::json($playlists, 200); - } - - public function getOwned() { - $query = Playlist::summary()->with('pins', 'tracks', 'tracks.cover')->where('user_id', \Auth::user()->id)->orderBy('title', 'asc')->get(); - $playlists = []; - foreach ($query as $playlist) { - $playlists[] = [ - 'id' => $playlist->id, - 'title' => $playlist->title, - 'slug' => $playlist->slug, - 'created_at' => $playlist->created_at, - 'description' => $playlist->description, - 'url' => $playlist->url, - 'covers' => [ - 'small' => $playlist->getCoverUrl(Image::SMALL), - 'normal' => $playlist->getCoverUrl(Image::NORMAL) - ], - 'is_pinned' => $playlist->hasPinFor(Auth::user()->id), - 'is_public' => $playlist->is_public == 1 - ]; - } - return Response::json($playlists, 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/ProfilerController.php b/app/controllers/Api/Web/ProfilerController.php deleted file mode 100644 index f1443252..00000000 --- a/app/controllers/Api/Web/ProfilerController.php +++ /dev/null @@ -1,24 +0,0 @@ - ProfileRequest::load($request)->toArray()], 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/TaxonomiesController.php b/app/controllers/Api/Web/TaxonomiesController.php deleted file mode 100644 index d8c53b16..00000000 --- a/app/controllers/Api/Web/TaxonomiesController.php +++ /dev/null @@ -1,20 +0,0 @@ - License::all()->toArray(), - 'genres' => Genre::select('genres.*', DB::raw('(SELECT COUNT(id) FROM tracks WHERE tracks.genre_id = genres.id AND tracks.published_at IS NOT NULL) AS track_count'))->orderBy('name')->get()->toArray(), - 'track_types' => TrackType::select('track_types.*', DB::raw('(SELECT COUNT(id) FROM tracks WHERE tracks.track_type_id = track_types.id AND tracks.published_at IS NOT NULL) AS track_count'))->get()->toArray(), - 'show_songs' => ShowSong::select('title', 'id', 'slug', DB::raw('(SELECT COUNT(tracks.id) FROM show_song_track INNER JOIN tracks ON tracks.id = show_song_track.track_id WHERE show_song_track.show_song_id = show_songs.id AND tracks.published_at IS NOT NULL) AS track_count'))->get()->toArray() - ], 200); - } - } \ No newline at end of file diff --git a/app/controllers/Api/Web/TracksController.php b/app/controllers/Api/Web/TracksController.php deleted file mode 100644 index cbc54ebd..00000000 --- a/app/controllers/Api/Web/TracksController.php +++ /dev/null @@ -1,139 +0,0 @@ -execute(new UploadTrackCommand()); - } - - public function postDelete($id) { - return $this->execute(new DeleteTrackCommand($id)); - } - - public function postEdit($id) { - return $this->execute(new EditTrackCommand($id, Input::all())); - } - - public function getShow($id) { - $track = Track::userDetails()->withComments()->find($id); - if (!$track || !$track->canView(Auth::user())) - return $this->notFound('Track not found!'); - - if (Input::get('log')) { - ResourceLogItem::logItem('track', $id, ResourceLogItem::VIEW); - $track->view_count++; - } - - $returned_track = Track::mapPublicTrackShow($track); - if ($returned_track['is_downloadable'] != 1) { - unset($returned_track['formats']); - } - - return Response::json(['track' => $returned_track], 200); - } - - public function getIndex() { - $page = 1; - $perPage = 45; - - if (Input::has('page')) - $page = Input::get('page'); - - $query = Track::summary() - ->userDetails() - ->listed() - ->explicitFilter() - ->published() - ->with('user', 'genre', 'cover', 'album', 'album.user'); - - $this->applyFilters($query); - - $totalCount = $query->count(); - $query->take($perPage)->skip($perPage * ($page - 1)); - - $tracks = []; - $ids = []; - - foreach ($query->get(['tracks.*']) as $track) { - $tracks[] = Track::mapPublicTrackSummary($track); - $ids[] = $track->id; - } - - return Response::json(["tracks" => $tracks, "current_page" => $page, "total_pages" => ceil($totalCount / $perPage)], 200); - } - - public function getOwned() { - $query = Track::summary()->where('user_id', \Auth::user()->id)->orderBy('created_at', 'desc'); - - $tracks = []; - foreach ($query->get() as $track) - $tracks[] = Track::mapPrivateTrackSummary($track); - - return Response::json($tracks, 200); - } - - public function getEdit($id) { - $track = Track::with('showSongs')->find($id); - if (!$track) - return $this->notFound('Track ' . $id . ' not found!'); - - if ($track->user_id != Auth::user()->id) - return $this->notAuthorized(); - - return Response::json(Track::mapPrivateTrackShow($track), 200); - } - - private function applyFilters($query) { - if (Input::has('order')) { - $order = \Input::get('order'); - $parts = explode(',', $order); - $query->orderBy($parts[0], $parts[1]); - } - - if (Input::has('is_vocal')) { - $isVocal = \Input::get('is_vocal'); - if ($isVocal == 'true') - $query->whereIsVocal(true); - else - $query->whereIsVocal(false); - } - - if (Input::has('in_album')) { - if (Input::get('in_album') == 'true') - $query->whereNotNull('album_id'); - else - $query->whereNull('album_id'); - } - - if (Input::has('genres')) - $query->whereIn('genre_id', Input::get('genres')); - - if (Input::has('types')) - $query->whereIn('track_type_id', Input::get('types')); - - if (Input::has('songs')) { - $query->join('show_song_track', function($join) { - $join->on('tracks.id', '=', 'show_song_track.track_id'); - }); - $query->whereIn('show_song_track.show_song_id', Input::get('songs')); - } - - return $query; - } - } diff --git a/app/controllers/ApiControllerBase.php b/app/controllers/ApiControllerBase.php deleted file mode 100644 index 0553f885..00000000 --- a/app/controllers/ApiControllerBase.php +++ /dev/null @@ -1,23 +0,0 @@ -authorize()) - return $this->notAuthorized(); - - $result = $command->execute(); - if ($result->didFail()) { - return Response::json(['message' => 'Validation failed', 'errors' => $result->getValidator()->messages()->getMessages()], 400); - } - - return Response::json($result->getResponse(), 200); - } - - public function notAuthorized() { - return Response::json(['message' => 'You may not do this!'], 403); - } - - public function notFound($message) { - return Response::json(['message' => $message], 403); - } - } \ No newline at end of file diff --git a/app/controllers/ArtistsController.php b/app/controllers/ArtistsController.php deleted file mode 100644 index c5e1dde8..00000000 --- a/app/controllers/ArtistsController.php +++ /dev/null @@ -1,25 +0,0 @@ -first(); - if (!$user) - App::abort('404'); - - return View::make('artists.profile'); - } - - public function getShortlink($id) { - $user = User::find($id); - if (!$user) - App::abort('404'); - - return Redirect::action('ArtistsController@getProfile', [$id]); - } - } \ No newline at end of file diff --git a/app/controllers/AuthController.php b/app/controllers/AuthController.php deleted file mode 100644 index bef05124..00000000 --- a/app/controllers/AuthController.php +++ /dev/null @@ -1,94 +0,0 @@ -poniverse = new Poniverse(Config::get('poniverse.client_id'), Config::get('poniverse.secret')); - $this->poniverse->setRedirectUri(URL::to('/auth/oauth')); - } - - public function getLogin() { - if (Auth::guest()) - return Redirect::to($this->poniverse->getAuthenticationUrl('login')); - - return Redirect::to('/'); - } - - public function postLogout() { - Auth::logout(); - return Redirect::to('/'); - } - - public function getOAuth() { - $code = $this->poniverse->getClient()->getAccessToken( - Config::get('poniverse.urls')['token'], - 'authorization_code', - [ - 'code' => Input::query('code'), - 'redirect_uri' => URL::to('/auth/oauth') - ]); - - if($code['code'] != 200) { - if($code['code'] == 400 && $code['result']['error_description'] == 'The authorization code has expired' && !isset($this->request['login_attempt'])) { - return Redirect::to($this->poniverse->getAuthenticationUrl('login_attempt')); - } - - return Redirect::to('/')->with('message', 'Unfortunately we are having problems attempting to log you in at the moment. Please try again at a later time.' ); - } - - $this->poniverse->setAccessToken($code['result']['access_token']); - $poniverseUser = $this->poniverse->getUser(); - $token = DB::table('oauth2_tokens')->where('external_user_id', '=', $poniverseUser['id'])->where('service', '=', 'poniverse')->first(); - - $setData = [ - 'access_token' => $code['result']['access_token'], - 'expires' => date( 'Y-m-d H:i:s', strtotime("+".$code['result']['expires_in']." Seconds", time())), - 'type' => $code['result']['token_type'], - ]; - - if(isset($code['result']['refresh_token']) && !empty($code['result']['refresh_token'])) { - $setData['refresh_token'] = $code['result']['refresh_token']; - } - - if($token) { - //User already exists, update access token and refresh token if provided. - DB::table('oauth2_tokens')->where('id', '=', $token->id)->update($setData); - return $this->loginRedirect(User::find($token->user_id)); - } - - //Check by email to see if they already have an account - $localMember = User::where('email', '=', $poniverseUser['email'])->first(); - - if ($localMember) { - return $this->loginRedirect($localMember); - } - - $user = new User; - - $user->mlpforums_name = $poniverseUser['username']; - $user->display_name = $poniverseUser['display_name']; - $user->email = $poniverseUser['email']; - $user->created_at = gmdate("Y-m-d H:i:s", time()); - $user->uses_gravatar = 1; - - $user->save(); - - //We need to insert a new token row :O - - $setData['user_id'] = $user->id; - $setData['external_user_id'] = $poniverseUser['id']; - $setData['service'] = 'poniverse'; - - DB::table('oauth2_tokens')->insert($setData); - - return $this->loginRedirect($user); - } - - protected function loginRedirect($user, $rememberMe = true) { - Auth::login($user, $rememberMe); - return Redirect::to('/'); - } - } \ No newline at end of file diff --git a/app/controllers/ContentController.php b/app/controllers/ContentController.php deleted file mode 100644 index 55b5fe56..00000000 --- a/app/controllers/ContentController.php +++ /dev/null @@ -1,15 +0,0 @@ -getFile($coverType['id']); - - if (!is_file($filename)) { - $redirect = URL::to('/images/icons/profile_' . Image::$ImageTypes[$coverType['id']]['name'] . '.png'); - return Redirect::to($redirect); - } - - if (Config::get('app.sendfile')) { - $response->header('X-Sendfile', $filename); - } else { - $response->header('X-Accel-Redirect', $filename); - } - - $response->header('Content-Disposition', 'filename="' . $filename . '"'); - $response->header('Content-Type', 'image/png'); - - $lastModified = filemtime($filename); - - $response->header('Last-Modified', $lastModified); - $response->header('Cache-Control', 'max-age=' . (60 * 60 * 24 * 7)); - - return $response; - } - } \ No newline at end of file diff --git a/app/controllers/PlaylistsController.php b/app/controllers/PlaylistsController.php deleted file mode 100644 index acfea0ab..00000000 --- a/app/controllers/PlaylistsController.php +++ /dev/null @@ -1,55 +0,0 @@ -canView(Auth::user())) - App::abort(404); - - if ($playlist->slug != $slug) - return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->slug]); - - return View::make('playlists.show'); - } - - public function getShortlink($id) { - $playlist = Playlist::find($id); - if (!$playlist || !$playlist->canView(Auth::user())) - App::abort(404); - - return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->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/controllers/TracksController.php b/app/controllers/TracksController.php deleted file mode 100644 index a9ccd910..00000000 --- a/app/controllers/TracksController.php +++ /dev/null @@ -1,131 +0,0 @@ -published() - ->userDetails() - ->with( - 'user', - 'user.avatar', - 'genre' - )->first(); - - if (!$track || !$track->canView(Auth::user())) - App::abort(404); - - $userData = [ - 'stats' => [ - 'views' => 0, - 'plays' => 0, - 'downloads' => 0 - ], - 'is_favourited' => false - ]; - - if ($track->users->count()) { - $userRow = $track->users[0]; - $userData = [ - 'stats' => [ - 'views' => $userRow->view_count, - 'plays' => $userRow->play_count, - 'downloads' => $userRow->download_count, - ], - 'is_favourited' => $userRow->is_favourited - ]; - } - - return View::make('tracks.embed', ['track' => $track, 'user' => $userData]); - } - - public function getTrack($id, $slug) { - $track = Track::find($id); - if (!$track || !$track->canView(Auth::user())) - App::abort(404); - - if ($track->slug != $slug) - return Redirect::action('TracksController@getTrack', [$id, $track->slug]); - - return View::make('tracks.show'); - } - - public function getShortlink($id) { - $track = Track::find($id); - if (!$track || !$track->canView(Auth::user())) - App::abort(404); - - return Redirect::action('TracksController@getTrack', [$id, $track->slug]); - } - - public function getStream($id, $extension) { - $track = Track::find($id); - if (!$track || !$track->canView(Auth::user())) - App::abort(404); - - $trackFile = TrackFile::findOrFailByExtension($track->id, $extension); - ResourceLogItem::logItem('track', $id, ResourceLogItem::PLAY, $trackFile->getFormat()['index']); - - $response = Response::make('', 200); - $filename = $trackFile->getFile(); - - if (Config::get('app.sendfile')) { - $response->header('X-Sendfile', $filename); - } else { - $response->header('X-Accel-Redirect', $filename); - } - - $time = gmdate(filemtime($filename)); - - if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $time == $_SERVER['HTTP_IF_MODIFIED_SINCE']) { - header('HTTP/1.0 304 Not Modified'); - exit(); - } - - $response->header('Last-Modified', $time); - $response->header('Content-Type', $trackFile->getFormat()['mime_type']); - - return $response; - } - - public function getDownload($id, $extension) { - $track = Track::find($id); - if (!$track || !$track->canView(Auth::user())) - App::abort(404); - - $trackFile = TrackFile::findOrFailByExtension($track->id, $extension); - ResourceLogItem::logItem('track', $id, ResourceLogItem::DOWNLOAD, $trackFile->getFormat()['index']); - - $response = Response::make('', 200); - $filename = $trackFile->getFile(); - - if (Config::get('app.sendfile')) { - $response->header('X-Sendfile', $filename); - $response->header('Content-Disposition', 'attachment; filename="' . $trackFile->getDownloadFilename() . '"'); - } else { - $response->header('X-Accel-Redirect', $filename); - $response->header('Content-Disposition', 'attachment; filename="' . $trackFile->getDownloadFilename() . '"'); - } - - $time = gmdate(filemtime($filename)); - - if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $time == $_SERVER['HTTP_IF_MODIFIED_SINCE']) { - header('HTTP/1.0 304 Not Modified'); - exit(); - } - - $response->header('Last-Modified', $time); - $response->header('Content-Type', $trackFile->getFormat()['mime_type']); - - return $response; - } - } \ No newline at end of file diff --git a/app/controllers/UploaderController.php b/app/controllers/UploaderController.php deleted file mode 100644 index c748fb3a..00000000 --- a/app/controllers/UploaderController.php +++ /dev/null @@ -1,7 +0,0 @@ -getAvatarFile($coverType['id']), 'image/png', 'cover.png'); - } - } \ No newline at end of file diff --git a/app/database/migrations/2013_06_07_003952_create_users_table.php b/app/database/migrations/2013_06_07_003952_create_users_table.php deleted file mode 100644 index b0dd0bae..00000000 --- a/app/database/migrations/2013_06_07_003952_create_users_table.php +++ /dev/null @@ -1,57 +0,0 @@ -increments('id'); - $table->string('display_name', 255); - $table->string('mlpforums_name')->nullable(); - $table->boolean('sync_names')->default(true); - $table->string('email', 150)->indexed(); - $table->string('gravatar')->nullable(); - $table->string('slug'); - $table->boolean('uses_gravatar')->default(true); - $table->boolean('can_see_explicit_content'); - $table->text('bio'); - $table->integer('track_count')->unsigned(); - $table->integer('comment_count')->unsigned(); - $table->timestamps(); - }); - - Schema::create('roles', function($table){ - $table->increments('id'); - $table->string('name'); - }); - - Schema::create('role_user', function($table){ - $table->increments('id'); - $table->integer('user_id')->unsigned()->index(); - $table->integer('role_id')->unsigned()->index(); - $table->timestamps(); - - $table->foreign('user_id')->references('id')->on('users'); - $table->foreign('role_id')->references('id')->on('roles'); - }); - - Schema::create('cache', function($table){ - $table->string('key')->index(); - $table->text('value'); - $table->integer('expiration')->unsigned()->index(); - }); - - DB::table('roles')->insert(['name' => 'super_admin']); - DB::table('roles')->insert(['name' => 'admin']); - DB::table('roles')->insert(['name' => 'moderator']); - DB::table('roles')->insert(['name' => 'user']); - } - - public function down() { - Schema::drop('cache'); - Schema::drop('role_user'); - Schema::drop('roles'); - Schema::drop('users'); - } -} diff --git a/app/database/migrations/2013_06_27_015259_create_tracks_table.php b/app/database/migrations/2013_06_27_015259_create_tracks_table.php deleted file mode 100644 index ad97ac73..00000000 --- a/app/database/migrations/2013_06_27_015259_create_tracks_table.php +++ /dev/null @@ -1,128 +0,0 @@ -increments('id'); - $table->string('title', 100); - $table->text('description'); - $table->boolean('affiliate_distribution'); - $table->boolean('open_distribution'); - $table->boolean('remix'); - }); - - Schema::create('genres', function($table){ - $table->increments('id'); - $table->string('name')->unique(); - $table->string('slug', 200)->index(); - }); - - Schema::create('track_types', function($table){ - $table->increments('id'); - $table->string('title'); - $table->string('editor_title'); - }); - - Schema::create('tracks', function($table){ - $table->increments('id'); - - $table->integer('user_id')->unsigned(); - $table->integer('license_id')->unsigned()->nullable()->default(NULL); - $table->integer('genre_id')->unsigned()->nullable()->index()->default(NULL); - $table->integer('track_type_id')->unsigned()->nullable()->default(NULL); - - $table->string('title', 100)->index(); - $table->string('slug', 200)->index(); - $table->text('description')->nullable(); - $table->text('lyrics')->nullable(); - $table->boolean('is_vocal'); - $table->boolean('is_explicit'); - $table->integer('cover_id')->unsigned()->nullable(); - $table->boolean('is_downloadable'); - $table->float('duration')->unsigned(); - - $table->integer('play_count')->unsigned(); - $table->integer('view_count')->unsigned(); - $table->integer('download_count')->unsigned(); - $table->integer('favourite_count')->unsigned(); - $table->integer('comment_count')->unsigned(); - - $table->timestamps(); - $table->timestamp('deleted_at')->nullable()->index(); - $table->timestamp('published_at')->nullable()->index(); - $table->timestamp('released_at')->nullable(); - - $table->foreign('user_id')->references('id')->on('users'); - $table->foreign('license_id')->references('id')->on('licenses'); - $table->foreign('genre_id')->references('id')->on('genres')->on_update('cascade'); - $table->foreign('track_type_id')->references('id')->on('track_types')->on_update('cascade'); - }); - - - DB::table('licenses')->insert([ - 'title' => 'Personal', - 'description' => 'Only you and Pony.fm are allowed to distribute and broadcast the track.', - 'affiliate_distribution' => 0, - 'open_distribution' => 0, - 'remix' => 0 - ]); - - DB::table('licenses')->insert([ - 'title' => 'Broadcast', - 'description' => 'You, Pony.fm, and its affiliates may distribute and broadcast the track.', - 'affiliate_distribution' => 1, - 'open_distribution' => 0, - 'remix' => 0 - ]); - - DB::table('licenses')->insert([ - 'title' => 'Open', - 'description' => 'Anyone is permitted to broadcast and distribute the song in its original form, with attribution to you.', - 'affiliate_distribution' => 1, - 'open_distribution' => 1, - 'remix' => 0 - ]); - - DB::table('licenses')->insert([ - 'title' => 'Remix', - 'description' => 'Anyone is permitted to broadcast and distribute the song in any form, or create derivative works based on it for any purpose, with attribution to you.', - 'affiliate_distribution' => 1, - 'open_distribution' => 1, - 'remix' => 1 - ]); - - DB::table('track_types')->insert([ - 'title' => 'Original Song', - 'editor_title' => 'an original song' - ]); - - DB::table('track_types')->insert([ - 'title' => 'Official Song Remix', - 'editor_title' => 'a remix of an official song' - ]); - - DB::table('track_types')->insert([ - 'title' => 'Fan Song Remix', - 'editor_title' => 'a remix of a fan song' - ]); - - DB::table('track_types')->insert([ - 'title' => 'Ponified Song', - 'editor_title' => 'a non-pony song, turned pony' - ]); - - DB::table('track_types')->insert([ - 'title' => 'Official Show Audio Remix', - 'editor_title' => 'a remix of official show audio' - ]); - } - - public function down() { - Schema::drop('tracks'); - Schema::drop('licenses'); - Schema::drop('track_types'); - Schema::drop('genres'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_07_26_230827_create_images_table.php b/app/database/migrations/2013_07_26_230827_create_images_table.php deleted file mode 100644 index bf1f9e0b..00000000 --- a/app/database/migrations/2013_07_26_230827_create_images_table.php +++ /dev/null @@ -1,44 +0,0 @@ -increments('id'); - $table->string('filename', 256); - $table->string('mime', 100); - $table->string('extension', 32); - $table->integer('size'); - $table->string('hash', 32); - $table->integer('uploaded_by')->unsigned(); - $table->timestamps(); - - $table->foreign('uploaded_by')->references('id')->on('users'); - }); - - Schema::table('users', function($table) { - $table->integer('avatar_id')->unsigned()->nullable(); - $table->foreign('avatar_id')->references('id')->on('images'); - }); - - DB::table('tracks')->update(['cover_id' => null]); - - Schema::table('tracks', function($table) { - $table->foreign('cover_id')->references('id')->on('images'); - }); - } - - public function down() { - Schema::table('tracks', function($table) { - $table->dropForeign('tracks_cover_id_foreign'); - }); - - Schema::table('users', function($table) { - $table->dropForeign('users_avatar_id_foreign'); - $table->dropColumn('avatar_id'); - }); - - Schema::drop('images'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_07_28_060804_create_albums.php b/app/database/migrations/2013_07_28_060804_create_albums.php deleted file mode 100644 index d2aa6456..00000000 --- a/app/database/migrations/2013_07_28_060804_create_albums.php +++ /dev/null @@ -1,45 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned(); - $table->string('title')->index(); - $table->string('slug')->index(); - $table->text('description'); - $table->integer('cover_id')->unsigned()->nullable(); - - $table->integer('track_count')->unsigned(); - $table->integer('view_count')->unsigned(); - $table->integer('download_count')->unsigned(); - $table->integer('favourite_count')->unsigned(); - $table->integer('comment_count')->unsigned(); - - $table->timestamps(); - $table->timestamp('deleted_at')->nullable()->index(); - - $table->foreign('cover_id')->references('id')->on('images'); - $table->foreign('user_id')->references('id')->on('users'); - }); - - Schema::table('tracks', function($table) { - $table->integer('album_id')->unsigned()->nullable(); - $table->integer('track_number')->unsigned()->nullable(); - - $table->foreign('album_id')->references('id')->on('albums'); - }); - } - - public function down() { - Schema::table('tracks', function($table) { - $table->dropForeign('tracks_album_id_foreign'); - $table->dropColumn('album_id'); - $table->dropColumn('track_number'); - }); - - Schema::drop('albums'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_07_28_135136_create_playlists.php b/app/database/migrations/2013_07_28_135136_create_playlists.php deleted file mode 100644 index 9c61a5a5..00000000 --- a/app/database/migrations/2013_07_28_135136_create_playlists.php +++ /dev/null @@ -1,67 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned()->index(); - $table->string('title'); - $table->string('slug'); - $table->text('description'); - $table->boolean('is_public'); - - $table->integer('track_count')->unsigned(); - $table->integer('view_count')->unsigned(); - $table->integer('download_count')->unsigned(); - $table->integer('favourite_count')->unsigned(); - $table->integer('follow_count')->unsigned(); - $table->integer('comment_count')->unsigned(); - - $table->timestamps(); - $table->date('deleted_at')->nullable()->index(); - - $table->foreign('user_id')->references('id')->on('users')->on_update('cascade'); - }); - - Schema::create('playlist_track', function($table){ - $table->increments('id'); - $table->timestamps(); - $table->integer('playlist_id')->unsigned()->index(); - $table->integer('track_id')->unsigned()->index(); - $table->integer('position')->unsigned(); - - $table->foreign('playlist_id')->references('id')->on('playlists')->on_update('cascade')->on_delete('cascade'); - $table->foreign('track_id')->references('id')->on('tracks')->on_update('cascade'); - }); - - Schema::create('pinned_playlists', function($table) { - $table->increments('id'); - $table->integer('user_id')->unsigned()->index(); - $table->integer('playlist_id')->unsigned()->index(); - $table->timestamps(); - - $table->foreign('user_id')->references('id')->on('users')->on_update('cascade'); - $table->foreign('playlist_id')->references('id')->on('playlists')->on_update('cascade'); - }); - } - - public function down() { - Schema::table('playlist_track', function($table){ - $table->dropForeign('playlist_track_playlist_id_foreign'); - $table->dropForeign('playlist_track_track_id_foreign'); - }); - - Schema::drop('playlist_track'); - - Schema::drop('pinned_playlists'); - - Schema::table('playlists', function($table){ - $table->dropForeign('playlists_user_id_foreign'); - }); - - Schema::drop('playlists'); - } - -} \ No newline at end of file diff --git a/app/database/migrations/2013_08_01_051337_create_comments.php b/app/database/migrations/2013_08_01_051337_create_comments.php deleted file mode 100644 index d70491cb..00000000 --- a/app/database/migrations/2013_08_01_051337_create_comments.php +++ /dev/null @@ -1,38 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned(); - $table->string('ip_address', 46); - $table->text('content'); - - $table->timestamps(); - $table->timestamp('deleted_at')->nullable()->index(); - - $table->integer('profile_id')->unsigned()->nullable()->index(); - $table->integer('track_id')->unsigned()->nullable()->index(); - $table->integer('album_id')->unsigned()->nullable()->index(); - $table->integer('playlist_id')->unsigned()->nullable()->index(); - - $table->foreign('profile_id')->references('id')->on('users'); - $table->foreign('user_id')->references('id')->on('users'); - $table->foreign('track_id')->references('id')->on('tracks'); - $table->foreign('album_id')->references('id')->on('albums'); - $table->foreign('playlist_id')->references('id')->on('playlists'); - }); - } - - public function down() { - Schema::table('comments', function($table){ - $table->dropForeign('comments_user_id_foreign'); - $table->dropForeign('comments_track_id_foreign'); - $table->dropForeign('comments_album_id_foreign'); - $table->dropForeign('comments_playlist_id_foreign'); - }); - Schema::drop('comments'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_08_18_041928_create_user_tables.php b/app/database/migrations/2013_08_18_041928_create_user_tables.php deleted file mode 100644 index ac526370..00000000 --- a/app/database/migrations/2013_08_18_041928_create_user_tables.php +++ /dev/null @@ -1,57 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned()->index(); - - $table->integer('track_id')->unsigned()->nullable()->index(); - $table->integer('album_id')->unsigned()->nullable()->index(); - $table->integer('playlist_id')->unsigned()->nullable()->index(); - $table->integer('artist_id')->unsigned()->nullable()->index(); - - $table->boolean('is_followed'); - $table->boolean('is_favourited'); - $table->boolean('is_pinned'); - - $table->integer('view_count'); - $table->integer('play_count'); - $table->integer('download_count'); - - $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('track_id')->references('id')->on('tracks')->on_delete('cascade');; - $table->foreign('album_id')->references('id')->on('albums')->on_delete('cascade');; - $table->foreign('playlist_id')->references('id')->on('playlists')->on_delete('cascade');; - - $table->unique(['user_id', 'track_id', 'album_id', 'playlist_id', 'artist_id'], 'resource_unique'); - }); - - Schema::create('resource_log_items', function($table){ - $table->increments('id'); - $table->integer('user_id')->unsigned()->nullable()->index(); - $table->integer('log_type')->unsigned(); - $table->string('ip_address', 46)->index(); - $table->integer('track_format_id')->unsigned()->nullable(); - - $table->integer('track_id')->unsigned()->nullable()->index(); - $table->integer('album_id')->unsigned()->nullable()->index(); - $table->integer('playlist_id')->unsigned()->nullable()->index(); - - $table->timestamp('created_at'); - - $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('track_id')->references('id')->on('tracks'); - $table->foreign('album_id')->references('id')->on('albums'); - $table->foreign('playlist_id')->references('id')->on('playlists'); - }); - } - - public function down() { - Schema::drop('resource_users'); - Schema::drop('resource_log_items'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_08_18_045248_create_favourites.php b/app/database/migrations/2013_08_18_045248_create_favourites.php deleted file mode 100644 index 8901d451..00000000 --- a/app/database/migrations/2013_08_18_045248_create_favourites.php +++ /dev/null @@ -1,34 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned()->index(); - - $table->integer('track_id')->unsigned()->nullable()->index(); - $table->integer('album_id')->unsigned()->nullable()->index(); - $table->integer('playlist_id')->unsigned()->nullable()->index(); - - $table->timestamp('created_at'); - - $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('track_id')->references('id')->on('tracks'); - $table->foreign('album_id')->references('id')->on('albums'); - $table->foreign('playlist_id')->references('id')->on('playlists'); - }); - } - - public function down() { - Schema::table('favourites', function($table){ - $table->dropForeign('favourites_user_id_foreign'); - $table->dropForeign('favourites_track_id_foreign'); - $table->dropForeign('favourites_album_id_foreign'); - $table->dropForeign('favourites_playlist_id_foreign'); - }); - - Schema::drop('favourites'); - } - } \ No newline at end of file diff --git a/app/database/migrations/2013_08_29_025516_create_followers.php b/app/database/migrations/2013_08_29_025516_create_followers.php deleted file mode 100644 index d9604534..00000000 --- a/app/database/migrations/2013_08_29_025516_create_followers.php +++ /dev/null @@ -1,25 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned()->index(); - - $table->integer('artist_id')->unsigned()->nullable()->index(); - $table->integer('playlist_id')->unsigned()->nullable()->index(); - - $table->timestamp('created_at'); - - $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('playlist_id')->references('id')->on('playlists'); - }); - } - - public function down() { - Schema::drop('followers'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_09_01_025031_oauth.php b/app/database/migrations/2013_09_01_025031_oauth.php deleted file mode 100644 index 0606d77c..00000000 --- a/app/database/migrations/2013_09_01_025031_oauth.php +++ /dev/null @@ -1,22 +0,0 @@ -increments('id'); - $table->integer('user_id'); - $table->integer('external_user_id'); - $table->text('access_token'); - $table->timestamp('expires'); - $table->text('refresh_token'); - $table->string('type'); - $table->string('service'); - }); - } - - public function down() { - Schema::drop('oauth2_tokens'); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_09_01_232520_create_news_table.php b/app/database/migrations/2013_09_01_232520_create_news_table.php deleted file mode 100644 index d6e9aa73..00000000 --- a/app/database/migrations/2013_09_01_232520_create_news_table.php +++ /dev/null @@ -1,21 +0,0 @@ -increments('id'); - $table->integer('user_id')->unsigned()->index(); - $table->string('post_hash', 32)->index(); - $table->timestamps(); - - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - }); - } - - public function down() { - Schema::drop('news'); - } - -} \ No newline at end of file diff --git a/app/database/migrations/2013_09_23_031316_create_track_hashes.php b/app/database/migrations/2013_09_23_031316_create_track_hashes.php deleted file mode 100644 index 88da6afa..00000000 --- a/app/database/migrations/2013_09_23_031316_create_track_hashes.php +++ /dev/null @@ -1,23 +0,0 @@ -string('hash', 32)->notNullable()->indexed(); - }); - - foreach (Track::with('user')->get() as $track) { - $track->updateHash(); - $track->save(); - } - } - - public function down() { - Schema::table('tracks', function($table) { - $table->dropColumn('hash'); - }); - } -} \ No newline at end of file diff --git a/app/database/migrations/2013_09_24_055911_track_is_listed.php b/app/database/migrations/2013_09_24_055911_track_is_listed.php deleted file mode 100644 index 184e8b8d..00000000 --- a/app/database/migrations/2013_09_24_055911_track_is_listed.php +++ /dev/null @@ -1,23 +0,0 @@ -boolean('is_listed')->notNullable()->indexed(); - }); - - DB::update(' - UPDATE - tracks - SET - is_listed = true'); - } - - public function down() { - Schema::table('tracks', function($table) { - $table->dropColumn('is_listed'); - }); - } -} \ No newline at end of file diff --git a/app/database/migrations/2014_05_28_071738_update_track_hash.php b/app/database/migrations/2014_05_28_071738_update_track_hash.php deleted file mode 100644 index cbb72f79..00000000 --- a/app/database/migrations/2014_05_28_071738_update_track_hash.php +++ /dev/null @@ -1,16 +0,0 @@ -get() as $track) { - $track->updateHash(); - $track->save(); - } - } - - public function down() { - } -} \ No newline at end of file diff --git a/app/database/migrations/2015_04_30_064436_add_remember_me_field.php b/app/database/migrations/2015_04_30_064436_add_remember_me_field.php deleted file mode 100644 index 1e400d3b..00000000 --- a/app/database/migrations/2015_04_30_064436_add_remember_me_field.php +++ /dev/null @@ -1,17 +0,0 @@ -string('remember_token', 100)->nullable()->indexed(); - }); - } - - public function down() { - Schema::table('users', function($table) { - $table->dropColumn('remember_token'); - }); - } -} \ No newline at end of file diff --git a/app/database/migrations/2015_05_20_155236_add_archived_profile_field.php b/app/database/migrations/2015_05_20_155236_add_archived_profile_field.php deleted file mode 100644 index 6dfa4b13..00000000 --- a/app/database/migrations/2015_05_20_155236_add_archived_profile_field.php +++ /dev/null @@ -1,31 +0,0 @@ -boolean( 'is_archived' )->default(false); - } ); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table( 'users', function ( $table ) { - $table->dropColumn( 'is_archived' ); - } ); - } - -} \ No newline at end of file diff --git a/app/database/migrations/2015_05_25_011121_create_track_files_table.php b/app/database/migrations/2015_05_25_011121_create_track_files_table.php deleted file mode 100644 index 0984c119..00000000 --- a/app/database/migrations/2015_05_25_011121_create_track_files_table.php +++ /dev/null @@ -1,54 +0,0 @@ -increments('id'); - $table->integer('track_id')->unsigned()->indexed(); - $table->boolean('is_master')->default(false)->indexed(); - $table->string('format')->indexed(); - - $table->foreign('track_id')->references('id')->on('tracks'); - $table->timestamps(); - }); - - foreach (Track::all() as $track){ - foreach (Track::$Formats as $name => $item) { - DB::table('track_files')->insert( - [ - 'track_id' => $track->id, - 'is_master' => $name === 'FLAC' ? true : false, - 'format' => $name, - 'created_at'=> $track->created_at, - 'updated_at'=> Carbon\Carbon::now() - ] - ); - } - } - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::drop('track_files'); - } - -} \ No newline at end of file diff --git a/app/database/production.sqlite b/app/database/production.sqlite deleted file mode 100644 index e69de29b..00000000 diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php deleted file mode 100644 index 6a8c204c..00000000 --- a/app/database/seeds/DatabaseSeeder.php +++ /dev/null @@ -1,17 +0,0 @@ -call('UserTableSeeder'); - } - -} \ No newline at end of file diff --git a/app/filters.php b/app/filters.php deleted file mode 100644 index 9c739444..00000000 --- a/app/filters.php +++ /dev/null @@ -1,106 +0,0 @@ -after($request, $response); - - Cache::put('profiler-request-' . $profiler->getId(), $profiler->toString(), 2); - header('X-Request-Id: ' . $profiler->getId()); - } - - App::error(function($exception) use ($profiler) { - $profiler->log('error', $exception->__toString(), []); - processResponse($profiler, null, null); - }); - - App::after(function($request, $response) use ($profiler) { - if ($response->headers->get('content-type') != 'application/json') - return; - - processResponse($profiler, $request, $response); - }); - - Log::listen(function($level, $message, $context) use ($profiler) { - $profiler->log($level, $message, $context); - }); - - App::error(function($exception) { - // return Response::view('errors.500', array(), 404); - }); - } - - App::missing(function($exception) { - return Response::view('errors.404', array(), 404); - }); - - - /* - |-------------------------------------------------------------------------- - | Authentication Filters - |-------------------------------------------------------------------------- - | - | The following filters are used to verify that the user of the current - | session is logged into this application. The "basic" filter easily - | integrates HTTP Basic authentication for quick, simple checking. - | - */ - - Route::filter('auth', function() - { - if (Auth::guest()) return Redirect::guest('login'); - }); - - - Route::filter('auth.basic', function() - { - return Auth::basic(); - }); - - /* - |-------------------------------------------------------------------------- - | Guest Filter - |-------------------------------------------------------------------------- - | - | The "guest" filter is the counterpart of the authentication filters as - | it simply checks that the current user is not logged in. A redirect - | response will be issued if they are, which you may freely change. - | - */ - - Route::filter('guest', function() - { - if (Auth::check()) return Redirect::to('/'); - }); - - /* - |-------------------------------------------------------------------------- - | CSRF Protection Filter - |-------------------------------------------------------------------------- - | - | The CSRF filter is responsible for protecting your application against - | cross-site request forgery attacks. If this special token in a user - | session does not match the one given in this request, we'll bail. - | - */ - - Route::filter('csrf', function() - { - if (Session::token() != Input::get('_token') && Session::token() != Request::header('X-Token')) { - throw new Illuminate\Session\TokenMismatchException; - } - }); \ No newline at end of file diff --git a/app/lang/en/pagination.php b/app/lang/en/pagination.php deleted file mode 100644 index eb9be3ba..00000000 --- a/app/lang/en/pagination.php +++ /dev/null @@ -1,20 +0,0 @@ - '« Previous', - - 'next' => 'Next »', - -); \ No newline at end of file diff --git a/app/lang/en/reminders.php b/app/lang/en/reminders.php deleted file mode 100644 index 4a9f1766..00000000 --- a/app/lang/en/reminders.php +++ /dev/null @@ -1,22 +0,0 @@ - "Passwords must be six characters and match the confirmation.", - - "user" => "We can't find a user with that e-mail address.", - - "token" => "This password reset token is invalid.", - -); \ No newline at end of file diff --git a/app/lang/en/validation.php b/app/lang/en/validation.php deleted file mode 100644 index 40d4d727..00000000 --- a/app/lang/en/validation.php +++ /dev/null @@ -1,104 +0,0 @@ - "The :attribute must be accepted.", - "active_url" => "The :attribute is not a valid URL.", - "after" => "The :attribute must be a date after :date.", - "alpha" => "The :attribute may only contain letters.", - "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", - "alpha_num" => "The :attribute may only contain letters and numbers.", - "before" => "The :attribute must be a date before :date.", - "between" => array( - "numeric" => "The :attribute must be between :min - :max.", - "file" => "The :attribute must be between :min - :max kilobytes.", - "string" => "The :attribute must be between :min - :max characters.", - ), - "confirmed" => "The :attribute confirmation does not match.", - "date" => "The :attribute is not a valid date.", - "date_format" => "The :attribute does not match the format :format.", - "different" => "The :attribute and :other must be different.", - "digits" => "The :attribute must be :digits digits.", - "digits_between" => "The :attribute must be between :min and :max digits.", - "email" => "The :attribute format is invalid.", - "exists" => "The selected :attribute is invalid.", - "image" => "The :attribute must be an image.", - "in" => "The selected :attribute is invalid.", - "integer" => "The :attribute must be an integer.", - "ip" => "The :attribute must be a valid IP address.", - "max" => array( - "numeric" => "The :attribute may not be greater than :max.", - "file" => "The :attribute may not be greater than :max kilobytes.", - "string" => "The :attribute may not be greater than :max characters.", - ), - "mimes" => "The :attribute must be a file of type: :values.", - "min" => array( - "numeric" => "The :attribute must be at least :min.", - "file" => "The :attribute must be at least :min kilobytes.", - "string" => "The :attribute must be at least :min characters.", - ), - "not_in" => "The selected :attribute is invalid.", - "numeric" => "The :attribute must be a number.", - "regex" => "The :attribute format is invalid.", - "required" => "The :attribute field is required.", - "required_if" => "The :attribute field is required when :other is :value.", - "required_with" => "The :attribute field is required when :values is present.", - "required_without" => "The :attribute field is required when :values is not present.", - "same" => "The :attribute and :other must match.", - "size" => array( - "numeric" => "The :attribute must be :size.", - "file" => "The :attribute must be :size kilobytes.", - "string" => "The :attribute must be :size characters.", - ), - "unique" => "The :attribute has already been taken.", - "url" => "The :attribute format is invalid.", - - /* - |-------------------------------------------------------------------------- - | Custom Validation Language Lines - |-------------------------------------------------------------------------- - | - | Here you may specify custom validation messages for attributes using the - | convention "attribute.rule" to name the lines. This makes it quick to - | specify a specific custom language line for a given attribute rule. - | - */ - - 'custom' => array(), - - //=== CUSTOM VALIDATION MESSAGES ===// - - "audio" => "The :attribute must be an audio file.", - "audio_channels" => "The :attribute contains an invalid number of channels.", - "audio_format" => "The :attribute does not contain audio in a valid format.", - "required_when" => "The :attribute field cannot be left blank.", - "sample_rate" => "The :attribute has an invalid sample rate.", - "min_width" => "The :attribute is not wide enough.", - "min_height" => "The :attribute is not tall enough.", - "textarea_length" => "The :attribute must be less than 250 characters long.", // @TODO: Figure out how to retrieve the parameter from the validation rule - - /* - |-------------------------------------------------------------------------- - | Custom Validation Attributes - |-------------------------------------------------------------------------- - | - | The following language lines are used to swap attribute place-holders - | with something more reader friendly such as E-Mail Address instead - | of "email". This simply helps us make messages a little cleaner. - | - */ - - 'attributes' => array(), - -); diff --git a/app/library/Assets.php b/app/library/Assets.php deleted file mode 100644 index be3c779b..00000000 --- a/app/library/Assets.php +++ /dev/null @@ -1,107 +0,0 @@ -'; - - $scripts = self::mergeGlobs(self::getScriptsForArea($area)); - $retVal = ""; - - foreach ($scripts as $script) { - $filename = self::replaceExtensionWith($script, ".coffee", ".js"); - $retVal .= ""; - } - - return $retVal; - } - - public static function styleIncludes($area = 'app') { - if (!Config::get("app.debug")) - return ''; - - $styles = self::mergeGlobs(self::getStylesForArea($area)); - $retVal = ""; - - foreach ($styles as $style) { - $filename = self::replaceExtensionWith($style, ".less", ".css"); - $retVal .= ""; - } - - return $retVal; - } - - private static function replaceExtensionWith($filename, $fromExtension, $toExtension) { - $fromLength = strlen($fromExtension); - return substr($filename, -$fromLength) == $fromExtension - ? substr($filename, 0, strlen($filename) - $fromLength) . $toExtension - : $filename; - } - - /** Merges an array of paths that are passed into "glob" into a list of unique filenames. - * Note that this method assumes the globs should be relative to the "app" folder of this project */ - private static function mergeGlobs($globs) { - $files = []; - $filesFound = []; - foreach ($globs as $glob) { - foreach (glob("../app/" . $glob, GLOB_BRACE) as $file) { - if (isset($filesFound[$file])) - continue; - - $filesFound[$file] = true; - $files[] = substr($file, 7); // chop off ../app/ - } - } - - return $files; - } - - private static function getScriptsForArea($area) { - if ($area == 'app') { - return [ - "scripts/base/jquery-2.0.2.js", - "scripts/base/angular.js", - "scripts/base/*.{coffee,js}", - "scripts/shared/*.{coffee,js}", - "scripts/app/*.{coffee,js}", - "scripts/app/services/*.{coffee,js}", - "scripts/app/filters/*.{coffee,js}", - "scripts/app/directives/*.{coffee,js}", - "scripts/app/controllers/*.{coffee,js}", - "scripts/**/*.{coffee,js}" - ]; - } else if ($area == 'embed') { - return [ - "scripts/base/jquery-2.0.2.js", - "scripts/base/jquery.viewport.js", - "scripts/base/underscore.js", - "scripts/base/moment.js", - "scripts/base/jquery.timeago.js", - "scripts/base/soundmanager2-nodebug.js", - "scripts/embed/*.coffee"]; - } - - throw new Exception(); - } - - private static function getStylesForArea($area) { - if ($area == 'app') { - return [ - "styles/base/jquery-ui.css", - "styles/base/colorbox.css", - "styles/app.less", - "styles/profiler.less" - ]; - } else if ($area == 'embed') { - return [ - "styles/embed.less" - ]; - } - - throw new Exception(); - } - } \ No newline at end of file diff --git a/app/library/AudioCache.php b/app/library/AudioCache.php deleted file mode 100644 index 48866988..00000000 --- a/app/library/AudioCache.php +++ /dev/null @@ -1,16 +0,0 @@ -_lastModified = $lastModified; - parent::__construct([], '', '', []); - } - - public function load(FilterInterface $additionalFilter = null) { - } - - public function getLastModified() { - return $this->_lastModified; - } - } diff --git a/app/library/External.php b/app/library/External.php deleted file mode 100644 index e2a7dbe8..00000000 --- a/app/library/External.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ - class File extends \Illuminate\Support\Facades\File - { - - public static function inline($path, $mime, $name = null) - { - if (is_null($name)) - { - $name = basename($path); - } - - $response = Response::make(static::get($path)); - - $response->header('Content-Type', $mime); - $response->header('Content-Disposition', 'inline; filename="'.$name.'"'); - $response->header('Content-Transfer-Encoding', 'binary'); - $response->header('Expires', 0); - $response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); - $response->header('Pragma', 'public'); - $response->header('Content-Length', filesize($path)); - - return $response; - } - - } diff --git a/app/library/Gravatar.php b/app/library/Gravatar.php deleted file mode 100644 index 1bb3e071..00000000 --- a/app/library/Gravatar.php +++ /dev/null @@ -1,26 +0,0 @@ -format('c'); - } - - $title = date('c', strtotime($timestamp)); - $content = date('F d, o \@ g:i:s a', strtotime($timestamp)); - return ''.$content.''; - } - } \ No newline at end of file diff --git a/app/library/IpsHasher.php b/app/library/IpsHasher.php deleted file mode 100644 index aefe0c2f..00000000 --- a/app/library/IpsHasher.php +++ /dev/null @@ -1,29 +0,0 @@ - $options['salt']]) === $hashedValue; - } - - public function needsRehash($hashedValue, array $options = array()) { - return false; - } - - static public function ips_sanitize( $value ) { - $value = str_replace('&', '&', $value); - $value = str_replace('\\', '\', $value); - $value = str_replace('!', '!', $value); - $value = str_replace('$', '$', $value); - $value = str_replace('"', '"', $value); - $value = str_replace('<', '<', $value); - $value = str_replace('>', '>', $value); - $value = str_replace('\'', ''', $value); - return $value; - } - } \ No newline at end of file diff --git a/app/library/PFMAuth.php b/app/library/PFMAuth.php deleted file mode 100644 index 3e68067e..00000000 --- a/app/library/PFMAuth.php +++ /dev/null @@ -1,21 +0,0 @@ -getPathname()); - return in_array($file->getAudioCodec(), $parameters); - } +class PfmValidator extends Illuminate\Validation\Validator +{ + /** + * Determine if a given rule implies that the attribute is required. + * + * @param string $rule + * @return bool + */ + protected function implicit($rule) + { + return $rule == 'required' or $rule == 'accepted' or $rule == 'required_with' or $rule == 'required_when'; + } + + /** + * Validate the audio format of the file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateAudioFormat($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of formats the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioCodec(), $parameters); + } - /** - * Validate the sample rate of the audio file. - * - * @param string $attribute - * @param array $value - * @param array $parameters - * @return bool - */ - public function validateSampleRate($attribute, $value, $parameters) - { - // attribute is the file field - // value is the file array itself - // parameters is a list of sample rates the file can be, verified via ffmpeg - $file = AudioCache::get($value->getPathname()); - return in_array($file->getAudioSampleRate(), $parameters); - } + /** + * Validate the sample rate of the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateSampleRate($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioSampleRate(), $parameters); + } - /** - * Validate the number of channels in the audio file. - * - * @param string $attribute - * @param array $value - * @param array $parameters - * @return bool - */ - public function validateAudioChannels($attribute, $value, $parameters) - { - // attribute is the file field - // value is the file array itself - // parameters is a list of sample rates the file can be, verified via ffmpeg - $file = AudioCache::get($value->getPathname()); - return in_array($file->getAudioChannels(), $parameters); - } + /** + * Validate the number of channels in the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateAudioChannels($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioChannels(), $parameters); + } - /** - * Validate the bit rate of the audio file. - * - * @param string $attribute - * @param array $value - * @param array $parameters - * @return bool - */ - public function validateAudioBitrate($attribute, $value, $parameters) - { - // attribute is the file field - // value is the file array itself - // parameters is a list of sample rates the file can be, verified via ffmpeg - $file = AudioCache::get($value->getPathname()); - return in_array($file->getAudioBitRate(), $parameters); - } + /** + * Validate the bit rate of the audio file. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateAudioBitrate($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is a list of sample rates the file can be, verified via ffmpeg + $file = AudioCache::get($value->getPathname()); + + return in_array($file->getAudioBitRate(), $parameters); + } - /** - * Validate the duration of the audio file, in seconds. - * - * @param string $attribute - * @param array $value - * @param array $parameters - * @return bool - */ - public function validateMinDuration($attribute, $value, $parameters) - { - // attribute is the file field - // value is the file array itself - // parameters is an array containing one value: the minimum duration - $file = AudioCache::get($value->getPathname()); - return $file->getDuration() >= (float) $parameters[0]; - } + /** + * Validate the duration of the audio file, in seconds. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + public function validateMinDuration($attribute, $value, $parameters) + { + // attribute is the file field + // value is the file array itself + // parameters is an array containing one value: the minimum duration + $file = AudioCache::get($value->getPathname()); + + return $file->getDuration() >= (float)$parameters[0]; + } - /** - * Require a field when the value of another field matches a certain value. - * - * @param string $attribute - * @param array $value - * @param array $parameters - * @return bool - */ - /** OLD CODE - public function validate_required_when($attribute, $value, $parameters) - { - if ( Input::get($parameters[0]) === $parameters[1] && static::required($attribute, $value) ){ - return true; + /** + * Require a field when the value of another field matches a certain value. + * + * @param string $attribute + * @param array $value + * @param array $parameters + * @return bool + */ + /** OLD CODE + * public function validate_required_when($attribute, $value, $parameters) + * { + * if ( Input::get($parameters[0]) === $parameters[1] && static::required($attribute, $value) ){ + * return true; + * + * } else { + * return false; + * } + * } + **/ - } else { - return false; - } - } - **/ + // custom required_when validator + public function validateRequiredWhen($attribute, $value, $parameters) + { + if (Input::get($parameters[0]) == $parameters[1]) { + return $this->validate_required($attribute, $value); + } - // custom required_when validator - public function validateRequiredWhen($attribute, $value, $parameters){ - if ( Input::get($parameters[0]) == $parameters[1] ) { - return $this->validate_required($attribute, $value); - } - - return true; - } + return true; + } - // custom image width validator - public function validateMinWidth($attribute, $value, $parameters){ - return getimagesize($value->getPathname())[0] >= $parameters[0]; - } + // custom image width validator + public function validateMinWidth($attribute, $value, $parameters) + { + return getimagesize($value->getPathname())[0] >= $parameters[0]; + } - // custom image height validator - public function validateMinHeight($attribute, $value, $parameters){ - return getimagesize($value->getPathname())[1] >= $parameters[0]; - } + // custom image height validator + public function validateMinHeight($attribute, $value, $parameters) + { + return getimagesize($value->getPathname())[1] >= $parameters[0]; + } - public function validateTextareaLength($attribute, $value, $parameters) { - return strlen(str_replace("\r\n", "\n", $value)) <= $parameters[0]; - } - } + public function validateTextareaLength($attribute, $value, $parameters) + { + return strlen(str_replace("\r\n", "\n", $value)) <= $parameters[0]; + } +} \ No newline at end of file diff --git a/app/models/AlbumDownloader.php b/app/models/AlbumDownloader.php deleted file mode 100644 index 4d2913a0..00000000 --- a/app/models/AlbumDownloader.php +++ /dev/null @@ -1,48 +0,0 @@ -_album = $album; - $this->_format = $format; - } - - function download() { - $zip = new ZipStream($this->_album->user->display_name . ' - ' . $this->_album->title . '.zip'); - $zip->setComment( - 'Album: ' . $this->_album->title ."\r\n". - 'Artist: ' . $this->_album->user->display_name ."\r\n". - 'URL: ' . $this->_album->url ."\r\n"."\r\n". - 'Downloaded on '. date('l, F jS, Y, \a\t h:i:s A') . '.' - ); - - $directory = $this->_album->user->display_name . '/' . $this->_album->title . '/'; - - $notes = - 'Album: ' . $this->_album->title ."\r\n". - 'Artist: ' . $this->_album->user->display_name ."\r\n". - 'URL: ' . $this->_album->url ."\r\n". - "\r\n". - $this->_album->description ."\r\n". - "\r\n". - "\r\n". - 'Tracks' ."\r\n". - "\r\n"; - - foreach ($this->_album->tracks as $track) { - if (!$track->is_downloadable) - continue; - - $zip->addLargeFile($track->getFileFor($this->_format), $directory . $track->getDownloadFilenameFor($this->_format)); - $notes .= - $track->track_number . '. ' . $track->title ."\r\n". - $track->description ."\r\n". - "\r\n"; - } - - $zip->addFile($notes, $directory . 'Album Notes.txt'); - $zip->finalize(); - } - } \ No newline at end of file diff --git a/app/models/Commands/AddTrackToPlaylistCommand.php b/app/models/Commands/AddTrackToPlaylistCommand.php deleted file mode 100644 index e016743c..00000000 --- a/app/models/Commands/AddTrackToPlaylistCommand.php +++ /dev/null @@ -1,43 +0,0 @@ -_playlist = Playlist::find($playlistId); - $this->_track = Track::find($trackId); - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $user != null && $this->_playlist && $this->_track && $this->_playlist->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $songIndex = $this->_playlist->tracks()->count() + 1; - $this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]); - - Playlist::whereId($this->_playlist->id)->update([ - 'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = ' . $this->_playlist->id . ')') - ]); - - return CommandResponse::succeed(['message' => 'Track added!']); - } - } \ No newline at end of file diff --git a/app/models/Commands/CommandBase.php b/app/models/Commands/CommandBase.php deleted file mode 100644 index 6776c0d7..00000000 --- a/app/models/Commands/CommandBase.php +++ /dev/null @@ -1,29 +0,0 @@ -_listeners[] = $listener; - } - - protected function notify($message, $progress) { - foreach ($this->_listeners as $listener) { - $listener($message, $progress); - } - } - - /** - * @return bool - */ - public function authorize() { - return true; - } - - /** - * @return CommandResponse - */ - public abstract function execute(); - } \ No newline at end of file diff --git a/app/models/Commands/CommandResponse.php b/app/models/Commands/CommandResponse.php deleted file mode 100644 index 707b58e9..00000000 --- a/app/models/Commands/CommandResponse.php +++ /dev/null @@ -1,49 +0,0 @@ -_didFail = true; - $response->_validator = $validator; - return $response; - } - - public static function succeed($response = null) { - $cmdResponse = new CommandResponse(); - $cmdResponse->_didFail = false; - $cmdResponse->_response = $response; - return $cmdResponse; - } - - private $_validator; - private $_response; - private $_didFail; - - private function __construct() { - } - - /** - * @return bool - */ - public function didFail() { - return $this->_didFail; - } - - /** - * @return mixed - */ - public function getResponse() { - return $this->_response; - } - - /** - * @return Validator - */ - public function getValidator() { - return $this->_validator; - } - } \ No newline at end of file diff --git a/app/models/Commands/CreateAlbumCommand.php b/app/models/Commands/CreateAlbumCommand.php deleted file mode 100644 index 295b0491..00000000 --- a/app/models/Commands/CreateAlbumCommand.php +++ /dev/null @@ -1,65 +0,0 @@ -_input = $input; - } - - /** - * @return bool - */ - public function authorize() { - $user = \Auth::user(); - return $user != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $rules = [ - 'title' => 'required|min:3|max:50', - 'cover' => 'image|mimes:png|min_width:350|min_height:350', - 'cover_id' => 'exists:images,id', - 'track_ids' => 'exists:tracks,id' - ]; - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $album = new Album(); - $album->user_id = Auth::user()->id; - $album->title = $this->_input['title']; - $album->description = $this->_input['description']; - - if (isset($this->_input['cover_id'])) { - $album->cover_id = $this->_input['cover_id']; - } - else if (isset($this->_input['cover'])) { - $cover = $this->_input['cover']; - $album->cover_id = Image::upload($cover, Auth::user())->id; - } else if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') - $album->cover_id = null; - - $trackIds = explode(',', $this->_input['track_ids']); - $album->save(); - $album->syncTrackIds($trackIds); - - return CommandResponse::succeed(['id' => $album->id]); - } - } \ No newline at end of file diff --git a/app/models/Commands/CreateCommentCommand.php b/app/models/Commands/CreateCommentCommand.php deleted file mode 100644 index a18e7744..00000000 --- a/app/models/Commands/CreateCommentCommand.php +++ /dev/null @@ -1,71 +0,0 @@ -_input = $input; - $this->_id = $id; - $this->_type = $type; - } - - /** - * @return bool - */ - public function authorize() { - $user = \Auth::user(); - return $user != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $rules = [ - 'content' => 'required', - 'track_id' => 'exists:tracks,id', - 'albums_id' => 'exists:albums,id', - 'playlist_id' => 'exists:playlists,id', - 'profile_id' => 'exists:users,id', - ]; - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $comment = new Comment(); - $comment->user_id = Auth::user()->id; - $comment->content = $this->_input['content']; - - if ($this->_type == 'track') - $column = 'track_id'; - else if ($this->_type == 'user') - $column = 'profile_id'; - else if ($this->_type == 'album') - $column = 'album_id'; - else if ($this->_type == 'playlist') - $column = 'playlist_id'; - else - App::abort(500); - - $comment->$column = $this->_id; - $comment->save(); - - return CommandResponse::succeed(Comment::mapPublic($comment)); - } - } \ No newline at end of file diff --git a/app/models/Commands/CreatePlaylistCommand.php b/app/models/Commands/CreatePlaylistCommand.php deleted file mode 100644 index eed3616e..00000000 --- a/app/models/Commands/CreatePlaylistCommand.php +++ /dev/null @@ -1,68 +0,0 @@ -_input = $input; - } - - /** - * @return bool - */ - public function authorize() { - $user = \Auth::user(); - return $user != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $rules = [ - 'title' => 'required|min:3|max:50', - 'is_public' => 'required', - 'is_pinned' => 'required' - ]; - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $playlist = new Playlist(); - $playlist->user_id = Auth::user()->id; - $playlist->title = $this->_input['title']; - $playlist->description = $this->_input['description']; - $playlist->is_public = $this->_input['is_public'] == 'true'; - - $playlist->save(); - - if ($this->_input['is_pinned'] == 'true') { - $playlist->pin(Auth::user()->id); - } - - return CommandResponse::succeed([ - 'id' => $playlist->id, - 'title' => $playlist->title, - 'slug' => $playlist->slug, - 'created_at' => $playlist->created_at, - 'description' => $playlist->description, - 'url' => $playlist->url, - 'is_pinned' => $this->_input['is_pinned'] == 'true', - 'is_public' => $this->_input['is_public'] == 'true']); - } - } \ No newline at end of file diff --git a/app/models/Commands/DeleteAlbumCommand.php b/app/models/Commands/DeleteAlbumCommand.php deleted file mode 100644 index fb13bd41..00000000 --- a/app/models/Commands/DeleteAlbumCommand.php +++ /dev/null @@ -1,41 +0,0 @@ -_albumId = $albumId; - $this->_album = ALbum::find($albumId); - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $this->_album && $user != null && $this->_album->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - foreach ($this->_album->tracks as $track) { - $track->album_id = null; - $track->track_number = null; - $track->updateTags(); - $track->save(); - } - - $this->_album->delete(); - return CommandResponse::succeed(); - } - } \ No newline at end of file diff --git a/app/models/Commands/DeletePlaylistCommand.php b/app/models/Commands/DeletePlaylistCommand.php deleted file mode 100644 index 1779b297..00000000 --- a/app/models/Commands/DeletePlaylistCommand.php +++ /dev/null @@ -1,39 +0,0 @@ -_playlistId = $playlistId; - $this->_playlist = Playlist::find($playlistId); - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - foreach ($this->_playlist->pins as $pin) { - $pin->delete(); - } - - $this->_playlist->delete(); - return CommandResponse::succeed(); - } - } \ No newline at end of file diff --git a/app/models/Commands/DeleteTrackCommand.php b/app/models/Commands/DeleteTrackCommand.php deleted file mode 100644 index f2f11c4f..00000000 --- a/app/models/Commands/DeleteTrackCommand.php +++ /dev/null @@ -1,40 +0,0 @@ -_trackId = $trackId; - $this->_track = Track::find($trackId); - } - - /** - * @return bool - */ - public function authorize() { - $user = \Auth::user(); - return $this->_track && $user != null && $this->_track->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - if ($this->_track->album_id != null) { - $album = $this->_track->album; - $this->_track->album_id = null; - $this->_track->track_number = null; - $this->_track->delete(); - $album->updateTrackNumbers(); - } else - $this->_track->delete(); - - return CommandResponse::succeed(); - } - } \ No newline at end of file diff --git a/app/models/Commands/EditAlbumCommand.php b/app/models/Commands/EditAlbumCommand.php deleted file mode 100644 index 3f7cf989..00000000 --- a/app/models/Commands/EditAlbumCommand.php +++ /dev/null @@ -1,71 +0,0 @@ -_input = $input; - $this->_albumId = $trackId; - $this->_album = Album::find($trackId); - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $this->_album && $user != null && $this->_album->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $rules = [ - 'title' => 'required|min:3|max:50', - 'cover' => 'image|mimes:png|min_width:350|min_height:350', - 'cover_id' => 'exists:images,id', - 'track_ids' => 'exists:tracks,id' - ]; - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $this->_album->title = $this->_input['title']; - $this->_album->description = $this->_input['description']; - - if (isset($this->_input['cover_id'])) { - $this->_album->cover_id = $this->_input['cover_id']; - } - else if (isset($this->_input['cover'])) { - $cover = $this->_input['cover']; - $this->_album->cover_id = Image::upload($cover, Auth::user())->id; - } else if (isset($this->_input['remove_cover']) && $this->_input['remove_cover'] == 'true') - $this->_album->cover_id = null; - - $trackIds = explode(',', $this->_input['track_ids']); - $this->_album->syncTrackIds($trackIds); - $this->_album->save(); - - Album::whereId($this->_album->id)->update([ - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $this->_album->id . ')') - ]); - - return CommandResponse::succeed(['real_cover_url' => $this->_album->getCoverUrl(Image::NORMAL)]); - } - } \ No newline at end of file diff --git a/app/models/Commands/EditPlaylistCommand.php b/app/models/Commands/EditPlaylistCommand.php deleted file mode 100644 index e4599ae9..00000000 --- a/app/models/Commands/EditPlaylistCommand.php +++ /dev/null @@ -1,72 +0,0 @@ -_input = $input; - $this->_playlistId = $playlistId; - $this->_playlist = Playlist::find($playlistId); - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $this->_playlist && $user != null && $this->_playlist->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $rules = [ - 'title' => 'required|min:3|max:50', - 'is_public' => 'required', - 'is_pinned' => 'required' - ]; - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $this->_playlist->title = $this->_input['title']; - $this->_playlist->description = $this->_input['description']; - $this->_playlist->is_public = $this->_input['is_public'] == 'true'; - - $this->_playlist->save(); - - $pin = PinnedPlaylist::whereUserId(Auth::user()->id)->wherePlaylistId($this->_playlistId)->first(); - if ($pin && $this->_input['is_pinned'] != 'true') - $pin->delete(); - else if (!$pin && $this->_input['is_pinned'] == 'true') { - $this->_playlist->pin(Auth::user()->id); - } - - return CommandResponse::succeed([ - 'id' => $this->_playlist->id, - 'title' => $this->_playlist->title, - 'slug' => $this->_playlist->slug, - 'created_at' => $this->_playlist->created_at, - 'description' => $this->_playlist->description, - 'url' => $this->_playlist->url, - 'is_pinned' => $this->_input['is_pinned'] == 'true', - 'is_public' => $this->_input['is_public'] == 'true']); - } - } \ No newline at end of file diff --git a/app/models/Commands/EditTrackCommand.php b/app/models/Commands/EditTrackCommand.php deleted file mode 100644 index 6976e206..00000000 --- a/app/models/Commands/EditTrackCommand.php +++ /dev/null @@ -1,146 +0,0 @@ -_trackId = $trackId; - $this->_track = Track::find($trackId); - $this->_input = $input; - } - - /** - * @return bool - */ - public function authorize() { - $user = \Auth::user(); - return $this->_track && $user != null && $this->_track->user_id == $user->id; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $isVocal = (isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true') ? true : false; - - $rules = [ - 'title' => 'required|min:3|max:80', - 'released_at' => 'before:' . (date('Y-m-d', time() + (86400 * 2))) . (isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? '|date' : ''), - 'license_id' => 'required|exists:licenses,id', - 'genre_id' => 'required|exists:genres,id', - 'cover' => 'image|mimes:png|min_width:350|min_height:350', - 'track_type_id' => 'required|exists:track_types,id', - 'songs' => 'required_when:track_type,2|exists:songs,id', - 'cover_id' => 'exists:images,id', - 'album_id' => 'exists:albums,id' - ]; - - if ($isVocal) - $rules['lyrics'] = 'required'; - - if (isset($this->_input['track_type_id']) && $this->_input['track_type_id'] == 2) - $rules['show_song_ids'] = 'required|exists:show_songs,id'; - - $validator = \Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $track = $this->_track; - $track->title = $this->_input['title']; - $track->released_at = isset($this->_input['released_at']) && $this->_input['released_at'] != "" ? strtotime($this->_input['released_at']) : null; - $track->description = isset($this->_input['description']) ? $this->_input['description'] : ''; - $track->lyrics = isset($this->_input['lyrics']) ? $this->_input['lyrics'] : ''; - $track->license_id = $this->_input['license_id']; - $track->genre_id = $this->_input['genre_id']; - $track->track_type_id = $this->_input['track_type_id']; - $track->is_explicit = $this->_input['is_explicit'] == 'true'; - $track->is_downloadable = $this->_input['is_downloadable'] == 'true'; - $track->is_listed = $this->_input['is_listed'] == 'true'; - $track->is_vocal = $isVocal; - - if (isset($this->_input['album_id']) && strlen(trim($this->_input['album_id']))) { - if ($track->album_id != null && $track->album_id != $this->_input['album_id']) - $this->removeTrackFromAlbum($track); - - if ($track->album_id != $this->_input['album_id']) { - $album = Album::find($this->_input['album_id']); - $track->track_number = $album->tracks()->count() + 1; - $track->album_id = $this->_input['album_id']; - - Album::whereId($album->id)->update([ - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') - ]); - } - } else { - if ($track->album_id != null) { - $this->removeTrackFromAlbum($track); - } - - $track->track_number = null; - $track->album_id = null; - } - - if ($track->track_type_id == 2) { - $track->showSongs()->sync(explode(',', $this->_input['show_song_ids'])); - } else - $track->showSongs()->sync([]); - - if ($track->published_at == null) { - $track->published_at = new \DateTime(); - - DB::table('tracks')->whereUserId($track->user_id)->update(['is_latest' => false]); - $track->is_latest = true; - } - - if (isset($this->_input['cover_id'])) { - $track->cover_id = $this->_input['cover_id']; - } - else if (isset($this->_input['cover'])) { - $cover = $this->_input['cover']; - $track->cover_id = Image::upload($cover, Auth::user())->id; - } else if ($this->_input['remove_cover'] == 'true') - $track->cover_id = null; - - $track->updateTags(); - $track->save(); - - User::whereId($this->_track->user_id)->update([ - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE deleted_at IS NULL AND published_at IS NOT NULL AND user_id = ' . $this->_track->user_id . ')') - ]); - - return CommandResponse::succeed(['real_cover_url' => $track->getCoverUrl(Image::NORMAL)]); - } - - private function removeTrackFromAlbum($track) { - $album = $track->album; - $index = 0; - - foreach ($album->tracks as $track) { - if ($track->id == $this->_trackId) - continue; - - $track->track_number = ++$index; - $track->updateTags(); - $track->save(); - } - - Album::whereId($album->id)->update([ - 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') - ]); - } - } \ No newline at end of file diff --git a/app/models/Commands/SaveAccountSettingsCommand.php b/app/models/Commands/SaveAccountSettingsCommand.php deleted file mode 100644 index 14089ed4..00000000 --- a/app/models/Commands/SaveAccountSettingsCommand.php +++ /dev/null @@ -1,79 +0,0 @@ -_input = $input; - } - - /** - * @return bool - */ - public function authorize() { - return Auth::user() != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $user = Auth::user(); - - $rules = [ - 'display_name' => 'required|min:3|max:26', - 'bio' => 'textarea_length:250' - ]; - - if ($this->_input['sync_names'] == 'true') - $this->_input['display_name'] = $user->mlpforums_name; - - if ($this->_input['uses_gravatar'] == 'true') { - $rules['gravatar'] = 'email'; - } else { - $rules['avatar'] = 'image|mimes:png|min_width:350|min_height:350'; - $rules['avatar_id'] = 'exists:images,id'; - } - - $validator = Validator::make($this->_input, $rules); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - if ($this->_input['uses_gravatar'] != 'true') { - if ($user->avatar_id == null && !isset($this->_input['avatar']) && !isset($this->_input['avatar_id'])) { - $validator->messages()->add('avatar', 'You must upload or select an avatar if you are not using gravatar!'); - return CommandResponse::fail($validator); - } - } - - $user->bio = $this->_input['bio']; - $user->display_name = $this->_input['display_name']; - $user->sync_names = $this->_input['sync_names'] == 'true'; - $user->can_see_explicit_content = $this->_input['can_see_explicit_content'] == 'true'; - $user->uses_gravatar = $this->_input['uses_gravatar'] == 'true'; - - if ($user->uses_gravatar) { - $user->avatar_id = null; - $user->gravatar = $this->_input['gravatar']; - } else { - if (isset($this->_input['avatar_id'])) - $user->avatar_id = $this->_input['avatar_id']; - else if (isset($this->_input['avatar'])) - $user->avatar_id = Image::upload($this->_input['avatar'], $user)->id; - } - - $user->save(); - - return CommandResponse::succeed(); - } - } \ No newline at end of file diff --git a/app/models/Commands/ToggleFavouriteCommand.php b/app/models/Commands/ToggleFavouriteCommand.php deleted file mode 100644 index 106dd7d3..00000000 --- a/app/models/Commands/ToggleFavouriteCommand.php +++ /dev/null @@ -1,71 +0,0 @@ -_resourceId = $resourceId; - $this->_resourceType = $resourceType; - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return$user != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $typeId = $this->_resourceType . '_id'; - $existing = Favourite::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); - $isFavourited = false; - - if ($existing) { - $existing->delete(); - } else { - $fav = new Favourite(); - $fav->$typeId = $this->_resourceId; - $fav->user_id = Auth::user()->id; - $fav->created_at = time(); - $fav->save(); - $isFavourited = true; - } - - $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); - $resourceUser->is_favourited = $isFavourited; - $resourceUser->save(); - - $resourceTable = $this->_resourceType . 's'; - - // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db - // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created - // for the same resource at the same time, the cached values will still be correct with this method. - - DB::table($resourceTable)->whereId($this->_resourceId)->update(['favourite_count' => - DB::raw('( - SELECT - COUNT(id) - FROM - favourites - WHERE ' . - $typeId . ' = ' . $this->_resourceId . ')')]); - - return CommandResponse::succeed(['is_favourited' => $isFavourited]); - } - } \ No newline at end of file diff --git a/app/models/Commands/ToggleFollowingCommand.php b/app/models/Commands/ToggleFollowingCommand.php deleted file mode 100644 index b8273e90..00000000 --- a/app/models/Commands/ToggleFollowingCommand.php +++ /dev/null @@ -1,57 +0,0 @@ -_resourceId = $resourceId; - $this->_resourceType = $resourceType; - } - - /** - * @return bool - */ - public function authorize() { - $user = Auth::user(); - return $user != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $typeId = $this->_resourceType . '_id'; - $existing = Follower::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); - $isFollowed = false; - - if ($existing) { - $existing->delete(); - } else { - $follow = new Follower(); - $follow->$typeId = $this->_resourceId; - $follow->user_id = Auth::user()->id; - $follow->created_at = time(); - $follow->save(); - $isFollowed = true; - } - - $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); - $resourceUser->is_followed = $isFollowed; - $resourceUser->save(); - - return CommandResponse::succeed(['is_followed' => $isFollowed]); - } - } \ No newline at end of file diff --git a/app/models/Commands/UploadTrackCommand.php b/app/models/Commands/UploadTrackCommand.php deleted file mode 100644 index bc5f2cc0..00000000 --- a/app/models/Commands/UploadTrackCommand.php +++ /dev/null @@ -1,148 +0,0 @@ -_allowLossy = $allowLossy; - $this->_allowShortTrack = $allowShortTrack; - } - - /** - * @return bool - */ - public function authorize() { - return \Auth::user() != null; - } - - /** - * @throws \Exception - * @return CommandResponse - */ - public function execute() { - $user = \Auth::user(); - $trackFile = \Input::file('track'); - $audio = \AudioCache::get($trackFile->getPathname()); - - $validator = \Validator::make(['track' => $trackFile], [ - 'track' => - 'required|' - . ($this->_allowLossy ? '' : 'audio_format:'. implode(',', $this->_losslessFormats).'|') - . ($this->_allowShortTrack ? '' : 'min_duration:30|') - . 'audio_channels:1,2|' - . 'sample_rate:44100,48000,88200,96000,176400,192000' - ]); - - if ($validator->fails()) - return CommandResponse::fail($validator); - - $track = new Track(); - - try { - $track->user_id = $user->id; - $track->title = pathinfo($trackFile->getClientOriginalName(), PATHINFO_FILENAME); - $track->duration = $audio->getDuration(); - $track->is_listed = true; - - $track->save(); - - $destination = $track->getDirectory(); - $track->ensureDirectoryExists(); - - $source = $trackFile->getPathname(); - $index = 0; - - $processes = []; - - // Lossy uploads need to be identified and set as the master file - // without being re-encoded. - $audioObject = AudioCache::get($source); - $isLossyUpload = !in_array($audioObject->getAudioCodec(), $this->_losslessFormats); - - if ($isLossyUpload) { - if ($audioObject->getAudioCodec() === 'mp3') { - $masterFormat = 'MP3'; - - } else if (Str::startsWith($audioObject->getAudioCodec(), 'aac')) { - $masterFormat = 'AAC'; - - } else if ($audioObject->getAudioCodec() === 'vorbis') { - $masterFormat = 'OGG Vorbis'; - - } else { - $validator->messages()->add('track', 'The track does not contain audio in a known lossy format.'); - return CommandResponse::fail($validator); - } - - $trackFile = new TrackFile(); - $trackFile->is_master = true; - $trackFile->format = $masterFormat; - $trackFile->track_id = $track->id; - $trackFile->save(); - - // Lossy masters are copied into the datastore - no re-encoding involved. - File::copy($source, $trackFile->getFile()); - } - - foreach (Track::$Formats as $name => $format) { - // Don't bother with lossless transcodes of lossy uploads, and - // don't re-encode the lossy master. - if ($isLossyUpload && ($format['is_lossless'] || $name === $masterFormat)) { - continue; - } - - $trackFile = new TrackFile(); - $trackFile->is_master = $name === 'FLAC' ? true : false; - $trackFile->format = $name; - $track->trackFiles()->save($trackFile); - - $target = $destination . '/' . $trackFile->getFilename(); //$track->getFilenameFor($name); - - $command = $format['command']; - $command = str_replace('{$source}', '"' . $source . '"', $command); - $command = str_replace('{$target}', '"' . $target . '"', $command); - - Log::info('Encoding ' . $track->id . ' into ' . $target); - $this->notify('Encoding ' . $name, $index / count(Track::$Formats) * 100); - - $pipes = []; - $proc = proc_open($command, [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'a']], $pipes); - $processes[] = $proc; - } - - foreach ($processes as $proc) - proc_close($proc); - - $track->updateTags(); - - } catch (\Exception $e) { - $track->delete(); - throw $e; - } - - return CommandResponse::succeed([ - 'id' => $track->id, - 'name' => $track->name - ]); - } - } diff --git a/app/models/Entities/Album.php b/app/models/Entities/Album.php deleted file mode 100644 index e340ed0a..00000000 --- a/app/models/Entities/Album.php +++ /dev/null @@ -1,285 +0,0 @@ -with(['users' => function($query) { - $query->whereUserId(Auth::user()->id); - }]); - } - - return !$query; - } - - protected $table = 'albums'; - - public function user() { - return $this->belongsTo('Entities\User'); - } - - public function users() { - return $this->hasMany('Entities\ResourceUser'); - } - - public function favourites() { - return $this->hasMany('Entities\Favourite'); - } - - public function cover() { - return $this->belongsTo('Entities\Image'); - } - - public function tracks() { - return $this->hasMany('Entities\Track')->orderBy('track_number', 'asc'); - } - - public function comments(){ - return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); - } - - public static function mapPublicAlbumShow($album) { - $tracks = []; - foreach ($album->tracks as $track) { - $tracks[] = Track::mapPublicTrackSummary($track); - } - - $formats = []; - foreach (Track::$Formats as $name => $format) { - $formats[] = [ - 'name' => $name, - 'extension' => $format['extension'], - 'url' => $album->getDownloadUrl($name), - 'size' => Helpers::formatBytes($album->getFilesize($name)) - ]; - } - - $comments = []; - foreach ($album->comments as $comment) { - $comments[] = Comment::mapPublic($comment); - } - - $is_downloadable = 0; - foreach ($album->tracks as $track) { - if ($track->is_downloadable == 1) { - $is_downloadable = 1; - break; - } - } - - $data = self::mapPublicAlbumSummary($album); - $data['tracks'] = $tracks; - $data['comments'] = $comments; - $data['formats'] = $formats; - $data['description'] = $album->description; - $data['is_downloadable'] = $is_downloadable; - $data['share'] = [ - 'url' => URL::to('/a' . $album->id), - 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($album->url) . '&name=' . urlencode($album->title) . '&description=' . urlencode($album->description), - 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $album->title . ' by ' . $album->user->display_name . ' on Pony.fm' - ]; - - return $data; - } - - public static function mapPublicAlbumSummary($album) { - $userData = [ - 'stats' => [ - 'views' => 0, - 'downloads' => 0 - ], - 'is_favourited' => false - ]; - - if (Auth::check() && $album->users->count()) { - $userRow = $album->users[0]; - $userData = [ - 'stats' => [ - 'views' => (int) $userRow->view_count, - 'downloads' => (int) $userRow->download_count, - ], - 'is_favourited' => (bool) $userRow->is_favourited - ]; - } - - return [ - 'id' => (int) $album->id, - 'track_count' => (int) $album->track_count, - 'title' => $album->title, - 'slug' => $album->slug, - 'created_at' => $album->created_at, - 'stats' => [ - 'views' => (int) $album->view_count, - 'downloads' => (int) $album->download_count, - 'comments' => (int) $album->comment_count, - 'favourites' => (int) $album->favourite_count - ], - 'covers' => [ - 'small' => $album->getCoverUrl(Image::SMALL), - 'normal' => $album->getCoverUrl(Image::NORMAL) - ], - 'url' => $album->url, - 'user' => [ - 'id' => (int) $album->user->id, - 'name' => $album->user->display_name, - 'url' => $album->user->url, - ], - 'user_data' => $userData, - 'permissions' => [ - 'delete' => Auth::check() && Auth::user()->id == $album->user_id, - 'edit' => Auth::check() && Auth::user()->id == $album->user_id - ] - ]; - } - - public function hasCover() { - return $this->cover_id != null; - } - - public function getUrlAttribute() { - return URL::to('albums/' . $this->id . '-' . $this->slug); - } - - public function getDownloadUrl($format) { - return URL::to('a' . $this->id . '/dl.' . Track::$Formats[$format]['extension']); - } - - public function getFilesize($format) { - $tracks = $this->tracks; - if (!count($tracks)) - return 0; - - return Cache::remember($this->getCacheKey('filesize-' . $format), 1440, function() use ($tracks, $format) { - $size = 0; - foreach ($tracks as $track) { - // Ensure that only downloadable tracks are added onto the file size - if ($track->is_downloadable == 1) { - $size += $track->getFilesize($format); - } - } - - return $size; - }); - } - - public function getCoverUrl($type = Image::NORMAL) { - if (!$this->hasCover()) - return $this->user->getAvatarUrl($type); - - return $this->cover->getUrl($type); - } - - public function getDirectory() { - $dir = (string) ( floor( $this->id / 100 ) * 100 ); - return \Config::get('app.files_directory') . '/tracks/' . $dir; - } - - public function getDates() { - return ['created_at', 'deleted_at', 'published_at']; - } - - public function getFilenameFor($format) { - if (!isset(Track::$Formats[$format])) - throw new Exception("$format is not a valid format!"); - - $format = Track::$Formats[$format]; - return "{$this->id}.{$format['extension']}.zip"; - } - - public function updateTrackNumbers() { - $tracks = Track::whereAlbumId($this->id)->get(); - $index = 1; - - foreach ($tracks as $track) { - $track->track_number = $index; - $index++; - $track->updateTags(); - $track->save(); - } - } - - public function syncTrackIds($trackIds) { - $trackIdsInAlbum = []; - foreach ($this->tracks as $track) { - $trackIdsInAlbum[] = $track->id; - } - - $trackIdsCount = count($trackIds); - $trackIdsInAlbumCount = count($trackIdsInAlbum); - $isSame = true; - - if ($trackIdsInAlbumCount != $trackIdsCount) - $isSame = false; - else - for ($i = 0; $i < $trackIdsInAlbumCount; $i++) { - if ($i >= $trackIdsCount || $trackIdsInAlbum[$i] != $trackIds[$i]) { - $isSame = false; - break; - } - } - - if ($isSame) - return; - - $index = 1; - $tracksToRemove = []; - $albumsToFix = []; - - foreach ($this->tracks as $track) - $tracksToRemove[$track->id] = $track; - - foreach ($trackIds as $trackId) { - if (!strlen(trim($trackId))) - continue; - - $track = Track::find($trackId); - if ($track->album_id != null && $track->album_id != $this->id) { - $albumsToFix[] = $track->album; - } - - $track->album_id = $this->id; - $track->track_number = $index; - $track->updateTags(); - $track->save(); - - unset($tracksToRemove[$track->id]); - $index++; - } - - foreach ($tracksToRemove as $track) { - $track->album_id = null; - $track->track_number = null; - $track->updateTags(); - $track->save(); - } - - foreach ($albumsToFix as $album) { - $album->updateTrackNumbers(); - } - - foreach (Track::$Formats as $name => $format) { - Cache::forget($this->getCacheKey('filesize' . $name)); - } - } - - private function getCacheKey($key) { - return 'album-' . $this->id . '-' . $key; - } - } diff --git a/app/models/Entities/Comment.php b/app/models/Entities/Comment.php deleted file mode 100644 index 0a5d4c42..00000000 --- a/app/models/Entities/Comment.php +++ /dev/null @@ -1,62 +0,0 @@ -belongsTo('Entities\User'); - } - - public function track(){ - return $this->belongsTo('Entities\Track'); - } - - public function album(){ - return $this->belongsTo('Entities\Album'); - } - - public function playlist(){ - return $this->belongsTo('Entities\Playlist'); - } - - public function profile(){ - return $this->belongsTo('Entities\User', 'profile_id'); - } - - public static function mapPublic($comment) { - return [ - 'id' => $comment->id, - 'created_at' => $comment->created_at, - 'content' => $comment->content, - 'user' => [ - 'name' => $comment->user->display_name, - 'id' => $comment->user->id, - 'url' => $comment->user->url, - 'avatars' => [ - 'normal' => $comment->user->getAvatarUrl(Image::NORMAL), - 'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL), - 'small' => $comment->user->getAvatarUrl(Image::SMALL), - ] - ] - ]; - } - - public function getResourceAttribute(){ - if($this->track_id !== NULL) - return $this->track; - - else if($this->album_id !== NULL) - return $this->album; - - else if($this->playlist_id !== NULL) - return $this->playlist; - - else if($this->profile_id !== NULL) - return $this->profile; - - else return NULL; - } - } \ No newline at end of file diff --git a/app/models/Entities/Favourite.php b/app/models/Entities/Favourite.php deleted file mode 100644 index 8afdf064..00000000 --- a/app/models/Entities/Favourite.php +++ /dev/null @@ -1,54 +0,0 @@ -belongsTo('Entities\User'); - } - - public function track() { - return $this->belongsTo('Entities\Track'); - } - - public function album() { - return $this->belongsTo('Entities\Album'); - } - - public function playlist() { - return $this->belongsTo('Entities\Playlist'); - } - - /** - * Return the resource associated with this favourite. - * - * @return Resource|NULL - */ - public function getResourceAttribute(){ - if ($this->track_id) - return $this->track; - - else if($this->album_id) - return $this->album; - - else if($this->playlist_id) - return $this->playlist; - - // no resource - this should never happen under real circumstances - else - return null; - } - - public function getTypeAttribute(){ - return get_class($this->resource); - } - } \ No newline at end of file diff --git a/app/models/Entities/Follower.php b/app/models/Entities/Follower.php deleted file mode 100644 index 0d95e8c4..00000000 --- a/app/models/Entities/Follower.php +++ /dev/null @@ -1,9 +0,0 @@ - ['id' => self::NORMAL, 'name' => 'normal', 'width' => 350, 'height' => 350], - self::ORIGINAL => ['id' => self::ORIGINAL, 'name' => 'original', 'width' => null, 'height' => null], - self::SMALL => ['id' => self::SMALL, 'name' => 'small', 'width' => 100, 'height' => 100], - self::THUMBNAIL => ['id' => self::THUMBNAIL, 'name' => 'thumbnail', 'width' => 50, 'height' => 50] - ]; - - public static function getImageTypeFromName($name) { - foreach (self::$ImageTypes as $cover) { - if ($cover['name'] != $name) - continue; - - return $cover; - } - - return null; - } - - public static function upload(UploadedFile $file, $user) { - $userId = $user; - if ($user instanceof User) - $userId = $user->id; - - $hash = md5_file($file->getPathname()); - $image = Image::whereHash($hash)->whereUploadedBy($userId)->first(); - - if ($image) - return $image; - - $image = new Image(); - try { - $image->uploaded_by = $userId; - $image->size = $file->getSize(); - $image->filename = $file->getClientOriginalName(); - $image->extension = $file->getClientOriginalExtension(); - $image->mime = $file->getMimeType(); - $image->hash = $hash; - $image->save(); - - $image->ensureDirectoryExists(); - foreach (self::$ImageTypes as $coverType) { - $command = 'convert 2>&1 "' . $file->getPathname() . '" -background transparent -flatten +matte -strip -quality 95 -format png '; - if (isset($coverType['width']) && isset($coverType['height'])) - $command .= '-thumbnail ' . $coverType['width'] . 'x' . $coverType['height'] . '^ -gravity center -extent ' . $coverType['width'] . 'x' . $coverType['height'] . ' '; - - $command .= '"' . $image->getFile($coverType['id']) . '"'; - External::execute($command); - } - - return $image; - } - catch (\Exception $e) { - $image->delete(); - throw $e; - } - } - - protected $table = 'images'; - - public function getUrl($type = self::NORMAL) { - $type = self::$ImageTypes[$type]; - return URL::to('i' . $this->id . '/' . $type['name'] . '.png'); - } - - public function getFile($type = self::NORMAL) { - return $this->getDirectory() . '/' . $this->getFilename($type); - } - - public function getFilename($type = self::NORMAL) { - $typeInfo = self::$ImageTypes[$type]; - return $this->id . '_' . $typeInfo['name'] . '.png'; - } - - public function getDirectory() { - $dir = (string) ( floor( $this->id / 100 ) * 100 ); - return Config::get('app.files_directory') . '/images/' . $dir; - } - - public function ensureDirectoryExists() { - $destination = $this->getDirectory(); - umask(0); - - if (!is_dir($destination)) - mkdir($destination, 0777, true); - } - } diff --git a/app/models/Entities/License.php b/app/models/Entities/License.php deleted file mode 100644 index de63d8e4..00000000 --- a/app/models/Entities/License.php +++ /dev/null @@ -1,7 +0,0 @@ -cache = false; - $feed->set_feed_url('http://mlpforums.com/blog/rss/404-ponyfm-development-blog/'); - $feed->init(); - $feed->handle_content_type(); - - $posts = $feed->get_items($start, $end); - $postHashes = []; - - foreach ($posts as $post) { - $postHashes[] = self::calculateHash($post->get_permalink()); - } - - if (count($postHashes) == 0) - return []; - - $seenRecords = Auth::check() ? self::where('user_id', '=', Auth::user()->id)->whereIn('post_hash', $postHashes)->get() : []; - $seenHashes = []; - - foreach ($seenRecords as $record) { - $seenHashes[$record->post_hash] = 1; - } - - $postsReturn = []; - - // This date is around when the last blog post was posted as of now. - // I put in a cutoff so that blog posts made before this update is pushed are always marked as 'read' - $readCutoffDate = mktime(null, null, null, 4, 28, 2013); - - foreach ($posts as $post) { - $autoRead = $post->get_date('U') < $readCutoffDate; - $postsReturn[] = [ - 'title' => $post->get_title(), - 'date' => $post->get_date('j F Y g:i a'), - 'url' => $post->get_permalink(), - 'read' => $autoRead || isset($seenHashes[self::calculateHash($post->get_permalink())])]; - } - - return $postsReturn; - } - - public static function markPostAsRead($postUrl) { - $postHash = self::calculateHash($postUrl); - $news = new News(); - $news->user_id = Auth::user()->id; - $news->post_hash = $postHash; - $news->save(); - } - - private static function calculateHash($postPermalink) { - return md5($postPermalink); - } - } \ No newline at end of file diff --git a/app/models/Entities/PinnedPlaylist.php b/app/models/Entities/PinnedPlaylist.php deleted file mode 100644 index d7d05ee3..00000000 --- a/app/models/Entities/PinnedPlaylist.php +++ /dev/null @@ -1,16 +0,0 @@ -belongsTo('Entities\User'); - } - - public function playlist() { - return $this->belongsTo('Entities\Playlist'); - } - } \ No newline at end of file diff --git a/app/models/Entities/Playlist.php b/app/models/Entities/Playlist.php deleted file mode 100644 index ff70bcd3..00000000 --- a/app/models/Entities/Playlist.php +++ /dev/null @@ -1,193 +0,0 @@ -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; - $data['share'] = [ - 'url' => URL::to('/p' . $playlist->id), - 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($playlist->url) . '&name=' . urlencode($playlist->title) . '&description=' . urlencode($playlist->description), - 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $playlist->title . ' by ' . $playlist->user->display_name . ' on Pony.fm' - ]; - - return $data; - } - - public static function mapPublicPlaylistSummary($playlist) { - $userData = [ - 'stats' => [ - 'views' => 0, - 'downloads' => 0 - ], - 'is_favourited' => false - ]; - - if (Auth::check() && $playlist->users->count()) { - $userRow = $playlist->users[0]; - $userData = [ - 'stats' => [ - 'views' => (int) $userRow->view_count, - 'downloads' => (int) $userRow->download_count, - ], - 'is_favourited' => (bool) $userRow->is_favourited - ]; - } - - return [ - 'id' => (int) $playlist->id, - 'track_count' => $playlist->track_count, - 'title' => $playlist->title, - 'slug' => $playlist->slug, - 'created_at' => $playlist->created_at, - 'is_public' => (bool) $playlist->is_public, - 'stats' => [ - 'views' => (int) $playlist->view_count, - 'downloads' => (int) $playlist->download_count, - 'comments' => (int) $playlist->comment_count, - 'favourites' => (int) $playlist->favourite_count - ], - 'covers' => [ - 'small' => $playlist->getCoverUrl(Image::SMALL), - 'normal' => $playlist->getCoverUrl(Image::NORMAL) - ], - 'url' => $playlist->url, - 'user' => [ - 'id' => (int) $playlist->user->id, - 'name' => $playlist->user->display_name, - 'url' => $playlist->user->url, - ], - 'user_data' => $userData, - 'permissions' => [ - 'delete' => Auth::check() && Auth::user()->id == $playlist->user_id, - 'edit' => Auth::check() && Auth::user()->id == $playlist->user_id - ] - ]; - } - - public function tracks() { - return $this - ->belongsToMany('Entities\Track') - ->withPivot('position') - ->withTimestamps() - ->orderBy('position', 'asc'); - } - - public function users() { - return $this->hasMany('Entities\ResourceUser'); - } - - public function comments(){ - return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); - } - - public function pins() { - return $this->hasMany('Entities\PinnedPlaylist'); - } - - public function user() { - return $this->belongsTo('Entities\User'); - } - - public function hasPinFor($userId) { - foreach ($this->pins as $pin) { - if ($pin->user_id == $userId) - return true; - } - - return false; - } - - public function canView($user) { - return $this->is_public || ($user != null && $user->id == $this->user_id); - } - - public function getUrlAttribute() { - 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; - 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) { - if ($this->tracks->count() == 0) - return $this->user->getAvatarUrl($type); - - return $this->tracks[0]->getCoverUrl($type); - } - - public function pin($userId) { - $pin = new PinnedPlaylist(); - $pin->playlist_id = $this->id; - $pin->user_id = $userId; - $pin->save(); - } - - private function getCacheKey($key) { - return 'playlist-' . $this->id . '-' . $key; - } - } diff --git a/app/models/Entities/ProfileRequest.php b/app/models/Entities/ProfileRequest.php deleted file mode 100644 index 7b2e2bfd..00000000 --- a/app/models/Entities/ProfileRequest.php +++ /dev/null @@ -1,65 +0,0 @@ -_data = json_decode($data); - return $req; - } - - public static function create() { - $req = new ProfileRequest(); - $req->_id = uniqid(); - return $req; - } - - private function __construct() { - $this->_data = ['log' => []]; - } - - public function toArray() { - return $this->_data; - } - - public function toString() { - return json_encode($this->_data); - } - - public function getId() { - return $this->_id; - } - - public function after($request, $response) { - $this->_data['queries'] = []; - foreach (DB::getQueryLog() as $query) { - if (starts_with($query['query'], 'select * from `cache` where')) - continue; - - if (starts_with($query['query'], 'delete from `cache` where')) - continue; - - if (starts_with($query['query'], 'insert into `cache`')) - continue; - - $this->_data['queries'][] = $query; - } - } - - public function log($level, $message, $context) { - $this->_data['log'][] = [ - 'level' => $level, - 'message' => $message - ]; - } - } \ No newline at end of file diff --git a/app/models/Entities/ResourceLogItem.php b/app/models/Entities/ResourceLogItem.php deleted file mode 100644 index 9d111a07..00000000 --- a/app/models/Entities/ResourceLogItem.php +++ /dev/null @@ -1,69 +0,0 @@ -{$resourceIdColumn} = $resourceId; - $logItem->created_at = time(); - $logItem->log_type = $logType; - $logItem->track_format_id = $formatId; - $logItem->ip_address = Request::getClientIp(); - - if (Auth::check()) { - $logItem->user_id = Auth::user()->id; - } - - $logItem->save(); - - $resourceTable = $resourceType . 's'; - $countColumn = ''; - - if ($logType == self::VIEW) $countColumn = 'view_count'; - else if ($logType == self::DOWNLOAD) $countColumn = 'download_count'; - else if ($logType == self::PLAY) $countColumn = 'play_count'; - - // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db - // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created - // for the same resource at the same time, the cached values will still be correct with this method. - - DB::table($resourceTable)->whereId($resourceId)->update([$countColumn => - DB::raw('(SELECT - COUNT(id) - FROM - resource_log_items - WHERE ' . - $resourceIdColumn . ' = ' . $resourceId . ' - AND - log_type = ' . $logType . ')')]); - - if (Auth::check()) { - $resourceUserId = ResourceUser::getId(Auth::user()->id, $resourceType, $resourceId); - DB::table('resource_users')->whereId($resourceUserId)->update([$countColumn => - DB::raw('(SELECT - COUNT(id) - FROM - resource_log_items - WHERE - user_id = ' . Auth::user()->id . ' - AND ' . - $resourceIdColumn . ' = ' . $resourceId . ' - AND - log_type = ' . $logType . ')')]); - } - } - } \ No newline at end of file diff --git a/app/models/Entities/ResourceUser.php b/app/models/Entities/ResourceUser.php deleted file mode 100644 index 5cb09d59..00000000 --- a/app/models/Entities/ResourceUser.php +++ /dev/null @@ -1,30 +0,0 @@ -where('user_id', '=', $userId)->first(); - if ($existing) - return $existing; - - $item = new ResourceUser(); - $item->{$resourceIdColumn} = $resourceId; - $item->user_id = $userId; - return $item; - } - - public static function getId($userId, $resourceType, $resourceId) { - $item = self::get($userId, $resourceType, $resourceId); - if ($item->exists) - return $item->id; - - $item->save(); - return $item->id; - } - } \ No newline at end of file diff --git a/app/models/Entities/ShowSong.php b/app/models/Entities/ShowSong.php deleted file mode 100644 index 40a5a9b1..00000000 --- a/app/models/Entities/ShowSong.php +++ /dev/null @@ -1,7 +0,0 @@ - ['index' => 0, 'is_lossless' => true, 'extension' => 'flac', 'tag_format' => 'metaflac', 'tag_method' => 'updateTagsWithGetId3', 'mime_type' => 'audio/flac', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec flac -aq 8 -f flac {$target}'], - 'MP3' => ['index' => 1, 'is_lossless' => false, 'extension' => 'mp3', 'tag_format' => 'id3v2.3', 'tag_method' => 'updateTagsWithGetId3', 'mime_type' => 'audio/mpeg', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libmp3lame -ab 320k -f mp3 {$target}'], - 'OGG Vorbis' => ['index' => 2, 'is_lossless' => false, 'extension' => 'ogg', 'tag_format' => 'vorbiscomment', 'tag_method' => 'updateTagsWithGetId3', 'mime_type' => 'audio/ogg', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libvorbis -aq 7 -f ogg {$target}'], - 'AAC' => ['index' => 3, 'is_lossless' => false, 'extension' => 'm4a', 'tag_format' => 'AtomicParsley', 'tag_method' => 'updateTagsWithAtomicParsley', 'mime_type' => 'audio/mp4', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec libfaac -ab 256k -f mp4 {$target}'], - 'ALAC' => ['index' => 4, 'is_lossless' => true, 'extension' => 'alac.m4a', 'tag_format' => 'AtomicParsley', 'tag_method' => 'updateTagsWithAtomicParsley', 'mime_type' => 'audio/mp4', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec alac {$target}'], - ]; - - public static function summary() { - return self::select('id', 'title', 'user_id', 'slug', 'is_vocal', 'is_explicit', 'created_at', 'published_at', 'duration', 'is_downloadable', 'genre_id', 'track_type_id', 'cover_id', 'album_id', 'comment_count', 'download_count', 'view_count', 'play_count', 'favourite_count'); - } - - public function scopeUserDetails($query) { - if (Auth::check()) { - $query->with(['users' => function($query) { - $query->whereUserId(Auth::user()->id); - }]); - } - } - - public function scopePublished($query) { - $query->whereNotNull('published_at'); - } - - public function scopeListed($query) { - $query->whereIsListed(true); - } - - public function scopeExplicitFilter($query) { - if (!Auth::check() || !Auth::user()->can_see_explicit_content) - $query->whereIsExplicit(false); - } - - public function scopeWithComments($query) { - $query->with(['comments' => function($query) { $query->with('user'); }]); - } - - public static function popular($count, $allowExplicit = false) { - $trackIds = Cache::remember('popular_tracks' . $count . '-' . ($allowExplicit ? 'explicit' : 'safe'), 5, function() use ($allowExplicit, $count) { - $query = static - ::published() - ->listed() - ->join(DB::raw(' - ( SELECT `track_id`, `created_at` - FROM `resource_log_items` - WHERE track_id IS NOT NULL AND log_type = 3 AND `created_at` > now() - INTERVAL 1 DAY - ) AS ranged_plays'), - 'tracks.id', '=', 'ranged_plays.track_id') - ->groupBy('id') - ->orderBy('plays', 'desc') - ->take($count); - - if (!$allowExplicit) - $query->whereIsExplicit(false); - - $results = []; - - foreach($query->get(['*', DB::raw('count(*) as plays')]) as $track) { - $results[] = $track->id; - } - - return $results; - }); - - if (!count($trackIds)) - return []; - - $tracks = Track::summary() - ->userDetails() - ->explicitFilter() - ->published() - ->with('user', 'genre', 'cover', 'album', 'album.user') - ->whereIn('id', $trackIds); - - $processed = []; - foreach ($tracks->get() as $track) - $processed[] = Track::mapPublicTrackSummary($track); - - return $processed; - } - - public static function mapPublicTrackShow($track) { - $returnValue = self::mapPublicTrackSummary($track); - $returnValue['description'] = $track->description; - $returnValue['lyrics'] = $track->lyrics; - - $comments = []; - - foreach ($track->comments as $comment) { - $comments[] = Comment::mapPublic($comment); - } - - $returnValue['comments'] = $comments; - - if ($track->album_id != null) { - $returnValue['album'] = [ - 'title' => $track->album->title, - 'url' => $track->album->url, - ]; - } - - $formats = []; - - foreach ($track->trackFiles as $trackFile) { - $formats[] = [ - 'name' => $trackFile->format, - 'extension' => $trackFile->extension, - 'url' => $trackFile->url, - 'size' => $trackFile->size - ]; - } - - $returnValue['share'] = [ - 'url' => URL::to('/t' . $track->id), - 'html' => '', - 'bbcode' => '[url=' . $track->url . '][img]' . $track->getCoverUrl() . '[/img][/url]', - 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $track->title . ' by ' . $track->user->display_name . ' on Pony.fm' - ]; - - $returnValue['share']['tumblrUrl'] = 'http://www.tumblr.com/share/video?embed=' . urlencode($returnValue['share']['html']) . '&caption=' . urlencode($track->title); - - $returnValue['formats'] = $formats; - - return $returnValue; - } - - public static function mapPublicTrackSummary($track) { - $userData = [ - 'stats' => [ - 'views' => 0, - 'plays' => 0, - 'downloads' => 0 - ], - 'is_favourited' => false - ]; - - if (Auth::check() && $track->users->count()) { - $userRow = $track->users[0]; - $userData = [ - 'stats' => [ - 'views' => (int) $userRow->view_count, - 'plays' => (int) $userRow->play_count, - 'downloads' => $userRow->download_count, - ], - 'is_favourited' => (bool) $userRow->is_favourited - ]; - } - - return [ - 'id' => (int) $track->id, - 'title' => $track->title, - 'user' => [ - 'id' => (int) $track->user->id, - 'name' => $track->user->display_name, - 'url' => $track->user->url - ], - 'stats' => [ - 'views' => (int) $track->view_count, - 'plays' => (int) $track->play_count, - 'downloads' => (int) $track->download_count, - 'comments' => (int) $track->comment_count, - 'favourites' => (int) $track->favourite_count - ], - 'url' => $track->url, - 'slug' => $track->slug, - 'is_vocal' => (bool) $track->is_vocal, - 'is_explicit' => (bool) $track->is_explicit, - 'is_downloadable' => (bool) $track->is_downloadable, - 'is_published' => (bool) $track->isPublished(), - 'published_at' => $track->published_at, - 'duration' => $track->duration, - 'genre' => $track->genre != null - ? - [ - 'id' => (int) $track->genre->id, - 'slug' => $track->genre->slug, - 'name' => $track->genre->name - ] : null, - 'track_type_id' => $track->track_type_id, - 'covers' => [ - 'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL), - 'small' => $track->getCoverUrl(Image::SMALL), - 'normal' => $track->getCoverUrl(Image::NORMAL) - ], - 'streams' => [ - 'mp3' => $track->getStreamUrl('MP3'), - 'aac' => (!Config::get('app.debug') || is_file($track->getFileFor('AAC')) ) ? $track->getStreamUrl('AAC') : null, - 'ogg' => ( Config::get('app.debug') || is_file($track->getFileFor('OGG Vorbis'))) ? $track->getStreamUrl('OGG Vorbis') : null - ], - 'user_data' => $userData, - 'permissions' => [ - 'delete' => Auth::check() && Auth::user()->id == $track->user_id, - 'edit' => Auth::check() && Auth::user()->id == $track->user_id - ] - ]; - } - - public static function mapPrivateTrackShow($track) { - $showSongs = []; - foreach ($track->showSongs as $showSong) { - $showSongs[] = ['id' => $showSong->id, 'title' => $showSong->title]; - } - - $returnValue = self::mapPrivateTrackSummary($track); - $returnValue['album_id'] = $track->album_id; - $returnValue['show_songs'] = $showSongs; - $returnValue['real_cover_url'] = $track->getCoverUrl(Image::NORMAL); - $returnValue['cover_url'] = $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null; - $returnValue['released_at'] = $track->released_at; - $returnValue['lyrics'] = $track->lyrics; - $returnValue['description'] = $track->description; - $returnValue['is_downloadable'] = !$track->isPublished() ? true : (bool)$track->is_downloadable; - $returnValue['license_id'] = $track->license_id != null ? $track->license_id : 3; - return $returnValue; - } - - public static function mapPrivateTrackSummary($track) { - return [ - 'id' => $track->id, - 'title' => $track->title, - 'user_id' => $track->user_id, - 'slug' => $track->slug, - 'is_vocal' => $track->is_vocal, - 'is_explicit' => $track->is_explicit, - 'is_downloadable' => $track->is_downloadable, - 'is_published' => $track->isPublished(), - 'created_at' => $track->created_at, - 'published_at' => $track->published_at, - 'duration' => $track->duration, - 'genre_id' => $track->genre_id, - 'track_type_id' => $track->track_type_id, - 'cover_url' => $track->getCoverUrl(Image::SMALL), - 'is_listed' => !!$track->is_listed - ]; - } - - protected $table = 'tracks'; - - public function genre() { - return $this->belongsTo('Entities\Genre'); - } - - public function trackType() { - return $this->belongsTo('Entities\TrackType', 'track_type_id'); - } - - public function comments(){ - return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); - } - - public function favourites() { - return $this->hasMany('Entities\Favourite'); - } - - public function cover() { - return $this->belongsTo('Entities\Image'); - } - - public function showSongs() { - return $this->belongsToMany('Entities\ShowSong'); - } - - public function users() { - return $this->hasMany('Entities\ResourceUser'); - } - - public function user() { - return $this->belongsTo('Entities\User'); - } - - public function album() { - return $this->belongsTo('Entities\Album'); - } - - public function trackFiles() { - return $this->hasMany('Entities\TrackFile'); - } - - public function getYearAttribute() { - return date('Y', strtotime($this->getReleaseDate())); - } - - public function setTitleAttribute($value) { - $this->setTitleAttributeSlug($value);; - $this->updateHash(); - } - - public function getFilesize($formatName) { - return Cache::remember($this->getCacheKey('filesize-' . $formatName), 1440, function () use ($formatName) { - $file = $this->getFileFor($formatName); - $size = 0; - - if (is_file($file)) - $size = filesize($file); - - return $size; - }); - } - - public function canView($user) { - if ($this->isPublished()) - return true; - - return $this->user_id == $user->id; - } - - public function getUrlAttribute() { - 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->released_at !== NULL) - return $this->released_at; - - if ($this->published_at !== NULL) { - return Str::limit($this->published_at, 10, ''); - } - - return Str::limit($this->attributes['created_at'], 10, ''); - } - - public function ensureDirectoryExists() { - $destination = $this->getDirectory(); - umask(0); - - if (!is_dir($destination)) - mkdir($destination, 0777, true); - } - - public function hasCover() { - return $this->cover_id != null; - } - - public function isPublished() { - return $this->published_at != null && $this->deleted_at == null; - } - - public function getCoverUrl($type = Image::NORMAL) { - if (!$this->hasCover()) { - if ($this->album_id != null) - return $this->album->getCoverUrl($type); - - return $this->user->getAvatarUrl($type); - } - - return $this->cover->getUrl($type); - } - - public function getStreamUrl($format = 'MP3') { - return URL::to('/t' . $this->id . '/stream.' . self::$Formats[$format]['extension']); - } - - public function getDirectory() { - $dir = (string) ( floor( $this->id / 100 ) * 100 ); - return \Config::get('app.files_directory') . '/tracks/' . $dir; - } - - public function getDates() { - return ['created_at', 'deleted_at', 'published_at', 'released_at']; - } - - public function getFilenameFor($format) { - if (!isset(self::$Formats[$format])) - throw new Exception("$format is not a valid format!"); - - $format = self::$Formats[$format]; - return "{$this->id}.{$format['extension']}"; - } - - public function getDownloadFilenameFor($format) { - if (!isset(self::$Formats[$format])) - throw new Exception("$format is not a valid format!"); - - $format = self::$Formats[$format]; - return "{$this->title}.{$format['extension']}"; - } - - public function getFileFor($format) { - if (!isset(self::$Formats[$format])) - throw new Exception("$format is not a valid format!"); - - $format = self::$Formats[$format]; - return "{$this->getDirectory()}/{$this->id}.{$format['extension']}"; - } - - public function getUrlFor($format) { - if (!isset(self::$Formats[$format])) - throw new Exception("$format is not a valid format!"); - - $format = self::$Formats[$format]; - return URL::to('/t' . $this->id . '/dl.' . $format['extension']); - } - - public function updateHash() { - $this->hash = md5(Helpers::sanitizeInputForHashing($this->user->display_name) . ' - ' . Helpers::sanitizeInputForHashing($this->title)); - } - - public function updateTags() { - $this->trackFiles()->touch(); - - foreach ($this->trackFiles as $trackFile) { - $format = $trackFile->format; - $data = self::$Formats[$format]; - - $this->{$data['tag_method']}($format); - } - } - - /** @noinspection PhpUnusedPrivateMethodInspection */ - private function updateTagsWithAtomicParsley($format) { - $command = 'AtomicParsley "' . $this->getFileFor($format) . '" '; - $command .= '--title ' . escapeshellarg($this->title) . ' '; - $command .= '--artist ' . escapeshellarg($this->user->display_name) . ' '; - $command .= '--year "' . $this->year . '" '; - $command .= '--genre ' . escapeshellarg($this->genre != null ? $this->genre->name : '') . ' '; - $command .= '--copyright ' . escapeshellarg('© '.$this->year.' '.$this->user->display_name).' '; - $command .= '--comment "' . 'Downloaded from: https://pony.fm/' . '" '; - $command .= '--encodingTool "' . 'Pony.fm - https://pony.fm/' . '" '; - - if ($this->album_id !== NULL) { - $command .= '--album ' . escapeshellarg($this->album->title) . ' '; - $command .= '--tracknum ' . $this->track_number . ' '; - } - - if ($this->cover !== NULL) { - $command .= '--artwork ' . $this->cover->getFile() . ' '; - } - - $command .= '--overWrite'; - - External::execute($command); - } - - /** @noinspection PhpUnusedPrivateMethodInspection */ - private function updateTagsWithGetId3($format) { - require_once(app_path() . '/library/getid3/getid3/getid3.php'); - require_once(app_path() . '/library/getid3/getid3/write.php'); - $tagWriter = new getid3_writetags; - - $tagWriter->overwrite_tags = true; - $tagWriter->tag_encoding = 'UTF-8'; - $tagWriter->remove_other_tags = true; - - $tagWriter->tag_data = [ - 'title' => [$this->title], - 'artist' => [$this->user->display_name], - 'year' => ['' . $this->year], - 'genre' => [$this->genre != null ? $this->genre->name : ''], - 'comment' => ['Downloaded from: https://pony.fm/'], - 'copyright' => ['© ' . $this->year . ' ' . $this->user->display_name], - 'publisher' => ['Pony.fm - https://pony.fm/'], - 'encoded_by' => ['https://pony.fm/'], -// 'url_artist' => [$this->user->url], -// 'url_source' => [$this->url], -// 'url_file' => [$this->url], - 'url_publisher' => ['https://pony.fm/'] - ]; - - if ($this->album_id !== NULL) { - $tagWriter->tag_data['album'] = [$this->album->title]; - $tagWriter->tag_data['track'] = [$this->track_number]; - } - - if ($format == 'MP3' && $this->cover_id != NULL && is_file($this->cover->getFile())) { - $tagWriter->tag_data['attached_picture'][0] = [ - 'data' => file_get_contents($this->cover->getFile()), - 'picturetypeid' => 2, - 'description' => 'cover', - 'mime' => 'image/png' - ]; - } - - $tagWriter->filename = $this->getFileFor($format); - $tagWriter->tagformats = [self::$Formats[$format]['tag_format']]; - - if ($tagWriter->WriteTags()) { - if (!empty($tagWriter->warnings)) { - Log::warning('Track #'.$this->id.': There were some warnings:
' . implode('

', $tagWriter->warnings)); - } - } else { - Log::error('Track #' . $this->id . ': Failed to write tags!
' . implode('

', $tagWriter->errors)); - } - } - - private function getCacheKey($key) { - return 'track-' . $this->id . '-' . $key; - } - } diff --git a/app/models/Entities/TrackFile.php b/app/models/Entities/TrackFile.php deleted file mode 100644 index a84dc40f..00000000 --- a/app/models/Entities/TrackFile.php +++ /dev/null @@ -1,103 +0,0 @@ -belongsTo('Entities\Track'); - } - - /** - * Look up and return a TrackFile by track ID and an extension. - * - * If the track does not have a TrackFile in the given extension's format, a 404 exception is thrown. - * - * @param int $trackId - * @param string $extension - * @return TrackFile - */ - public static function findOrFailByExtension($trackId, $extension) { - // find the extension's format - $requestedFormatName = null; - foreach (Track::$Formats as $name => $format) { - if ($extension === $format[ 'extension' ]) { - $requestedFormatName = $name; - break; - } - } - if ($requestedFormatName === null) { - App::abort(404); - } - - $trackFile = static:: - with('track') - ->where('track_id', $trackId) - ->where('format', $requestedFormatName) - ->first(); - - if ($trackFile === null) { - App::abort(404); - } else { - return $trackFile; - } - } - - public function getFormatAttribute($value) { - return $value; - } - - public function getExtensionAttribute() { - return Track::$Formats[$this->format]['extension']; - } - - public function getUrlAttribute() { - return URL::to('/t' . $this->track_id . '/dl.' . $this->extension); - } - - public function getSizeAttribute($value) { - return Helpers::formatBytes($this->getFilesize($this->getFile())); - } - - public function getFormat() { - return Track::$Formats[$this->format]; - } - - protected function getFilesize() { - return Cache::remember($this->getCacheKey('filesize'), 1440, function () { - $file = $this->getFile(); - $size = 0; - - if (is_file($file)) { - $size = filesize($file); - } - - return $size; - }); - } - - public function getDirectory() { - $dir = (string) (floor($this->track_id / 100) * 100); - return \Config::get('app.files_directory') . '/tracks/' . $dir; - } - - public function getFile() { - return "{$this->getDirectory()}/{$this->track_id}.{$this->extension}"; - } - - public function getFilename() { - return "{$this->track_id}.{$this->extension}"; - } - - public function getDownloadFilename() { - return "{$this->track->title}.{$this->extension}"; - } - - private function getCacheKey($key) { - return 'track_file-' . $this->id . '-' . $key; - } -} \ No newline at end of file diff --git a/app/models/Entities/TrackType.php b/app/models/Entities/TrackType.php deleted file mode 100644 index 43ea73ea..00000000 --- a/app/models/Entities/TrackType.php +++ /dev/null @@ -1,13 +0,0 @@ -with(['users' => function($query) { - $query->whereUserId(Auth::user()->id); - }]); - } - - return !$query; - } - - public function avatar() { - return $this->belongsTo('Entities\Image'); - } - - public function users() { - return $this->hasMany('Entities\ResourceUser', 'artist_id'); - } - - public function comments() { - return $this->hasMany('Entities\Comment', 'profile_id')->orderBy('created_at', 'desc'); - } - - public function getIsArchivedAttribute() { - return (bool) $this->attributes['is_archived']; - } - - public function getUrlAttribute() { - return URL::to('/' . $this->slug); - } - - public function getMessageUrlAttribute() { - return 'http://mlpforums.com/index.php?app=members&module=messaging§ion=send&do=form&fromMemberID='.$this->id; - } - - public function getAuthIdentifier() { - return $this->getKey(); - } - - public function getAuthPassword() { - return $this->password_hash; - } - - public function getReminderEmail() { - return $this->email; - } - - public function setDisplayNameAttribute($value) { - $this->attributes['display_name'] = $value; - $this->attributes['slug'] = Str::slug($value); - } - - public function getAvatarUrl($type = Image::NORMAL) { - if (!$this->uses_gravatar) - return $this->avatar->getUrl($type); - - if ($this->email == "redacted@example.net") { - return Gravatar::getUrl($this->id . "", Image::$ImageTypes[$type]['width'], "identicon"); - } - - $email = $this->gravatar; - - if (!strlen($email)) { - $email = $this->email; - } - - return Gravatar::getUrl($email, Image::$ImageTypes[$type]['width']); - } - - public function getAvatarFile($type = Image::NORMAL) { - if ($this->uses_gravatar) - throw new Exception('Cannot get avatar file if this user is configured to use Gravatar!'); - - $imageType = Image::$ImageTypes[$type]; - return URL::to('t' . $this->id . '/cover_' . $imageType['name'] . '.png?' . $this->cover_id); - } - - /** - * Get the token value for the "remember me" session. - * - * @return string - */ - public function getRememberToken() { - return $this->remember_token; - } - - /** - * Set the token value for the "remember me" session. - * - * @param string $value - * @return void - */ - public function setRememberToken($value) { - $this->remember_token = $value; - } - - /** - * Get the column name for the "remember me" token. - * - * @return string - */ - public function getRememberTokenName() { - return "remember_token"; - } - } \ No newline at end of file diff --git a/app/models/PlaylistDownloader.php b/app/models/PlaylistDownloader.php deleted file mode 100644 index 56357372..00000000 --- a/app/models/PlaylistDownloader.php +++ /dev/null @@ -1,56 +0,0 @@ -_playlist = $playlist; - $this->_format = $format; - } - - function download() { - $zip = new ZipStream($this->_playlist->user->display_name . ' - ' . $this->_playlist->title . '.zip'); - $zip->setComment( - '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') . '.' - ); - - $notes = - '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". - "\r\n". - "\r\n". - 'Tracks' ."\r\n". - "\r\n"; - - $m3u = ''; - $index = 1; - foreach ($this->_playlist->tracks as $track) { - if (!$track->is_downloadable) - continue; - - $trackTarget = $track->downloadDirectory . '/' . $track->getDownloadFilenameFor($this->_format); - $zip->addLargeFile($track->getFileFor($this->_format), $trackTarget); - $notes .= - $index . '. ' . $track->title ."\r\n". - $track->description ."\r\n". - "\r\n"; - - $m3u .= '#EXTINF:' . $track->duration . ',' . $track->title . "\r\n"; - $m3u .= '../' . $trackTarget . "\r\n"; - - $index++; - } - - $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/models/Traits/SlugTrait.php b/app/models/Traits/SlugTrait.php deleted file mode 100644 index 20e86b0e..00000000 --- a/app/models/Traits/SlugTrait.php +++ /dev/null @@ -1,12 +0,0 @@ -slug = Str::slug($value); - $this->attributes['title'] = $value; - } - } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php deleted file mode 100644 index 8c909459..00000000 --- a/app/routes.php +++ /dev/null @@ -1,161 +0,0 @@ -where('id', '\d+'); - Route::get('a{id}/dl.{extension}', 'AlbumsController@getDownload' ); - - Route::get('artists', 'ArtistsController@getIndex'); - Route::get('playlists', 'PlaylistsController@getIndex'); - - Route::get('/register', 'AccountController@getRegister'); - Route::get('/login', 'AuthController@getLogin'); - Route::get('/auth/oauth', 'AuthController@getOAuth'); - - Route::get('/about', function() { return View::make('pages.about'); }); - Route::get('/faq', function() { return View::make('pages.faq'); }); - - Route::get('i{id}/{type}.png', 'ImagesController@getImage')->where('id', '\d+'); - - Route::get('u{id}/avatar_{type}.png', 'UsersController@getAvatar')->where('id', '\d+'); - - 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/v1'], function() { - Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); - Route::post('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); - }); - - Route::group(['prefix' => 'api/web'], function() { - Route::get('/taxonomies/all', 'Api\Web\TaxonomiesController@getAll'); - - Route::get('/playlists/show/{id}', 'Api\Web\PlaylistsController@getShow'); - - Route::get('/tracks', 'Api\Web\TracksController@getIndex'); - Route::get('/tracks/{id}', 'Api\Web\TracksController@getShow')->where('id', '\d+'); - - Route::get('/albums', 'Api\Web\AlbumsController@getIndex'); - Route::get('/albums/{id}', 'Api\Web\AlbumsController@getShow')->where('id', '\d+'); - - Route::get('/playlists', 'Api\Web\PlaylistsController@getIndex'); - Route::get('/playlists/{id}', 'Api\Web\PlaylistsController@getShow')->where('id', '\d+'); - - Route::get('/comments/{type}/{id}', 'Api\Web\CommentsController@getIndex')->where('id', '\d+'); - - Route::get('/artists', 'Api\Web\ArtistsController@getIndex'); - Route::get('/artists/{slug}', 'Api\Web\ArtistsController@getShow'); - Route::get('/artists/{slug}/content', 'Api\Web\ArtistsController@getContent'); - Route::get('/artists/{slug}/favourites', 'Api\Web\ArtistsController@getFavourites'); - - Route::get('/dashboard', 'Api\Web\DashboardController@getIndex'); - - Route::group(['before' => 'auth|csrf'], function() { - Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload'); - Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete'); - Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@postEdit'); - - Route::post('/albums/create', 'Api\Web\AlbumsController@postCreate'); - Route::post('/albums/delete/{id}', 'Api\Web\AlbumsController@postDelete'); - Route::post('/albums/edit/{id}', 'Api\Web\AlbumsController@postEdit'); - - Route::post('/playlists/create', 'Api\Web\PlaylistsController@postCreate'); - Route::post('/playlists/delete/{id}', 'Api\Web\PlaylistsController@postDelete'); - Route::post('/playlists/edit/{id}', 'Api\Web\PlaylistsController@postEdit'); - Route::post('/playlists/{id}/add-track', 'Api\Web\PlaylistsController@postAddTrack'); - - Route::post('/comments/{type}/{id}', 'Api\Web\CommentsController@postCreate')->where('id', '\d+'); - - Route::post('/account/settings/save', 'Api\Web\AccountController@postSave'); - - Route::post('/favourites/toggle', 'Api\Web\FavouritesController@postToggle'); - - Route::post('/follow/toggle', 'Api\Web\FollowController@postToggle'); - - Route::post('/dashboard/read-news', 'Api\Web\DashboardController@postReadNews'); - }); - - Route::group(['before' => 'auth'], function() { - Route::get('/account/settings', 'Api\Web\AccountController@getSettings'); - - Route::get('/images/owned', 'Api\Web\ImagesController@getOwned'); - - Route::get('/tracks/owned', 'Api\Web\TracksController@getOwned'); - Route::get('/tracks/edit/{id}', 'Api\Web\TracksController@getEdit'); - - Route::get('/albums/owned', 'Api\Web\AlbumsController@getOwned'); - Route::get('/albums/edit/{id}', 'Api\Web\AlbumsController@getEdit'); - - Route::get('/playlists/owned', 'Api\Web\PlaylistsController@getOwned'); - Route::get('/playlists/pinned', 'Api\Web\PlaylistsController@getPinned'); - - Route::get('/favourites/tracks', 'Api\Web\FavouritesController@getTracks'); - Route::get('/favourites/albums', 'Api\Web\FavouritesController@getAlbums'); - Route::get('/favourites/playlists', 'Api\Web\FavouritesController@getPlaylists'); - }); - - Route::group(['before' => 'csrf'], function(){ - Route::post('/auth/logout', 'Api\Web\AuthController@postLogout'); - }); - }); - - Route::group(['prefix' => 'account'], function() { - Route::group(['before' => 'auth'], function(){ - Route::get('/favourites/tracks', 'FavouritesController@getTracks'); - Route::get('/favourites/albums', 'FavouritesController@getAlbums'); - Route::get('/favourites/playlists', 'FavouritesController@getPlaylists'); - - Route::get('/tracks', 'ContentController@getTracks'); - Route::get('/tracks/edit/{id}', 'ContentController@getTracks'); - Route::get('/albums', 'ContentController@getAlbums'); - Route::get('/albums/edit/{id}', 'ContentController@getAlbums'); - Route::get('/albums/create', 'ContentController@getAlbums'); - Route::get('/playlists', 'ContentController@getPlaylists'); - - Route::get('/uploader', 'UploaderController@getIndex'); - - Route::get('/', 'AccountController@getIndex'); - }); - }); - - Route::get('u{id}', 'ArtistsController@getShortlink')->where('id', '\d+'); - Route::get('users/{id}-{slug}', 'ArtistsController@getShortlink')->where('id', '\d+'); - Route::get('{slug}', 'ArtistsController@getProfile'); - Route::get('{slug}/content', 'ArtistsController@getProfile'); - Route::get('{slug}/favourites', 'ArtistsController@getProfile'); - - Route::get('/', 'HomeController@getIndex'); - -Route::group(['domain' => 'api.pony.fm'], function() { - Route::get('tracks/latest', ['uses' => 'Api\Mobile\TracksController@latest']); - Route::get('tracks/popular', [ 'uses' => 'Api\Mobile\TracksController@popular']); -/* Route::get('tracks/id', [ 'uses' => 'Api\Mobile\TracksController@track']); - Route::get('user', ['uses' => 'Api\Mobile\UserController@user']);*/ -}); \ No newline at end of file diff --git a/app/start/artisan.php b/app/start/artisan.php deleted file mode 100644 index 89fb4519..00000000 --- a/app/start/artisan.php +++ /dev/null @@ -1,18 +0,0 @@ -client->request('GET', '/'); - - $this->assertTrue($this->client->getResponse()->isOk()); - - $this->assertCount(1, $crawler->filter('h1:contains("Hello World!")')); - } - -} \ No newline at end of file diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php deleted file mode 100644 index 49b80fc2..00000000 --- a/app/tests/TestCase.php +++ /dev/null @@ -1,19 +0,0 @@ -boot(); - -/* -|-------------------------------------------------------------------------- -| Load The Artisan Console Application -|-------------------------------------------------------------------------- -| -| We'll need to run the script to load and return the Artisan console -| application. We keep this in its own script so that we will load -| the console application independent of running commands which -| will allow us to fire commands from Routes when we want to. -| -*/ - -$artisan = Illuminate\Console\Application::start($app); +$app = require_once __DIR__.'/bootstrap/app.php'; /* |-------------------------------------------------------------------------- @@ -56,7 +28,12 @@ $artisan = Illuminate\Console\Application::start($app); | */ -$status = $artisan->run(); +$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); /* |-------------------------------------------------------------------------- @@ -69,6 +46,6 @@ $status = $artisan->run(); | */ -$app->shutdown(); +$kernel->terminate($input, $status); -exit($status); \ No newline at end of file +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 00000000..f2801adf --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + App\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + App\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + App\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php index 6b329312..38301379 100644 --- a/bootstrap/autoload.php +++ b/bootstrap/autoload.php @@ -27,49 +27,8 @@ require __DIR__.'/../vendor/autoload.php'; | */ -if (file_exists($compiled = __DIR__.'/compiled.php')) -{ - require $compiled; -} - -/* -|-------------------------------------------------------------------------- -| Setup Patchwork UTF-8 Handling -|-------------------------------------------------------------------------- -| -| The Patchwork library provides solid handling of UTF-8 strings as well -| as provides replacements for all mb_* and iconv type functions that -| are not available by default in PHP. We'll setup this stuff here. -| -*/ - -Patchwork\Utf8\Bootup::initMbstring(); - -/* -|-------------------------------------------------------------------------- -| Register The Laravel Auto Loader -|-------------------------------------------------------------------------- -| -| We register an auto-loader "behind" the Composer loader that can load -| model classes on the fly, even if the autoload files have not been -| regenerated for the application. We'll add it to the stack here. -| -*/ - -Illuminate\Support\ClassLoader::register(); - -/* -|-------------------------------------------------------------------------- -| Register The Workbench Loaders -|-------------------------------------------------------------------------- -| -| The Laravel workbench provides a convenient place to develop packages -| when working locally. However we will need to load in the Composer -| auto-load files for the packages so that these can be used here. -| -*/ - -if (is_dir($workbench = __DIR__.'/../workbench')) -{ - Illuminate\Workbench\Starter::start($workbench); +$compiledPath = __DIR__.'/cache/compiled.php'; + +if (file_exists($compiledPath)) { + require $compiledPath; } diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bootstrap/paths.php b/bootstrap/paths.php deleted file mode 100644 index 5a1f640b..00000000 --- a/bootstrap/paths.php +++ /dev/null @@ -1,57 +0,0 @@ - __DIR__.'/../app', - - /* - |-------------------------------------------------------------------------- - | Public Path - |-------------------------------------------------------------------------- - | - | The public path contains the assets for your web application, such as - | your JavaScript and CSS files, and also contains the primary entry - | point for web requests into these applications from the outside. - | - */ - - 'public' => __DIR__.'/../public', - - /* - |-------------------------------------------------------------------------- - | Base Path - |-------------------------------------------------------------------------- - | - | The base path is the root of the Laravel installation. Most likely you - | will not need to change this value. But, if for some wild reason it - | is necessary you will do so here, just proceed with some caution. - | - */ - - 'base' => __DIR__.'/..', - - /* - |-------------------------------------------------------------------------- - | Storage Path - |-------------------------------------------------------------------------- - | - | The storage path is used by Laravel to store cached Blade views, logs - | and other pieces of information. You may modify the path here when - | you want to change the location of this directory for your apps. - | - */ - - 'storage' => __DIR__.'/../app/storage', - -); diff --git a/bootstrap/start.php b/bootstrap/start.php deleted file mode 100644 index 6e446200..00000000 --- a/bootstrap/start.php +++ /dev/null @@ -1,73 +0,0 @@ -redirectIfTrailingSlash(); - -/* -|-------------------------------------------------------------------------- -| Detect The Application Environment -|-------------------------------------------------------------------------- -| -| Laravel takes a dead simple approach to your application environments -| so you can just specify a machine name or HTTP host that matches a -| given environment, then we will automatically detect it for you. -| -*/ - -$env = $app->detectEnvironment([ - 'local' => ['pony.fm.local', 'api.pony.fm.local', 'homestead'], - 'stage' => ['stage.pony.fm'], -]); - -/* -|-------------------------------------------------------------------------- -| Bind Paths -|-------------------------------------------------------------------------- -| -| Here we are binding the paths configured in paths.php to the app. You -| should not be changing these here. If you need to change these you -| may do so within the paths.php file and they will be bound here. -| -*/ - -$app->bindInstallPaths(require __DIR__.'/paths.php'); - -/* -|-------------------------------------------------------------------------- -| Load The Application -|-------------------------------------------------------------------------- -| -| Here we will load the Illuminate application. We'll keep this is in a -| separate location so we can isolate the creation of an application -| from the actual running of the application with a given request. -| -*/ - -$framework = $app['path.base'].'/vendor/laravel/framework/src'; - -require $framework.'/Illuminate/Foundation/start.php'; - -/* -|-------------------------------------------------------------------------- -| Return The Application -|-------------------------------------------------------------------------- -| -| This script returns the application instance. The instance is given to -| the calling script so we can separate the building of the instances -| from the actual running of the application and sending responses. -| -*/ - -return $app; diff --git a/composer.json b/composer.json index 40a56aa0..a5146fc5 100644 --- a/composer.json +++ b/composer.json @@ -1,35 +1,59 @@ { - "require": { - "laravel/framework": "4.0.*", - "kriswallsmith/assetic": "1.2.*@dev", - "codescale/ffmpeg-php": "2.7.0", - "simplepie/simplepie": "1.3.1", - "intouch/laravel-newrelic": "*", - "barryvdh/laravel-ide-helper": "~1.11" - }, - "autoload": { - "classmap": [ - "app/commands", - "app/controllers", - "app/models", - "app/database/migrations", - "app/database/seeds", - "app/tests/TestCase.php" - ] - }, - "scripts": { - "pre-update-cmd": [ - "php artisan clear-compiled" - ], - "post-install-cmd": [ - "php artisan optimize" - ], - "post-update-cmd": [ - "php artisan optimize" - ] - }, - "config": { - "preferred-install": "dist" - }, - "minimum-stability": "stable" + "name": "laravel/laravel", + "description": "The Laravel Framework.", + "keywords": ["framework", "laravel"], + "license": "MIT", + "type": "project", + "require": { + "php": ">=5.5.9", + "laravel/framework": "5.1.*", + "codescale/ffmpeg-php": "2.7.0", + "kriswallsmith/assetic": "1.2.*@dev", + "simplepie/simplepie": "1.3.1", + "intouch/laravel-newrelic": "*", + "barryvdh/laravel-ide-helper": "^2.1" + }, + "require-dev": { + "fzaninotto/faker": "~1.4", + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "~4.0", + "phpspec/phpspec": "~2.1" + }, + "autoload": { + "classmap": [ + "database", + "app/Library" + ], + "psr-4": { + "App\\": "app/" + } + }, + "autoload-dev": { + "classmap": [ + "tests/TestCase.php" + ] + }, + "scripts": { + "post-install-cmd": [ + "php artisan clear-compiled", + "php artisan optimize" + ], + "pre-update-cmd": [ + "php artisan clear-compiled" + ], + "post-update-cmd": [ + "php artisan clear-compiled", + "php artisan ide-helper:generate", + "php artisan optimize" + ], + "post-root-package-install": [ + "php -r \"copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "php artisan key:generate" + ] + }, + "config": { + "preferred-install": "dist" + } } diff --git a/composer.lock b/composer.lock index 7aaa227e..12939c00 100644 --- a/composer.lock +++ b/composer.lock @@ -4,28 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "17bad0024ab9a28b45e81c3a7f19ec06", + "hash": "d034b42b177f410db0ab3fc82a278346", "packages": [ { "name": "barryvdh/laravel-ide-helper", - "version": "v1.11.6", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "692b223e94139428427ab2b4d2370b8bc6b2fdbe" + "reference": "83999f8467374adcb8893f566c9171c9d9691f50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/692b223e94139428427ab2b4d2370b8bc6b2fdbe", - "reference": "692b223e94139428427ab2b4d2370b8bc6b2fdbe", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/83999f8467374adcb8893f566c9171c9d9691f50", + "reference": "83999f8467374adcb8893f566c9171c9d9691f50", "shasum": "" }, "require": { - "illuminate/console": "4.x", - "illuminate/filesystem": "4.x", - "illuminate/support": "4.x", - "php": ">=5.3.0", - "phpdocumentor/reflection-docblock": "2.0.x", + "illuminate/console": "5.0.x|5.1.x", + "illuminate/filesystem": "5.0.x|5.1.x", + "illuminate/support": "5.0.x|5.1.x", + "php": ">=5.4.0", + "phpdocumentor/reflection-docblock": "2.0.4", "symfony/class-loader": "~2.3" }, "require-dev": { @@ -37,7 +37,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -67,54 +67,61 @@ "phpstorm", "sublime" ], - "time": "2015-03-16 17:22:03" + "time": "2015-08-13 11:40:00" }, { "name": "classpreloader/classpreloader", - "version": "1.0.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/ClassPreloader/ClassPreloader.git", - "reference": "2c9f3bcbab329570c57339895bd11b5dd3b00877" + "reference": "8c3c14b10309e3b40bce833913a6c0c0b8c8f962" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/2c9f3bcbab329570c57339895bd11b5dd3b00877", - "reference": "2c9f3bcbab329570c57339895bd11b5dd3b00877", + "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/8c3c14b10309e3b40bce833913a6c0c0b8c8f962", + "reference": "8c3c14b10309e3b40bce833913a6c0c0b8c8f962", "shasum": "" }, "require": { - "nikic/php-parser": "~0.9", - "php": ">=5.3.3", - "symfony/console": "~2.1", - "symfony/filesystem": "~2.1", - "symfony/finder": "~2.1" + "nikic/php-parser": "~1.3", + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" }, - "bin": [ - "classpreloader.php" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "psr-0": { - "ClassPreloader": "src/" + "psr-4": { + "ClassPreloader\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com" + } + ], "description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case", "keywords": [ "autoload", "class", "preload" ], - "time": "2014-03-12 00:05:31" + "time": "2015-06-28 21:39:13" }, { "name": "codescale/ffmpeg-php", @@ -161,173 +168,34 @@ "time": "2013-05-05 09:10:04" }, { - "name": "doctrine/annotations", - "version": "v1.2.4", + "name": "danielstjules/stringy", + "version": "1.10.0", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e" + "url": "https://github.com/danielstjules/Stringy.git", + "reference": "4749c205db47ee5b32e8d1adf6d9aff8db6caf3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/b5202eb9e83f8db52e0e58867e0a46e63be8332e", - "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e", + "url": "https://api.github.com/repos/danielstjules/Stringy/zipball/4749c205db47ee5b32e8d1adf6d9aff8db6caf3b", + "reference": "4749c205db47ee5b32e8d1adf6d9aff8db6caf3b", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": ">=5.3.2" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "4.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Annotations\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2014-12-23 22:40:37" - }, - { - "name": "doctrine/cache", - "version": "v1.4.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/c9eadeb743ac6199f7eec423cb9426bc518b7b03", - "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": ">=3.7", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Cache\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2015-04-15 00:11:59" - }, - { - "name": "doctrine/collections", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a", - "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" + "ext-mbstring": "*", + "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } + "psr-4": { + "Stringy\\": "src/" + }, + "files": [ + "src/Create.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -335,170 +203,58 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Daniel St. Jules", + "email": "danielst.jules@gmail.com", + "homepage": "http://www.danielstjules.com" } ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", + "description": "A string manipulation library with multibyte support", + "homepage": "https://github.com/danielstjules/Stringy", "keywords": [ - "array", - "collections", - "iterator" + "UTF", + "helpers", + "manipulation", + "methods", + "multibyte", + "string", + "utf-8", + "utility", + "utils" ], - "time": "2015-04-14 22:21:58" + "time": "2015-07-23 00:54:12" }, { - "name": "doctrine/common", - "version": "v2.5.0", + "name": "dnoegel/php-xdg-base-dir", + "version": "0.1", "source": { "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3" + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/cd8daf2501e10c63dced7b8b9b905844316ae9d3", - "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/265b8593498b997dc2d31e75b89f053b5cc9621a", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a", "shasum": "" }, "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "~3.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6.x-dev" - } + "phpunit/phpunit": "@stable" }, + "type": "project", "autoload": { - "psr-0": { - "Doctrine\\Common\\": "lib/" + "psr-4": { + "XdgBaseDir\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "collections", - "eventmanager", - "persistence", - "spl" - ], - "time": "2015-04-02 19:55:44" - }, - { - "name": "doctrine/dbal", - "version": "v2.4.4", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/a370e5b95e509a7809d11f3d280acfc9310d464b", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b", - "shasum": "" - }, - "require": { - "doctrine/common": "~2.4", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*", - "symfony/console": "~2.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "type": "library", - "autoload": { - "psr-0": { - "Doctrine\\DBAL\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Database Abstraction Layer", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "persistence", - "queryobject" - ], - "time": "2015-01-12 21:57:01" + "description": "implementation of xdg base directory specification for php", + "time": "2014-10-24 07:27:01" }, { "name": "doctrine/inflector", @@ -567,205 +323,24 @@ ], "time": "2014-12-20 21:24:13" }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09 13:34:57" - }, - { - "name": "efficiently/authority-controller", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/efficiently/authority-controller.git", - "reference": "5434a144e72ee2c22ba317d3e833e4b61374be40" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/efficiently/authority-controller/zipball/5434a144e72ee2c22ba317d3e833e4b61374be40", - "reference": "5434a144e72ee2c22ba317d3e833e4b61374be40", - "shasum": "" - }, - "require": { - "machuga/authority-l4": "2.2.*", - "php": ">=5.4.0" - }, - "require-dev": { - "mockery/mockery": "0.9.*", - "orchestra/testbench": "2.2.*", - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.0": "1.0.x-dev", - "dev-1.1": "1.1.x-dev", - "dev-1.2": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "tests/AcTestCase.php", - "tests/helpers", - "tests/fixtures/", - "tests/fixtures/models", - "tests/fixtures/controllers" - ], - "files": [ - "src/Efficiently/AuthorityController/helpers.php" - ], - "psr-0": { - "Efficiently\\AuthorityController": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "TortueTorche", - "email": "tortuetorche@spam.me" - } - ], - "description": "AuthorityController is an PHP authorization library for Laravel 4 which restricts what resources a given user is allowed to access.", - "keywords": [ - "Authentication", - "ability", - "acl", - "allow", - "authority", - "authorization", - "can", - "cancan", - "deny", - "laravel", - "permission", - "rails", - "rbac", - "role", - "security" - ], - "time": "2014-12-18 15:39:34" - }, - { - "name": "filp/whoops", - "version": "1.0.7", - "source": { - "type": "git", - "url": "https://github.com/filp/whoops.git", - "reference": "12e144c788b275e5869ac15eda7bd0ae5da775bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/12e144c788b275e5869ac15eda7bd0ae5da775bd", - "reference": "12e144c788b275e5869ac15eda7bd0ae5da775bd", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "mockery/mockery": "dev-master", - "silex/silex": "1.0.*@dev" - }, - "type": "library", - "autoload": { - "psr-0": { - "Whoops": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Filipe Dobreira", - "homepage": "https://github.com/filp", - "role": "Developer" - } - ], - "description": "php error handling for cool kids", - "homepage": "https://github.com/filp/whoops", - "keywords": [ - "error", - "exception", - "handling", - "library", - "silex-provider", - "whoops", - "zf2" - ], - "time": "2013-06-10 12:22:13" - }, { "name": "intouch/laravel-newrelic", - "version": "1.1.6", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/In-Touch/laravel-newrelic.git", - "reference": "af02c5300a38999e54dc831ff3db528659665677" + "reference": "7213ce8478a309c31489f9b0872e4511166dbe80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/In-Touch/laravel-newrelic/zipball/af02c5300a38999e54dc831ff3db528659665677", - "reference": "af02c5300a38999e54dc831ff3db528659665677", + "url": "https://api.github.com/repos/In-Touch/laravel-newrelic/zipball/7213ce8478a309c31489f9b0872e4511166dbe80", + "reference": "7213ce8478a309c31489f9b0872e4511166dbe80", "shasum": "" }, "require": { - "illuminate/support": "4.*", + "illuminate/support": "5.*", "intouch/newrelic": ">=1.0.2", - "php": ">=5.3.0" + "php": ">=5.4.0" }, "type": "library", "autoload": { @@ -783,14 +358,14 @@ "email": "pleckey@intouchinsight.com" } ], - "description": "Laravel 4 NewRelic Integration", + "description": "Laravel 5 NewRelic Integration", "homepage": "https://github.com/In-Touch/laravel-newrelic", "keywords": [ "laravel", "new relic", "newrelic" ], - "time": "2015-04-24 02:12:14" + "time": "2015-03-11 18:34:13" }, { "name": "intouch/newrelic", @@ -834,72 +409,77 @@ "time": "2014-08-18 12:08:45" }, { - "name": "ircmaxell/password-compat", - "version": "v1.0.4", + "name": "jakub-onderka/php-console-color", + "version": "0.1", "source": { "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "4.*" - }, - "type": "library", - "autoload": { - "files": [ - "lib/password.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" - } - ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", - "keywords": [ - "hashing", - "password" - ], - "time": "2014-11-20 16:49:30" - }, - { - "name": "jeremeamia/SuperClosure", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/jeremeamia/super_closure.git", - "reference": "4d89ca74994feab128ea46d5b3add92e6cb84554" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/4d89ca74994feab128ea46d5b3add92e6cb84554", - "reference": "4d89ca74994feab128ea46d5b3add92e6cb84554", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", "shasum": "" }, "require": { - "nikic/php-parser": "~0.9", - "php": ">=5.3.3" + "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "~3.7" + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" }, "type": "library", "autoload": { "psr-0": { - "Jeremeamia\\SuperClosure": "src/" + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ], + "time": "2014-04-08 15:00:19" + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -908,33 +488,83 @@ ], "authors": [ { - "name": "Jeremy Lindblom" + "name": "Jakub Onderka", + "email": "acci@acci.cz", + "homepage": "http://www.acci.cz/" } ], - "description": "Doing interesting things with closures like serialization.", + "time": "2015-04-20 18:58:01" + }, + { + "name": "jeremeamia/SuperClosure", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/jeremeamia/super_closure.git", + "reference": "b712f39c671e5ead60c7ebfe662545456aade833" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/b712f39c671e5ead60c7ebfe662545456aade833", + "reference": "b712f39c671e5ead60c7ebfe662545456aade833", + "shasum": "" + }, + "require": { + "nikic/php-parser": "~1.0", + "php": ">=5.4" + }, + "require-dev": { + "codeclimate/php-test-reporter": "~0.1.2", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "SuperClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia", + "role": "Developer" + } + ], + "description": "Serialize Closure objects, including their context and binding", "homepage": "https://github.com/jeremeamia/super_closure", "keywords": [ "closure", "function", + "lambda", "parser", "serializable", "serialize", "tokenizer" ], - "time": "2015-01-10 01:09:28" + "time": "2015-03-11 20:06:43" }, { "name": "kriswallsmith/assetic", - "version": "dev-master", + "version": "1.2.x-dev", "source": { "type": "git", "url": "https://github.com/kriswallsmith/assetic.git", - "reference": "5bea57990f7ddbeb3d57e7ef96eae9ddd56c4297" + "reference": "182bfb92b61df601b6eb5676bcb3c91eb5fad57a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/5bea57990f7ddbeb3d57e7ef96eae9ddd56c4297", - "reference": "5bea57990f7ddbeb3d57e7ef96eae9ddd56c4297", + "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/182bfb92b61df601b6eb5676bcb3c91eb5fad57a", + "reference": "182bfb92b61df601b6eb5676bcb3c91eb5fad57a", "shasum": "" }, "require": { @@ -949,8 +579,8 @@ "leafo/scssphp": "*", "leafo/scssphp-compass": "*", "mrclay/minify": "*", - "patchwork/jsqueeze": "*", - "phpunit/phpunit": "~3.7", + "patchwork/jsqueeze": "~1.0", + "phpunit/phpunit": "~4", "psr/log": "~1.0", "ptachoire/cssembed": "*", "twig/twig": "~1.6" @@ -995,53 +625,58 @@ "compression", "minification" ], - "time": "2014-07-08 11:30:40" + "time": "2015-08-05 10:14:34" }, { "name": "laravel/framework", - "version": "v4.0.11", + "version": "v5.1.16", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "7be5f82453edb3db13c8b85d1769481200123f1e" + "reference": "e34dcc0c57e0f560248aec5128161256ff8bf4e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/7be5f82453edb3db13c8b85d1769481200123f1e", - "reference": "7be5f82453edb3db13c8b85d1769481200123f1e", + "url": "https://api.github.com/repos/laravel/framework/zipball/e34dcc0c57e0f560248aec5128161256ff8bf4e1", + "reference": "e34dcc0c57e0f560248aec5128161256ff8bf4e1", "shasum": "" }, "require": { - "classpreloader/classpreloader": "1.0.*", - "doctrine/dbal": "2.4.*", - "filp/whoops": "1.0.7", - "ircmaxell/password-compat": "1.0.*", - "jeremeamia/superclosure": "1.0.*", - "monolog/monolog": "1.*", - "nesbot/carbon": "1.*", - "patchwork/utf8": "1.1.*", - "php": ">=5.3.0", - "predis/predis": "0.8.*", - "swiftmailer/swiftmailer": "5.0.*", - "symfony/browser-kit": "2.3.*", - "symfony/console": "2.3.*", - "symfony/css-selector": "2.3.*", - "symfony/debug": "2.3.*", - "symfony/dom-crawler": "2.3.*", - "symfony/event-dispatcher": "2.3.*", - "symfony/finder": "2.3.*", - "symfony/http-foundation": "2.3.*", - "symfony/http-kernel": "2.3.*", - "symfony/process": "2.3.*", - "symfony/routing": "2.3.*", - "symfony/translation": "2.3.*" + "classpreloader/classpreloader": "~2.0", + "danielstjules/stringy": "~1.8", + "doctrine/inflector": "~1.0", + "ext-mbstring": "*", + "ext-openssl": "*", + "jeremeamia/superclosure": "~2.0", + "league/flysystem": "~1.0", + "monolog/monolog": "~1.11", + "mtdowling/cron-expression": "~1.0", + "nesbot/carbon": "~1.19", + "php": ">=5.5.9", + "psy/psysh": "~0.5.1", + "swiftmailer/swiftmailer": "~5.1", + "symfony/console": "2.7.*", + "symfony/css-selector": "2.7.*", + "symfony/debug": "2.7.*", + "symfony/dom-crawler": "2.7.*", + "symfony/finder": "2.7.*", + "symfony/http-foundation": "2.7.*", + "symfony/http-kernel": "2.7.*", + "symfony/process": "2.7.*", + "symfony/routing": "2.7.*", + "symfony/translation": "2.7.*", + "symfony/var-dumper": "2.7.*", + "vlucas/phpdotenv": "~1.0" }, "replace": { "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", "illuminate/container": "self.version", + "illuminate/contracts": "self.version", "illuminate/cookie": "self.version", "illuminate/database": "self.version", "illuminate/encryption": "self.version", @@ -1050,11 +685,11 @@ "illuminate/filesystem": "self.version", "illuminate/foundation": "self.version", "illuminate/hashing": "self.version", - "illuminate/html": "self.version", "illuminate/http": "self.version", "illuminate/log": "self.version", "illuminate/mail": "self.version", "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", "illuminate/routing": "self.version", @@ -1062,33 +697,44 @@ "illuminate/support": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version", - "illuminate/workbench": "self.version" + "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "2.4.*", - "iron-io/iron_mq": "1.4.*", - "mockery/mockery": "0.8.0", - "pda/pheanstalk": "2.1.*", - "phpunit/phpunit": "3.7.*" + "aws/aws-sdk-php": "~3.0", + "iron-io/iron_mq": "~2.0", + "mockery/mockery": "~0.9.1", + "pda/pheanstalk": "~3.0", + "phpunit/phpunit": "~4.0", + "predis/predis": "~1.0" + }, + "suggest": { + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", + "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.3|~6.0).", + "iron-io/iron_mq": "Required to use the iron queue driver (~2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", + "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { "classmap": [ - [ - "src/Illuminate/Queue/IlluminateQueueClosure.php" - ] + "src/Illuminate/Queue/IlluminateQueueClosure.php" ], "files": [ + "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" ], - "psr-0": { - "Illuminate": "src/" + "psr-4": { + "Illuminate\\": "src/Illuminate/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1098,150 +744,110 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com", - "homepage": "https://github.com/taylorotwell", - "role": "Creator of Laravel" + "email": "taylorotwell@gmail.com" } ], "description": "The Laravel Framework.", + "homepage": "http://laravel.com", "keywords": [ "framework", "laravel" ], - "time": "2014-07-12 17:43:27" + "time": "2015-09-04 12:46:14" }, { - "name": "machuga/authority", - "version": "2.1.1", + "name": "league/flysystem", + "version": "1.0.12", "source": { "type": "git", - "url": "https://github.com/machuga/authority.git", - "reference": "e12c9cb5b2d0624f190ff21d27bd00a1de645b34" + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "7323424a9d39c24e597ed3f2144419dfbb52e086" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/machuga/authority/zipball/e12c9cb5b2d0624f190ff21d27bd00a1de645b34", - "reference": "e12c9cb5b2d0624f190ff21d27bd00a1de645b34", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/7323424a9d39c24e597ed3f2144419dfbb52e086", + "reference": "7323424a9d39c24e597ed3f2144419dfbb52e086", "shasum": "" }, "require": { - "illuminate/events": "~4", - "php": ">=5.3.0" + "php": ">=5.4.0" }, "require-dev": { - "mockery/mockery": "0.7.*", - "phpunit/phpunit": "3.7.*" + "ext-fileinfo": "*", + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^2.2", + "phpspec/prophecy-phpunit": "~1.0", + "phpunit/phpunit": "~4.1" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-copy": "Allows you to use Copy.com storage", + "league/flysystem-dropbox": "Allows you to use Dropbox storage", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "1.1-dev" } }, "autoload": { - "psr-0": { - "Authority": "src/" + "psr-4": { + "League\\Flysystem\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "mit" + "MIT" ], "authors": [ { - "name": "Matthew Machuga", - "email": "machuga@gmail.com" - }, - { - "name": "Koen Schmeets", - "email": "hello@koenschmeets.nl" - }, - { - "name": "Jesse O'Brien", - "email": "jesse@jesse-obrien.ca" + "name": "Frank de Jonge", + "email": "info@frenky.net" } ], - "description": "A simple and flexible authorization system for PHP", - "time": "2015-02-19 04:30:09" - }, - { - "name": "machuga/authority-l4", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/machuga/authority-l4.git", - "reference": "016ddd3892ec8c07c830f7e34e48bf8c63e022dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/machuga/authority-l4/zipball/016ddd3892ec8c07c830f7e34e48bf8c63e022dd", - "reference": "016ddd3892ec8c07c830f7e34e48bf8c63e022dd", - "shasum": "" - }, - "require": { - "illuminate/support": "~4", - "machuga/authority": "2.1.*", - "php": ">=5.3.0" - }, - "require-dev": { - "mockery/mockery": "0.7.*", - "phpunit/phpunit": "3.7.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/migrations" - ], - "psr-0": { - "Authority\\AuthorityL4": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "authors": [ - { - "name": "Matthew Machuga", - "email": "machuga@gmail.com" - }, - { - "name": "Koen Schmeets", - "email": "hello@koenschmeets.nl" - }, - { - "name": "Jesse O'Brien", - "email": "jesse@jesse-obrien.ca" - }, - { - "name": "Conar Welsh", - "email": "conar@welshlabs.com" - } - ], - "description": "A simple and flexible authorization system for PHP", - "homepage": "https://github.com/machuga/authority-l4", + "description": "Filesystem abstraction: Many filesystems, one API.", "keywords": [ - "Authentication", - "Laravel 4", - "authorization", - "laravel" + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" ], - "time": "2014-03-13 16:49:16" + "time": "2015-09-05 12:06:41" }, { "name": "monolog/monolog", - "version": "1.13.1", + "version": "1.17.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "c31a2c4e8db5da8b46c74cf275d7f109c0f249ac" + "reference": "0524c87587ab85bc4c2d6f5b41253ccb930a5422" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c31a2c4e8db5da8b46c74cf275d7f109c0f249ac", - "reference": "c31a2c4e8db5da8b46c74cf275d7f109c0f249ac", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/0524c87587ab85bc4c2d6f5b41253ccb930a5422", + "reference": "0524c87587ab85bc4c2d6f5b41253ccb930a5422", "shasum": "" }, "require": { @@ -1252,12 +858,14 @@ "psr/log-implementation": "1.0.0" }, "require-dev": { - "aws/aws-sdk-php": "~2.4, >2.4.8", + "aws/aws-sdk-php": "^2.4.9", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", - "phpunit/phpunit": "~4.0", - "raven/raven": "~0.5", - "ruflin/elastica": "0.90.*", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "raven/raven": "~0.11", + "ruflin/elastica": ">=0.90 <3.0", "swiftmailer/swiftmailer": "~5.3", "videlalvaro/php-amqplib": "~2.4" }, @@ -1267,6 +875,7 @@ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "php-console/php-console": "Allow sending log messages to Google Chrome", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server", @@ -1275,7 +884,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13.x-dev" + "dev-master": "1.16.x-dev" } }, "autoload": { @@ -1301,24 +910,69 @@ "logging", "psr-3" ], - "time": "2015-03-09 09:58:04" + "time": "2015-08-31 09:17:37" }, { - "name": "nesbot/carbon", - "version": "1.17.0", + "name": "mtdowling/cron-expression", + "version": "v1.0.4", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "a1dd1ad9abfc8b3c4d8768068e6c71d293424e86" + "url": "https://github.com/mtdowling/cron-expression.git", + "reference": "fd92e883195e5dfa77720b1868cf084b08be4412" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/a1dd1ad9abfc8b3c4d8768068e6c71d293424e86", - "reference": "a1dd1ad9abfc8b3c4d8768068e6c71d293424e86", + "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/fd92e883195e5dfa77720b1868cf084b08be4412", + "reference": "fd92e883195e5dfa77720b1868cf084b08be4412", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Cron": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "time": "2015-01-11 23:07:46" + }, + { + "name": "nesbot/carbon", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", + "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/translation": "~2.6|~3.0" }, "require-dev": { "phpunit/phpunit": "~4.0" @@ -1347,36 +1001,36 @@ "datetime", "time" ], - "time": "2015-03-08 14:05:44" + "time": "2015-06-25 04:19:39" }, { "name": "nikic/php-parser", - "version": "v0.9.5", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb" + "reference": "196f177cfefa0f1f7166c0a05d8255889be12418" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/196f177cfefa0f1f7166c0a05d8255889be12418", + "reference": "196f177cfefa0f1f7166c0a05d8255889be12418", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.2" + "php": ">=5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.9-dev" + "dev-master": "1.4-dev" } }, "autoload": { - "psr-0": { - "PHPParser": "lib/" - } + "files": [ + "lib/bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1392,58 +1046,7 @@ "parser", "php" ], - "time": "2014-07-23 18:24:17" - }, - { - "name": "patchwork/utf8", - "version": "v1.1.29", - "source": { - "type": "git", - "url": "https://github.com/tchwork/utf8.git", - "reference": "65b19607048351f767a034d4cc709db8b136d2c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tchwork/utf8/zipball/65b19607048351f767a034d4cc709db8b136d2c5", - "reference": "65b19607048351f767a034d4cc709db8b136d2c5", - "shasum": "" - }, - "require": { - "lib-pcre": ">=7.3", - "php": ">=5.3.0" - }, - "suggest": { - "ext-iconv": "Use iconv for best performance", - "ext-intl": "Use Intl for best performance", - "ext-mbstring": "Use Mbstring for best performance" - }, - "type": "library", - "autoload": { - "psr-0": { - "Patchwork": "class/", - "Normalizer": "class/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "(Apache-2.0 or GPL-2.0)" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - } - ], - "description": "Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP", - "homepage": "https://github.com/tchwork/utf8", - "keywords": [ - "grapheme", - "i18n", - "unicode", - "utf-8", - "utf8" - ], - "time": "2015-04-26 09:48:22" + "time": "2015-07-14 17:31:05" }, { "name": "phpdocumentor/reflection-docblock", @@ -1494,56 +1097,6 @@ ], "time": "2015-02-03 12:10:50" }, - { - "name": "predis/predis", - "version": "v0.8.7", - "source": { - "type": "git", - "url": "https://github.com/nrk/predis.git", - "reference": "4123fcd85d61354c6c9900db76c9597dbd129bf6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/4123fcd85d61354c6c9900db76c9597dbd129bf6", - "reference": "4123fcd85d61354c6c9900db76c9597dbd129bf6", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "ext-curl": "Allows access to Webdis when paired with phpiredis", - "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" - }, - "type": "library", - "autoload": { - "psr-0": { - "Predis": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniele Alessandri", - "email": "suppakilla@gmail.com", - "homepage": "http://clorophilla.net" - } - ], - "description": "Flexible and feature-complete PHP client library for Redis", - "homepage": "http://github.com/nrk/predis", - "keywords": [ - "nosql", - "predis", - "redis" - ], - "time": "2014-08-01 09:43:10" - }, { "name": "psr/log", "version": "1.0.0", @@ -1582,6 +1135,78 @@ ], "time": "2012-12-21 11:40:51" }, + { + "name": "psy/psysh", + "version": "v0.5.2", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "aaf8772ade08b5f0f6830774a5d5c2f800415975" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/aaf8772ade08b5f0f6830774a5d5c2f800415975", + "reference": "aaf8772ade08b5f0f6830774a5d5c2f800415975", + "shasum": "" + }, + "require": { + "dnoegel/php-xdg-base-dir": "0.1", + "jakub-onderka/php-console-highlighter": "0.3.*", + "nikic/php-parser": "^1.2.1", + "php": ">=5.3.9", + "symfony/console": "~2.3.10|^2.4.2|~3.0", + "symfony/var-dumper": "~2.7|~3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "~1.5", + "phpunit/phpunit": "~3.7|~4.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/finder": "~2.1|~3.0" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.6.x-dev" + } + }, + "autoload": { + "files": [ + "src/Psy/functions.php" + ], + "psr-0": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "time": "2015-07-16 15:26:57" + }, { "name": "simplepie/simplepie", "version": "1.3.1", @@ -1638,25 +1263,28 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v5.0.3", + "version": "v5.4.1", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "32edc3b0de0fdc1b10f5c4912e8677b3f411a230" + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/32edc3b0de0fdc1b10f5c4912e8677b3f411a230", - "reference": "32edc3b0de0fdc1b10f5c4912e8677b3f411a230", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421", "shasum": "" }, "require": { - "php": ">=5.2.4" + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1,<0.9.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-master": "5.4-dev" } }, "autoload": { @@ -1669,79 +1297,22 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Chris Corbyn" - } - ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "http://swiftmailer.org", - "keywords": [ - "mail", - "mailer" - ], - "time": "2013-12-03 13:33:24" - }, - { - "name": "symfony/browser-kit", - "version": "v2.3.27", - "target-dir": "Symfony/Component/BrowserKit", - "source": { - "type": "git", - "url": "https://github.com/symfony/BrowserKit.git", - "reference": "8d708185137152fab42aca14efca19c71ee701dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/8d708185137152fab42aca14efca19c71ee701dc", - "reference": "8d708185137152fab42aca14efca19c71ee701dc", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/dom-crawler": "~2.0,>=2.0.5" - }, - "require-dev": { - "symfony/css-selector": "~2.0,>=2.0.5", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.0,>=2.0.5" - }, - "suggest": { - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\BrowserKit\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], - "description": "Symfony BrowserKit Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 22:05:05" + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "http://swiftmailer.org", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2015-06-06 14:19:39" }, { "name": "symfony/class-loader", @@ -1795,37 +1366,40 @@ }, { "name": "symfony/console", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Console", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "6081c3ca0284655996fa3d9f91063b8f0b669f3b" + "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/6081c3ca0284655996fa3d9f91063b8f0b669f3b", - "reference": "6081c3ca0284655996fa3d9f91063b8f0b669f3b", + "url": "https://api.github.com/repos/symfony/Console/zipball/d6cf02fe73634c96677e428f840704bfbcaec29e", + "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { + "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.1" }, "suggest": { - "symfony/event-dispatcher": "" + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" } }, @@ -1834,36 +1408,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 22:05:05" + "homepage": "https://symfony.com", + "time": "2015-07-28 15:18:12" }, { "name": "symfony/css-selector", - "version": "v2.3.27", - "target-dir": "Symfony/Component/CssSelector", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/CssSelector.git", - "reference": "241746d062f873d77d1886c2b97b56811bb5f659" + "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/CssSelector/zipball/241746d062f873d77d1886c2b97b56811bb5f659", - "reference": "241746d062f873d77d1886c2b97b56811bb5f659", + "url": "https://api.github.com/repos/symfony/CssSelector/zipball/0b5c07b516226b7dd32afbbc82fe547a469c5092", + "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1871,11 +1444,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\CssSelector\\": "" } }, @@ -1884,10 +1457,6 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Jean-François Simon", "email": "jeanfrancois.simon@sensiolabs.com" @@ -1895,51 +1464,55 @@ { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony CssSelector Component", - "homepage": "http://symfony.com", - "time": "2015-03-22 16:41:17" + "homepage": "https://symfony.com", + "time": "2015-05-15 13:33:16" }, { "name": "symfony/debug", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Debug", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Debug.git", - "reference": "796dd4cd1191774b3c4980ab586836c87f933569" + "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/796dd4cd1191774b3c4980ab586836c87f933569", - "reference": "796dd4cd1191774b3c4980ab586836c87f933569", + "url": "https://api.github.com/repos/symfony/Debug/zipball/9daa1bf9f7e615fa2fba30357e479a90141222e3", + "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9", + "psr/log": "~1.0" }, "conflict": { "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { + "symfony/class-loader": "~2.2", "symfony/http-foundation": "~2.1", "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2", "symfony/phpunit-bridge": "~2.7" }, "suggest": { - "symfony/class-loader": "", "symfony/http-foundation": "", "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Debug\\": "" } }, @@ -1948,39 +1521,38 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Debug Component", - "homepage": "http://symfony.com", - "time": "2015-03-21 11:11:30" + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" }, { "name": "symfony/dom-crawler", - "version": "v2.3.27", - "target-dir": "Symfony/Component/DomCrawler", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/DomCrawler.git", - "reference": "668b611914a23a00bac06f0433f6e6586b28cdca" + "reference": "9dabece63182e95c42b06967a0d929a5df78bc35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/668b611914a23a00bac06f0433f6e6586b28cdca", - "reference": "668b611914a23a00bac06f0433f6e6586b28cdca", + "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/9dabece63182e95c42b06967a0d929a5df78bc35", + "reference": "9dabece63182e95c42b06967a0d929a5df78bc35", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { - "symfony/css-selector": "~2.0,>=2.0.5", + "symfony/css-selector": "~2.3", "symfony/phpunit-bridge": "~2.7" }, "suggest": { @@ -1989,11 +1561,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\DomCrawler\\": "" } }, @@ -2002,40 +1574,43 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony DomCrawler Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 22:12:40" + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" }, { "name": "symfony/event-dispatcher", - "version": "v2.3.27", - "target-dir": "Symfony/Component/EventDispatcher", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "68771791930c7c1923bc64db1cfaf8692a5878a0" + "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/68771791930c7c1923bc64db1cfaf8692a5878a0", - "reference": "68771791930c7c1923bc64db1cfaf8692a5878a0", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", + "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { - "symfony/dependency-injection": "~2.0,>=2.0.5", - "symfony/phpunit-bridge": "~2.7" + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/phpunit-bridge": "~2.7", + "symfony/stopwatch": "~2.3" }, "suggest": { "symfony/dependency-injection": "", @@ -2044,11 +1619,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" } }, @@ -2057,86 +1632,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2015-02-24 10:24:26" - }, - { - "name": "symfony/filesystem", - "version": "v2.6.6", - "target-dir": "Symfony/Component/Filesystem", - "source": { - "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "4983964b3693e4f13449cb3800c64a9112c301b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4983964b3693e4f13449cb3800c64a9112c301b4", - "reference": "4983964b3693e4f13449cb3800c64a9112c301b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Filesystem\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "http://symfony.com", - "time": "2015-03-22 16:55:57" + "homepage": "https://symfony.com", + "time": "2015-06-18 19:21:56" }, { "name": "symfony/finder", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Finder", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "271c8f13ab5442868fbbc6737d33704a64b29351" + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/271c8f13ab5442868fbbc6737d33704a64b29351", - "reference": "271c8f13ab5442868fbbc6737d33704a64b29351", + "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4", + "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -2144,11 +1668,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Finder\\": "" } }, @@ -2157,52 +1681,52 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Finder Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 22:05:05" + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" }, { "name": "symfony/http-foundation", - "version": "v2.3.27", - "target-dir": "Symfony/Component/HttpFoundation", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "98a2199db323438a2d5e4b2d6bb031cf6f4bfaca" + "reference": "863af6898081b34c65d42100c370b9f3c51b70ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/98a2199db323438a2d5e4b2d6bb031cf6f4bfaca", - "reference": "98a2199db323438a2d5e4b2d6bb031cf6f4bfaca", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/863af6898081b34c65d42100c370b9f3c51b70ca", + "reference": "863af6898081b34c65d42100c370b9f3c51b70ca", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { + "symfony/expression-language": "~2.4", "symfony/phpunit-bridge": "~2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, "classmap": [ - "Symfony/Component/HttpFoundation/Resources/stubs" + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2210,55 +1734,60 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony HttpFoundation Component", - "homepage": "http://symfony.com", - "time": "2015-04-01 14:16:10" + "homepage": "https://symfony.com", + "time": "2015-07-22 10:11:00" }, { "name": "symfony/http-kernel", - "version": "v2.3.27", - "target-dir": "Symfony/Component/HttpKernel", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel.git", - "reference": "d33f5c343c2a73b5cf17e14630c97f4a47ce2d66" + "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/d33f5c343c2a73b5cf17e14630c97f4a47ce2d66", - "reference": "d33f5c343c2a73b5cf17e14630c97f4a47ce2d66", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/405d3e7a59ff7a28ec469441326a0ac79065ea98", + "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.9", "psr/log": "~1.0", - "symfony/debug": "~2.3.24|~2.5.9|~2.6,>=2.6.2", - "symfony/event-dispatcher": "~2.1", - "symfony/http-foundation": "~2.3,>=2.3.4" + "symfony/debug": "~2.6,>=2.6.2", + "symfony/event-dispatcher": "~2.6,>=2.6.7", + "symfony/http-foundation": "~2.5,>=2.5.4" + }, + "conflict": { + "symfony/config": "<2.7" }, "require-dev": { "symfony/browser-kit": "~2.3", "symfony/class-loader": "~2.1", - "symfony/config": "~2.0,>=2.0.5", - "symfony/console": "~2.2", + "symfony/config": "~2.7", + "symfony/console": "~2.3", "symfony/css-selector": "~2.0,>=2.0.5", "symfony/dependency-injection": "~2.2", "symfony/dom-crawler": "~2.0,>=2.0.5", + "symfony/expression-language": "~2.4", "symfony/finder": "~2.0,>=2.0.5", "symfony/phpunit-bridge": "~2.7", "symfony/process": "~2.0,>=2.0.5", "symfony/routing": "~2.2", "symfony/stopwatch": "~2.3", - "symfony/templating": "~2.2" + "symfony/templating": "~2.2", + "symfony/translation": "~2.0,>=2.0.5", + "symfony/var-dumper": "~2.6" }, "suggest": { "symfony/browser-kit": "", @@ -2266,16 +1795,17 @@ "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "" + "symfony/finder": "", + "symfony/var-dumper": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\HttpKernel\\": "" } }, @@ -2284,36 +1814,35 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony HttpKernel Component", - "homepage": "http://symfony.com", - "time": "2015-04-01 14:28:26" + "homepage": "https://symfony.com", + "time": "2015-07-31 13:24:45" }, { "name": "symfony/process", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Process", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "db46cf1e1730f75d411c6b8e981d830092d51dc4" + "reference": "48aeb0e48600321c272955132d7606ab0a49adb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/db46cf1e1730f75d411c6b8e981d830092d51dc4", - "reference": "db46cf1e1730f75d411c6b8e981d830092d51dc4", + "url": "https://api.github.com/repos/symfony/Process/zipball/48aeb0e48600321c272955132d7606ab0a49adb3", + "reference": "48aeb0e48600321c272955132d7606ab0a49adb3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -2321,11 +1850,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Process\\": "" } }, @@ -2334,58 +1863,63 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Process Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 15:19:08" + "homepage": "https://symfony.com", + "time": "2015-07-01 11:25:50" }, { "name": "symfony/routing", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Routing", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Routing.git", - "reference": "a6f4dc55fe3d2ba3a0efa145c3efb373992e92e7" + "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/a6f4dc55fe3d2ba3a0efa145c3efb373992e92e7", - "reference": "a6f4dc55fe3d2ba3a0efa145c3efb373992e92e7", + "url": "https://api.github.com/repos/symfony/Routing/zipball/ea9134f277162b02e5f80ac058b75a77637b0d26", + "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" }, "require-dev": { + "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0", - "symfony/config": "~2.2", + "symfony/config": "~2.7", + "symfony/expression-language": "~2.4", "symfony/http-foundation": "~2.3", "symfony/phpunit-bridge": "~2.7", "symfony/yaml": "~2.0,>=2.0.5" }, "suggest": { - "doctrine/common": "", - "symfony/config": "", - "symfony/yaml": "" + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/yaml": "For using the YAML loader" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Routing\\": "" } }, @@ -2394,55 +1928,65 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Routing Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 22:05:05" + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2015-07-09 16:07:40" }, { "name": "symfony/translation", - "version": "v2.3.27", - "target-dir": "Symfony/Component/Translation", + "version": "v2.7.3", "source": { "type": "git", "url": "https://github.com/symfony/Translation.git", - "reference": "600ef7febf07aec56f3d2579fd1496cd332d9112" + "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Translation/zipball/600ef7febf07aec56f3d2579fd1496cd332d9112", - "reference": "600ef7febf07aec56f3d2579fd1496cd332d9112", + "url": "https://api.github.com/repos/symfony/Translation/zipball/c8dc34cc936152c609cdd722af317e4239d10dd6", + "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" }, "require-dev": { - "symfony/config": "~2.3,>=2.3.12", + "psr/log": "~1.0", + "symfony/config": "~2.7", "symfony/intl": "~2.3", "symfony/phpunit-bridge": "~2.7", "symfony/yaml": "~2.2" }, "suggest": { + "psr/log": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Translation\\": "" } }, @@ -2451,21 +1995,1303 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Translation Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:33:35" + "homepage": "https://symfony.com", + "time": "2015-07-09 16:07:40" + }, + { + "name": "symfony/var-dumper", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e8903ebba5eb019f5886ffce739ea9e3b7519579", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "suggest": { + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2015-07-28 15:18:12" + }, + { + "name": "vlucas/phpdotenv", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Dotenv": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "homepage": "http://github.com/vlucas/phpdotenv", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2015-05-30 15:59:26" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "fzaninotto/faker", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d0190b156bcca848d401fb80f31f504f37141c8d", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "suggest": { + "ext-intl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2015-05-29 06:29:14" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "satooshi/php-coveralls": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2015-05-11 14:41:42" + }, + { + "name": "mockery/mockery", + "version": "0.9.4", + "source": { + "type": "git", + "url": "https://github.com/padraic/mockery.git", + "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", + "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2015-04-02 19:54:00" + }, + { + "name": "phpspec/php-diff", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/phpspec/php-diff.git", + "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", + "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Diff": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Chris Boulton", + "homepage": "http://github.com/chrisboulton", + "role": "Original developer" + } + ], + "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", + "time": "2013-11-01 13:02:21" + }, + { + "name": "phpspec/phpspec", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/phpspec.git", + "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/phpspec/zipball/e9a40577323e67f1de2e214abf32976a0352d8f8", + "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.1", + "php": ">=5.3.3", + "phpspec/php-diff": "~1.0.0", + "phpspec/prophecy": "~1.4", + "sebastian/exporter": "~1.0", + "symfony/console": "~2.3", + "symfony/event-dispatcher": "~2.1", + "symfony/finder": "~2.1", + "symfony/process": "~2.1", + "symfony/yaml": "~2.1" + }, + "require-dev": { + "behat/behat": "^3.0.11", + "bossa/phpspec2-expect": "~1.0", + "phpunit/phpunit": "~4.4", + "symfony/filesystem": "~2.1", + "symfony/process": "~2.1" + }, + "suggest": { + "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" + }, + "bin": [ + "bin/phpspec" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "PhpSpec": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "homepage": "http://marcelloduarte.net/" + } + ], + "description": "Specification-oriented BDD framework for PHP 5.3+", + "homepage": "http://phpspec.net/", + "keywords": [ + "BDD", + "SpecBDD", + "TDD", + "spec", + "specification", + "testing", + "tests" + ], + "time": "2015-05-30 15:21:40" + }, + { + "name": "phpspec/prophecy", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-08-13 10:07:40" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-08-04 03:42:39" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2015-06-21 08:01:12" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-08-16 08:51:00" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357", + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": ">=1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2015-08-24 04:09:38" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5e2645ad49d196e020b85598d7c97e482725786a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a", + "reference": "5e2645ad49d196e020b85598d7c97e482725786a", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-08-19 09:14:08" + }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "1.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-08-03 06:14:51" + }, + { + "name": "sebastian/exporter", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-06-21 07:55:53" + }, + { + "name": "sebastian/global-state", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2014-10-06 09:23:50" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-06-21 08:04:50" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "name": "symfony/yaml", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "71340e996171474a53f3d29111d046be4ad8a0ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/71340e996171474a53f3d29111d046be4ad8a0ff", + "reference": "71340e996171474a53f3d29111d046be4ad8a0ff", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2015-07-28 14:07:07" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": { @@ -2473,6 +3299,8 @@ }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": ">=5.5.9" + }, "platform-dev": [] } diff --git a/config/app.php b/config/app.php new file mode 100644 index 00000000..a6ebd715 --- /dev/null +++ b/config/app.php @@ -0,0 +1,202 @@ + env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'https://pony.fm'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => MCRYPT_RIJNDAEL_128, + + /* + |-------------------------------------------------------------------------- + | Logging Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure the log settings for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Settings: "single", "daily", "syslog", "errorlog" + | + */ + + 'log' => 'daily', + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => [ + + /* + * Laravel Framework Service Providers... + */ + Illuminate\Foundation\Providers\ArtisanServiceProvider::class, + Illuminate\Auth\AuthServiceProvider::class, + Illuminate\Broadcasting\BroadcastServiceProvider::class, + Illuminate\Bus\BusServiceProvider::class, + Illuminate\Cache\CacheServiceProvider::class, + Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, + Illuminate\Routing\ControllerServiceProvider::class, + Illuminate\Cookie\CookieServiceProvider::class, + Illuminate\Database\DatabaseServiceProvider::class, + Illuminate\Encryption\EncryptionServiceProvider::class, + Illuminate\Filesystem\FilesystemServiceProvider::class, + Illuminate\Foundation\Providers\FoundationServiceProvider::class, + Illuminate\Hashing\HashServiceProvider::class, + Illuminate\Mail\MailServiceProvider::class, + Illuminate\Pagination\PaginationServiceProvider::class, + Illuminate\Pipeline\PipelineServiceProvider::class, + Illuminate\Queue\QueueServiceProvider::class, + Illuminate\Redis\RedisServiceProvider::class, + Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, + Illuminate\Session\SessionServiceProvider::class, + Illuminate\Translation\TranslationServiceProvider::class, + Illuminate\Validation\ValidationServiceProvider::class, + Illuminate\View\ViewServiceProvider::class, + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + + Intouch\LaravelNewrelic\NewrelicServiceProvider::class, + Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class, + + ], + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => [ + + 'App' => Illuminate\Support\Facades\App::class, + 'Artisan' => Illuminate\Support\Facades\Artisan::class, + 'Auth' => Illuminate\Support\Facades\Auth::class, + 'Blade' => Illuminate\Support\Facades\Blade::class, + 'Bus' => Illuminate\Support\Facades\Bus::class, + 'Cache' => Illuminate\Support\Facades\Cache::class, + 'Config' => Illuminate\Support\Facades\Config::class, + 'Cookie' => Illuminate\Support\Facades\Cookie::class, + 'Crypt' => Illuminate\Support\Facades\Crypt::class, + 'DB' => Illuminate\Support\Facades\DB::class, + 'Eloquent' => Illuminate\Database\Eloquent\Model::class, + 'Event' => Illuminate\Support\Facades\Event::class, +// 'File' => Illuminate\Support\Facades\File::class, + 'Hash' => Illuminate\Support\Facades\Hash::class, + 'Input' => Illuminate\Support\Facades\Input::class, + 'Inspiring' => Illuminate\Foundation\Inspiring::class, + 'Lang' => Illuminate\Support\Facades\Lang::class, + 'Log' => Illuminate\Support\Facades\Log::class, + 'Mail' => Illuminate\Support\Facades\Mail::class, + 'Password' => Illuminate\Support\Facades\Password::class, + 'Queue' => Illuminate\Support\Facades\Queue::class, + 'Redirect' => Illuminate\Support\Facades\Redirect::class, + 'Redis' => Illuminate\Support\Facades\Redis::class, + 'Request' => Illuminate\Support\Facades\Request::class, + 'Response' => Illuminate\Support\Facades\Response::class, + 'Route' => Illuminate\Support\Facades\Route::class, + 'Schema' => Illuminate\Support\Facades\Schema::class, + 'Session' => Illuminate\Support\Facades\Session::class, + 'Storage' => Illuminate\Support\Facades\Storage::class, + 'URL' => Illuminate\Support\Facades\URL::class, + 'Validator' => Illuminate\Support\Facades\Validator::class, + 'View' => Illuminate\Support\Facades\View::class, + + 'Newrelic' => Intouch\LaravelNewrelic\Facades\Newrelic::class, + + ], + +]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 00000000..5223dd42 --- /dev/null +++ b/config/auth.php @@ -0,0 +1,67 @@ + 'eloquent', + + /* + |-------------------------------------------------------------------------- + | Authentication Model + |-------------------------------------------------------------------------- + | + | When using the "Eloquent" authentication driver, we need to know which + | Eloquent model should be used to retrieve your users. Of course, it + | is often just the "User" model but you may use whatever you like. + | + */ + + 'model' => App\User::class, + + /* + |-------------------------------------------------------------------------- + | Authentication Table + |-------------------------------------------------------------------------- + | + | When using the "Database" authentication driver, we need to know which + | table should be used to retrieve your users. We have chosen a basic + | default value but you may easily change it to any table you like. + | + */ + + 'table' => 'users', + + /* + |-------------------------------------------------------------------------- + | Password Reset Settings + |-------------------------------------------------------------------------- + | + | Here you may set the options for resetting passwords including the view + | that is your password reset e-mail. You can also set the name of the + | table that maintains all of the reset tokens for your application. + | + | The expire time is the number of minutes that the reset token should be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + */ + + 'password' => [ + 'email' => 'emails.auth.reminder', + 'table' => 'password_reminders', + 'expire' => 60, + ], + +]; diff --git a/config/broadcasting.php b/config/broadcasting.php new file mode 100644 index 00000000..36f9b3c1 --- /dev/null +++ b/config/broadcasting.php @@ -0,0 +1,49 @@ + env('BROADCAST_DRIVER', 'pusher'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_KEY'), + 'secret' => env('PUSHER_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + ], + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 00000000..fa3644f0 --- /dev/null +++ b/config/cache.php @@ -0,0 +1,79 @@ + env('CACHE_DRIVER', 'database'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'servers' => [ + [ + 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing a RAM based store such as APC or Memcached, there might + | be other applications utilizing the same cache. So, we'll specify a + | value to get prefixed to all our keys so we can avoid collisions. + | + */ + + 'prefix' => 'ponyfm', + +]; diff --git a/config/compile.php b/config/compile.php new file mode 100644 index 00000000..04807eac --- /dev/null +++ b/config/compile.php @@ -0,0 +1,35 @@ + [ + // + ], + + /* + |-------------------------------------------------------------------------- + | Compiled File Providers + |-------------------------------------------------------------------------- + | + | Here you may list service providers which define a "compiles" function + | that returns additional files that should be compiled, providing an + | easy way to get common files from any packages you are utilizing. + | + */ + + 'providers' => [ + // + ], + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 00000000..f6cf86b4 --- /dev/null +++ b/config/database.php @@ -0,0 +1,126 @@ + PDO::FETCH_CLASS, + + /* + |-------------------------------------------------------------------------- + | Default Database Connection Name + |-------------------------------------------------------------------------- + | + | Here you may specify which of the database connections below you wish + | to use as your default connection for all database work. Of course + | you may use many connections at once using the Database library. + | + */ + + 'default' => env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'database' => storage_path('database.sqlite'), + 'prefix' => '', + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'host' => env('DB_HOST', 'localhost'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', + 'prefix' => '', + 'strict' => false, + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'host' => env('DB_HOST', 'localhost'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'schema' => 'public', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'host' => env('DB_HOST', 'localhost'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer set of commands than a typical key-value systems + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'cluster' => false, + + 'default' => [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'database' => 0, + ], + + ], + +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 00000000..3fffcf0a --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,85 @@ + 'local', + + /* + |-------------------------------------------------------------------------- + | Default Cloud Filesystem Disk + |-------------------------------------------------------------------------- + | + | Many applications store files both locally and in the cloud. For this + | reason, you may specify a default "cloud" driver here. This driver + | will be bound as the Cloud disk implementation in the container. + | + */ + + 'cloud' => 's3', + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been setup for each driver as an example of the required options. + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + ], + + 'ftp' => [ + 'driver' => 'ftp', + 'host' => 'ftp.example.com', + 'username' => 'your-username', + 'password' => 'your-password', + + // Optional FTP Settings... + // 'port' => 21, + // 'root' => '', + // 'passive' => true, + // 'ssl' => true, + // 'timeout' => 30, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => 'your-key', + 'secret' => 'your-secret', + 'region' => 'your-region', + 'bucket' => 'your-bucket', + ], + + 'rackspace' => [ + 'driver' => 'rackspace', + 'username' => 'your-username', + 'key' => 'your-key', + 'container' => 'your-container', + 'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/', + 'region' => 'IAD', + 'url_type' => 'publicURL', + ], + + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 00000000..a22807e7 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,124 @@ + env('MAIL_DRIVER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | SMTP Host Address + |-------------------------------------------------------------------------- + | + | Here you may provide the host address of the SMTP server used by your + | applications. A default option is provided that is compatible with + | the Mailgun mail service which will provide reliable deliveries. + | + */ + + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + + /* + |-------------------------------------------------------------------------- + | SMTP Host Port + |-------------------------------------------------------------------------- + | + | This is the SMTP port used by your application to deliver e-mails to + | users of the application. Like the host we have set this value to + | stay compatible with the Mailgun e-mail application by default. + | + */ + + 'port' => env('MAIL_PORT', 587), + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => ['address' => null, 'name' => null], + + /* + |-------------------------------------------------------------------------- + | E-Mail Encryption Protocol + |-------------------------------------------------------------------------- + | + | Here you may specify the encryption protocol that should be used when + | the application send e-mail messages. A sensible default using the + | transport layer security protocol should provide great security. + | + */ + + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + + /* + |-------------------------------------------------------------------------- + | SMTP Server Username + |-------------------------------------------------------------------------- + | + | If your SMTP server requires a username for authentication, you should + | set it here. This will get used to authenticate with your server on + | connection. You may also set the "password" value below this one. + | + */ + + 'username' => env('MAIL_USERNAME'), + + /* + |-------------------------------------------------------------------------- + | SMTP Server Password + |-------------------------------------------------------------------------- + | + | Here you may set the password required by your SMTP server to send out + | messages from your application. This will be given to the server on + | connection so that the application will be able to send messages. + | + */ + + 'password' => env('MAIL_PASSWORD'), + + /* + |-------------------------------------------------------------------------- + | Sendmail System Path + |-------------------------------------------------------------------------- + | + | When using the "sendmail" driver to send e-mails, we will need to know + | the path to where Sendmail lives on this server. A default path has + | been provided here, which will work well on most of your systems. + | + */ + + 'sendmail' => '/usr/sbin/sendmail -bs', + + /* + |-------------------------------------------------------------------------- + | Mail "Pretend" + |-------------------------------------------------------------------------- + | + | When this option is enabled, e-mail will not actually be sent over the + | web and will instead be written to your application's logs files so + | you may inspect the message. This is great for local development. + | + */ + + 'pretend' => false, + +]; diff --git a/config/newrelic.php b/config/newrelic.php new file mode 100644 index 00000000..46a27527 --- /dev/null +++ b/config/newrelic.php @@ -0,0 +1,42 @@ + true, + + /* + * Define the name used when automatically naming transactions. + * a token string: + * a pattern you define yourself, available tokens: + * {controller} = Controller@action or Closure@path + * {method} = GET / POST / etc. + * {route} = route name if named, otherwise same as {controller} + * {path} = the registered route path (includes variable names) + * {uri} = the actual URI requested + * anything that is not a matched token will remain a string literal + * example: + * "GET /world" with pattern 'hello {path} you really {method} me' would return: + * 'hello /world you really GET me' + */ + 'name_provider' => '{uri} {route}', + + /* + * Will cause an exception to be thrown if the NewRelic + * PHP agent is not found / installed + */ + 'throw_if_not_installed' => false, + +); diff --git a/config/poniverse.php b/config/poniverse.php new file mode 100644 index 00000000..15cab0bf --- /dev/null +++ b/config/poniverse.php @@ -0,0 +1,12 @@ + 1, + 'urls' => [ + 'api' => env('PONI_API_URL', 'https://api.poniverse.net/v1/'), + 'register' => env('PONI_REGISTER_URL', 'https://poniverse.net/register?site=pony.fm'), + 'auth' => env('PONI_AUTH_URL', 'https://poniverse.net/oauth/authorize'), + 'token' => env('PONI_TOKEN_URL', 'https://poniverse.net/oauth/access_token') + ], + 'client_id' => env('PONI_CLIENT_ID'), + 'secret' => env('PONI_CLIENT_SECRET') +]; diff --git a/config/ponyfm.php b/config/ponyfm.php new file mode 100644 index 00000000..e10a1967 --- /dev/null +++ b/config/ponyfm.php @@ -0,0 +1,31 @@ + env('PONYFM_DATASTORE'), + + /* + |-------------------------------------------------------------------------- + | Use sendfile? + |-------------------------------------------------------------------------- + | + | sendfile is a way of letting the web server serve files that aren't + | normally in its document root. If the web server is configured for it, + | use this setting - otherwise, track files and images will be served by + | the PHP process. + | + */ + + 'sendfile' => env('USE_SENDFILE', true), + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 00000000..cf9b09da --- /dev/null +++ b/config/queue.php @@ -0,0 +1,93 @@ + env('QUEUE_DRIVER', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'expire' => 60, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'ttr' => 60, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => 'your-public-key', + 'secret' => 'your-secret-key', + 'queue' => 'your-queue-url', + 'region' => 'us-east-1', + ], + + 'iron' => [ + 'driver' => 'iron', + 'host' => 'mq-aws-us-east-1.iron.io', + 'token' => 'your-token', + 'project' => 'your-project-id', + 'queue' => 'your-queue-name', + 'encrypt' => true, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => 'default', + 'expire' => 60, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'database' => 'mysql', 'table' => 'failed_jobs', + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 00000000..51abbbd1 --- /dev/null +++ b/config/services.php @@ -0,0 +1,38 @@ + [ + 'domain' => '', + 'secret' => '', + ], + + 'mandrill' => [ + 'secret' => '', + ], + + 'ses' => [ + 'key' => '', + 'secret' => '', + 'region' => 'us-east-1', + ], + + 'stripe' => [ + 'model' => App\User::class, + 'key' => '', + 'secret' => '', + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 00000000..e347e35b --- /dev/null +++ b/config/session.php @@ -0,0 +1,153 @@ + env('SESSION_DRIVER', 'database'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => 120, + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => null, + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => 'IfYouAreReadingThisWeWantToWorkWithYou_PleaseDropAnEmailTo_HelloAtPoniverseDotNet', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => null, + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you if it can not be done securely. + | + */ + + 'secure' => env('SESSION_HTTPS_ONLY', true), + +]; diff --git a/config/view.php b/config/view.php new file mode 100644 index 00000000..e193ab61 --- /dev/null +++ b/config/view.php @@ -0,0 +1,33 @@ + [ + realpath(base_path('resources/views')), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => realpath(storage_path('framework/views')), + +]; diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 00000000..9b1dffd9 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +*.sqlite diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php new file mode 100644 index 00000000..ae7165b8 --- /dev/null +++ b/database/factories/ModelFactory.php @@ -0,0 +1,21 @@ +define(App\User::class, function ($faker) { + return [ + 'name' => $faker->name, + 'email' => $faker->email, + 'password' => str_random(10), + 'remember_token' => str_random(10), + ]; +}); diff --git a/app/config/packages/.gitkeep b/database/migrations/.gitkeep similarity index 100% rename from app/config/packages/.gitkeep rename to database/migrations/.gitkeep diff --git a/database/migrations/2013_06_07_003952_create_users_table.php b/database/migrations/2013_06_07_003952_create_users_table.php new file mode 100644 index 00000000..cf866ee4 --- /dev/null +++ b/database/migrations/2013_06_07_003952_create_users_table.php @@ -0,0 +1,60 @@ +increments('id'); + $table->string('display_name', 255); + $table->string('mlpforums_name')->nullable(); + $table->boolean('sync_names')->default(true); + $table->string('email', 150)->indexed(); + $table->string('gravatar')->nullable(); + $table->string('slug'); + $table->boolean('uses_gravatar')->default(true); + $table->boolean('can_see_explicit_content'); + $table->text('bio'); + $table->integer('track_count')->unsigned(); + $table->integer('comment_count')->unsigned(); + $table->timestamps(); + }); + + Schema::create('roles', function ($table) { + $table->increments('id'); + $table->string('name'); + }); + + Schema::create('role_user', function ($table) { + $table->increments('id'); + $table->integer('user_id')->unsigned()->index(); + $table->integer('role_id')->unsigned()->index(); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users'); + $table->foreign('role_id')->references('id')->on('roles'); + }); + + Schema::create('cache', function ($table) { + $table->string('key')->index(); + $table->text('value'); + $table->integer('expiration')->unsigned()->index(); + }); + + DB::table('roles')->insert(['name' => 'super_admin']); + DB::table('roles')->insert(['name' => 'admin']); + DB::table('roles')->insert(['name' => 'moderator']); + DB::table('roles')->insert(['name' => 'user']); + } + + public function down() + { + Schema::drop('cache'); + Schema::drop('role_user'); + Schema::drop('roles'); + Schema::drop('users'); + } +} diff --git a/database/migrations/2013_06_27_015259_create_tracks_table.php b/database/migrations/2013_06_27_015259_create_tracks_table.php new file mode 100644 index 00000000..8f3fa5ce --- /dev/null +++ b/database/migrations/2013_06_27_015259_create_tracks_table.php @@ -0,0 +1,131 @@ +increments('id'); + $table->string('title', 100); + $table->text('description'); + $table->boolean('affiliate_distribution'); + $table->boolean('open_distribution'); + $table->boolean('remix'); + }); + + Schema::create('genres', function ($table) { + $table->increments('id'); + $table->string('name')->unique(); + $table->string('slug', 200)->index(); + }); + + Schema::create('track_types', function ($table) { + $table->increments('id'); + $table->string('title'); + $table->string('editor_title'); + }); + + Schema::create('tracks', function ($table) { + $table->increments('id'); + + $table->integer('user_id')->unsigned(); + $table->integer('license_id')->unsigned()->nullable()->default(null); + $table->integer('genre_id')->unsigned()->nullable()->index()->default(null); + $table->integer('track_type_id')->unsigned()->nullable()->default(null); + + $table->string('title', 100)->index(); + $table->string('slug', 200)->index(); + $table->text('description')->nullable(); + $table->text('lyrics')->nullable(); + $table->boolean('is_vocal'); + $table->boolean('is_explicit'); + $table->integer('cover_id')->unsigned()->nullable(); + $table->boolean('is_downloadable'); + $table->float('duration')->unsigned(); + + $table->integer('play_count')->unsigned(); + $table->integer('view_count')->unsigned(); + $table->integer('download_count')->unsigned(); + $table->integer('favourite_count')->unsigned(); + $table->integer('comment_count')->unsigned(); + + $table->timestamps(); + $table->timestamp('deleted_at')->nullable()->index(); + $table->timestamp('published_at')->nullable()->index(); + $table->timestamp('released_at')->nullable(); + + $table->foreign('user_id')->references('id')->on('users'); + $table->foreign('license_id')->references('id')->on('licenses'); + $table->foreign('genre_id')->references('id')->on('genres')->on_update('cascade'); + $table->foreign('track_type_id')->references('id')->on('track_types')->on_update('cascade'); + }); + + + DB::table('licenses')->insert([ + 'title' => 'Personal', + 'description' => 'Only you and Pony.fm are allowed to distribute and broadcast the track.', + 'affiliate_distribution' => 0, + 'open_distribution' => 0, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'title' => 'Broadcast', + 'description' => 'You, Pony.fm, and its affiliates may distribute and broadcast the track.', + 'affiliate_distribution' => 1, + 'open_distribution' => 0, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'title' => 'Open', + 'description' => 'Anyone is permitted to broadcast and distribute the song in its original form, with attribution to you.', + 'affiliate_distribution' => 1, + 'open_distribution' => 1, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'title' => 'Remix', + 'description' => 'Anyone is permitted to broadcast and distribute the song in any form, or create derivative works based on it for any purpose, with attribution to you.', + 'affiliate_distribution' => 1, + 'open_distribution' => 1, + 'remix' => 1 + ]); + + DB::table('track_types')->insert([ + 'title' => 'Original Song', + 'editor_title' => 'an original song' + ]); + + DB::table('track_types')->insert([ + 'title' => 'Official Song Remix', + 'editor_title' => 'a remix of an official song' + ]); + + DB::table('track_types')->insert([ + 'title' => 'Fan Song Remix', + 'editor_title' => 'a remix of a fan song' + ]); + + DB::table('track_types')->insert([ + 'title' => 'Ponified Song', + 'editor_title' => 'a non-pony song, turned pony' + ]); + + DB::table('track_types')->insert([ + 'title' => 'Official Show Audio Remix', + 'editor_title' => 'a remix of official show audio' + ]); + } + + public function down() + { + Schema::drop('tracks'); + Schema::drop('licenses'); + Schema::drop('track_types'); + Schema::drop('genres'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_07_26_230827_create_images_table.php b/database/migrations/2013_07_26_230827_create_images_table.php new file mode 100644 index 00000000..90851397 --- /dev/null +++ b/database/migrations/2013_07_26_230827_create_images_table.php @@ -0,0 +1,47 @@ +increments('id'); + $table->string('filename', 256); + $table->string('mime', 100); + $table->string('extension', 32); + $table->integer('size'); + $table->string('hash', 32); + $table->integer('uploaded_by')->unsigned(); + $table->timestamps(); + + $table->foreign('uploaded_by')->references('id')->on('users'); + }); + + Schema::table('users', function ($table) { + $table->integer('avatar_id')->unsigned()->nullable(); + $table->foreign('avatar_id')->references('id')->on('images'); + }); + + DB::table('tracks')->update(['cover_id' => null]); + + Schema::table('tracks', function ($table) { + $table->foreign('cover_id')->references('id')->on('images'); + }); + } + + public function down() + { + Schema::table('tracks', function ($table) { + $table->dropForeign('tracks_cover_id_foreign'); + }); + + Schema::table('users', function ($table) { + $table->dropForeign('users_avatar_id_foreign'); + $table->dropColumn('avatar_id'); + }); + + Schema::drop('images'); + } +} \ No newline at end of file diff --git a/app/database/migrations/2013_07_28_034328_create_songs_table.php b/database/migrations/2013_07_28_034328_create_songs_table.php similarity index 80% rename from app/database/migrations/2013_07_28_034328_create_songs_table.php rename to database/migrations/2013_07_28_034328_create_songs_table.php index 9b7e24f2..4ba519a0 100644 --- a/app/database/migrations/2013_07_28_034328_create_songs_table.php +++ b/database/migrations/2013_07_28_034328_create_songs_table.php @@ -2,28 +2,30 @@ use Illuminate\Database\Migrations\Migration; -class CreateSongsTable extends Migration { - public function up() { - Schema::create('show_songs', function($table) { - $table->increments('id'); - $table->string('title', 100); - $table->text('lyrics'); - $table->string('slug', 200)->indexed(); - }); +class CreateSongsTable extends Migration +{ + public function up() + { + Schema::create('show_songs', function ($table) { + $table->increments('id'); + $table->string('title', 100); + $table->text('lyrics'); + $table->string('slug', 200)->indexed(); + }); - Schema::create('show_song_track', function($table) { - $table->increments('id'); - $table->integer('track_id')->unsigned(); - $table->integer('show_song_id')->unsigned(); + Schema::create('show_song_track', function ($table) { + $table->increments('id'); + $table->integer('track_id')->unsigned(); + $table->integer('show_song_id')->unsigned(); - $table->foreign('track_id')->references('id')->on('tracks')->on_update('cascade'); - $table->foreign('show_song_id')->references('id')->on('show_songs')->on_update('cascade'); - }); + $table->foreign('track_id')->references('id')->on('tracks')->on_update('cascade'); + $table->foreign('show_song_id')->references('id')->on('show_songs')->on_update('cascade'); + }); - DB::table('show_songs')->insert([ - 'id' => 1, - 'title' => "Equestria Girls", - 'lyrics' => "[Pinkie Pie] + DB::table('show_songs')->insert([ + 'id' => 1, + 'title' => "Equestria Girls", + 'lyrics' => "[Pinkie Pie] Ooh! This is my jam! There is a place @@ -97,12 +99,12 @@ Aoaoah oh, aoaoaoh! Break it down, DJ Pon-3 These are the ponies I love the most I wish you could all be Equestria girls", - 'slug' => "equestria-girls", - ]); - DB::table('show_songs')->insert([ - 'id' => 2, - 'title' => "My Little Pony Theme Song", - 'lyrics' => "[Backup singer] + 'slug' => "equestria-girls", + ]); + DB::table('show_songs')->insert([ + 'id' => 2, + 'title' => "My Little Pony Theme Song", + 'lyrics' => "[Backup singer] My Little Pony, My Little Pony Ahh, ahh, ahh, ahhh….. @@ -132,12 +134,12 @@ It's an easy feat And magic makes it all complete You have my little ponies Do you know you're all my very best friends?", - 'slug' => "my-little-pony-theme-song", - ]); - DB::table('show_songs')->insert([ - 'id' => 3, - 'title' => "Laughter Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "my-little-pony-theme-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 3, + 'title' => "Laughter Song", + 'lyrics' => "[Pinkie Pie] When I was a little filly and the sun was going down... Twilight Sparkle: Tell me she's not... @@ -176,12 +178,12 @@ Snortle at the spooky And tell that big dumb scary face to take a hike and leave you alone and if he thinks he can scare you then he's got another thing coming and the very idea of such a thing just makes you wanna... hahahaha... heh... Laaaaaaauuugh!", - 'slug' => "laughter-song", - ]); -DB::table('show_songs')->insert([ - 'id' => 4, - 'title' => "Pinkie's Gala Fantasy Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "laughter-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 4, + 'title' => "Pinkie's Gala Fantasy Song", + 'lyrics' => "[Pinkie Pie] Oh the Grand Galloping Gala is the best place for me Oh the Grand Galloping Gala is the best place for me Hip hip @@ -197,12 +199,12 @@ Oh the Grand Galloping Gala is the best place for me 'Cause it's the most galarrific superly-terrific gala ever In the whole galaxy Wheee!", - 'slug' => "pinkies-gala-fantasy-song", -]); -DB::table('show_songs')->insert([ - 'id' => 5, - 'title' => "The Ticket Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "pinkies-gala-fantasy-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 5, + 'title' => "The Ticket Song", + 'lyrics' => "[Pinkie Pie] Twilight is my bestest friend Whoopie, whoopie! @@ -222,22 +224,22 @@ Twilight Sparkle: Pinkie! She'll give her extra ticket to the gala to me! Twilight Sparkle: PIIINKIIIE!!", - 'slug' => "the-ticket-song", -]); -DB::table('show_songs')->insert([ - 'id' => 6, - 'title' => "Junior Speedsters Chant", - 'lyrics' => "[Rainbow Dash/Gilda] + 'slug' => "the-ticket-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 6, + 'title' => "Junior Speedsters Chant", + 'lyrics' => "[Rainbow Dash/Gilda] Junior Speedsters are our lives, Sky-bound soars and daring dives Junior Speedsters, it's our quest, To some day be the very best!", - 'slug' => "junior-speedsters-chant", -]); -DB::table('show_songs')->insert([ - 'id' => 7, - 'title' => "Hop Skip and Jump song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "junior-speedsters-chant", + ]); + DB::table('show_songs')->insert([ + 'id' => 7, + 'title' => "Hop Skip and Jump song", + 'lyrics' => "[Pinkie Pie] It's not very far Just move your little rump You can make it if you try with a hop, skip and jump @@ -252,12 +254,12 @@ A hop, skip and jump, A hop, skip and jump, A hop skip and jump, A hop skip and jump!", - 'slug' => "hop-skip-and-jump-song", -]); -DB::table('show_songs')->insert([ - 'id' => 8, - 'title' => "Evil Enchantress song", - 'lyrics' => "[Pinkie Pie/Flutterguy] + 'slug' => "hop-skip-and-jump-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 8, + 'title' => "Evil Enchantress song", + 'lyrics' => "[Pinkie Pie/Flutterguy] She's an evil enchantress She does evil dances And if you look deep in her eyes @@ -267,12 +269,12 @@ She'll mix up an evil brew Then she'll gobble you up In a big tasty stew Soooo.... Watch out!", - 'slug' => "evil-enchantress-song", -]); -DB::table('show_songs')->insert([ - 'id' => 9, - 'title' => "Winter Wrap Up", - 'lyrics' => "[Rainbow Dash] + 'slug' => "evil-enchantress-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 9, + 'title' => "Winter Wrap Up", + 'lyrics' => "[Rainbow Dash] Three months of winter coolness And awesome holidays @@ -407,12 +409,12 @@ Winter Wrap Up! Winter Wrap Up! 'Cause tomorrow spring is here 'Cause tomorrow spring is here 'Cause tomorrow spring is here!", - 'slug' => "winter-wrap-up", -]); -DB::table('show_songs')->insert([ - 'id' => 10, - 'title' => "Cupcake Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "winter-wrap-up", + ]); + DB::table('show_songs')->insert([ + 'id' => 10, + 'title' => "Cupcake Song", + 'lyrics' => "[Pinkie Pie] All you have to do is take a cup of flour! Add it to the mix! Now just take a little something sweet, not sour! @@ -426,12 +428,12 @@ And you never get your fill of... Cupcakes! So sweet and tasty! Cupcakes! Don't be too hasty! Cupcakes! Cupcakes, cupcakes, CUPCAKES!", - 'slug' => "cupcake-song", -]); -DB::table('show_songs')->insert([ - 'id' => 11, - 'title' => "Art of the Dress", - 'lyrics' => "[Rarity] + 'slug' => "cupcake-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 11, + 'title' => "Art of the Dress", + 'lyrics' => "[Rarity] Thread by thread, stitching it together Twilight's dress, cutting out the pattern snip by snip Making sure the fabric folds nicely @@ -467,12 +469,12 @@ Croup, dock, haunch, shoulders, hip Thread by thread, primmed and pressed Yard by yard, never stressed And that's the art of the dress!", - 'slug' => "art-of-the-dress", -]); -DB::table('show_songs')->insert([ - 'id' => 12, - 'title' => "Hush Now Lullaby", - 'lyrics' => "[Fluttershy] + 'slug' => "art-of-the-dress", + ]); + DB::table('show_songs')->insert([ + 'id' => 12, + 'title' => "Hush Now Lullaby", + 'lyrics' => "[Fluttershy] Hush now, quiet now It's time to lay your sleepy head Hush now, quiet now @@ -502,12 +504,12 @@ Said hush now! Quiet now! It's time to go to BED! OW!", - 'slug' => "hush-now-lullaby", -]); -DB::table('show_songs')->insert([ - 'id' => 13, - 'title' => "Cutie Mark Crusaders Song", - 'lyrics' => "[Scootaloo] + 'slug' => "hush-now-lullaby", + ]); + DB::table('show_songs')->insert([ + 'id' => 13, + 'title' => "Cutie Mark Crusaders Song", + 'lyrics' => "[Scootaloo] Look, here, are three little ponies Ready to sing for this crowd Listen up, 'cause here's our story @@ -556,12 +558,12 @@ We are the Cutie Mark Crusaders On a quest to find out who we are And we will never stop the journey Not until we have our cutie marks!", - 'slug' => "cutie-mark-crusaders-song", -]); -DB::table('show_songs')->insert([ - 'id' => 14, - 'title' => "You Got to Share, You Got to Care", - 'lyrics' => "[Pinkie Pie] + 'slug' => "cutie-mark-crusaders-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 14, + 'title' => "You Got to Share, You Got to Care", + 'lyrics' => "[Pinkie Pie] We may be divided But of you all, I beg To remember we're all hoofed @@ -594,12 +596,12 @@ You gotta care It's the right thing to do And there'll always be a way Thro-o-o-o-ugh!", - 'slug' => "you-got-to-share-you-got-to-care", -]); -DB::table('show_songs')->insert([ - 'id' => 15, - 'title' => "So Many Wonders", - 'lyrics' => "[Fluttershy] + 'slug' => "you-got-to-share-you-got-to-care", + ]); + DB::table('show_songs')->insert([ + 'id' => 15, + 'title' => "So Many Wonders", + 'lyrics' => "[Fluttershy] What is this place filled with so many wonders? Casting its spell @@ -618,12 +620,12 @@ If I knew the ground had so much up its sleeve I'd have come here sooner, and never leave Yes, I love everythiiiiiiiiiiiing!", - 'slug' => "so-many-wonders", -]); -DB::table('show_songs')->insert([ - 'id' => 16, - 'title' => "Pinkie Pie's Singing Telegram", - 'lyrics' => "[Pinkie Pie] + 'slug' => "so-many-wonders", + ]); + DB::table('show_songs')->insert([ + 'id' => 16, + 'title' => "Pinkie Pie's Singing Telegram", + 'lyrics' => "[Pinkie Pie] This is your singing telegram I hope it finds you well You're invited to a party @@ -648,12 +650,12 @@ It won't be the same without you So we hope that you say yes So, please, oh please R.S.V.P And come, and be our guest!", - 'slug' => "pinkie-pies-singing-telegram", -]); -DB::table('show_songs')->insert([ - 'id' => 17, - 'title' => "At the Gala", - 'lyrics' => "Twilight Sparkle: I can't believe we're finally here. With all that we've imagined, the reality of this night is sure to make this... The Best Night Ever! + 'slug' => "pinkie-pies-singing-telegram", + ]); + DB::table('show_songs')->insert([ + 'id' => 17, + 'title' => "At the Gala", + 'lyrics' => "Twilight Sparkle: I can't believe we're finally here. With all that we've imagined, the reality of this night is sure to make this... The Best Night Ever! At the Gala @@ -763,12 +765,12 @@ Twilight Sparkle: To talk! Into the Gala, into the Gala! And we'll have the best night ever! At the Gala!", - 'slug' => "at-the-gala", -]); -DB::table('show_songs')->insert([ - 'id' => 18, - 'title' => "I'm at the Grand Galloping Gala", - 'lyrics' => "[Pinkie Pie] + 'slug' => "at-the-gala", + ]); + DB::table('show_songs')->insert([ + 'id' => 18, + 'title' => "I'm at the Grand Galloping Gala", + 'lyrics' => "[Pinkie Pie] I'm at the Grand Galloping Gala, I'm at the Grand Galloping Gala, I'm at the Grand Galloping Gala, @@ -780,12 +782,12 @@ I'm at the Grand Galloping GalaaaaaaaaaaAAAAAAAAAAAA! [pause] It's all I ever... dreamed?", - 'slug' => "im-at-the-grand-galloping-gala", -]); -DB::table('show_songs')->insert([ - 'id' => 19, - 'title' => "Pony Pokey", - 'lyrics' => "[Pinkie] + 'slug' => "im-at-the-grand-galloping-gala", + ]); + DB::table('show_songs')->insert([ + 'id' => 19, + 'title' => "Pony Pokey", + 'lyrics' => "[Pinkie] You reach your right hoof in You reach your right hoof out You reach your right hoof in @@ -830,12 +832,12 @@ You do the Pony Pokey And that's what it's all about Yeah!", - 'slug' => "pony-pokey", -]); -DB::table('show_songs')->insert([ - 'id' => 20, - 'title' => "Find A Pet Song", - 'lyrics' => "[Fluttershy] + 'slug' => "pony-pokey", + ]); + DB::table('show_songs')->insert([ + 'id' => 20, + 'title' => "Find A Pet Song", + 'lyrics' => "[Fluttershy] Now, Rainbow, my dear, I cannot express my delight It's abundantly clear That somewhere out here @@ -969,12 +971,12 @@ May the games Begin Rainbow Dash: And may the best pet win!", - 'slug' => "find-a-pet-song", -]); -DB::table('show_songs')->insert([ - 'id' => 21, - 'title' => "Becoming Popular (The Pony Everypony Should Know)", - 'lyrics' => "[Rarity] + 'slug' => "find-a-pet-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 21, + 'title' => "Becoming Popular (The Pony Everypony Should Know)", + 'lyrics' => "[Rarity] I'll be the toast of the town, the girl on the go I'm the type of pony everypony, everypony should know @@ -998,44 +1000,44 @@ I'm the type of pony everypony, everypony should know Because I'm the type of pony Yes, I'm the type of pony Yes, I'm the type of pony everypony should know", - 'slug' => "becoming-popular-the-pony-everypony-should-know", -]); -DB::table('show_songs')->insert([ - 'id' => 22, - 'title' => "The Heart Carol", - 'lyrics' => "[Choir] + 'slug' => "becoming-popular-the-pony-everypony-should-know", + ]); + DB::table('show_songs')->insert([ + 'id' => 22, + 'title' => "The Heart Carol", + 'lyrics' => "[Choir] The fire of friendship lives in our hearts As long as it burns we cannot drift apart Though quarrels arise, their numbers are few Laughter and singing will see us through (will see us through) We are a circle of pony friends A circle of friends we'll be to the very end", - 'slug' => "the-heart-carol", -]); -DB::table('show_songs')->insert([ - 'id' => 23, - 'title' => "Happy Monthiversary", - 'lyrics' => "[Pinkie Pie] + 'slug' => "the-heart-carol", + ]); + DB::table('show_songs')->insert([ + 'id' => 23, + 'title' => "Happy Monthiversary", + 'lyrics' => "[Pinkie Pie] Happy monthiversary to you and you today [very quickly] I can't believe you're already a month old time sure flies doesn't it well it seems like only yesterday you were born. But now you're a month old today, hey!", - 'slug' => "happy-monthiversary", -]); -DB::table('show_songs')->insert([ - 'id' => 24, - 'title' => "Piggy Dance", - 'lyrics' => "[Pinkie Pie] + 'slug' => "happy-monthiversary", + ]); + DB::table('show_songs')->insert([ + 'id' => 24, + 'title' => "Piggy Dance", + 'lyrics' => "[Pinkie Pie] First you jiggle your tail! Oink oink oink! Then you wriggle your snout! Oink oink oink! Then you wiggle your rump! Oink oink oink! Then shout it out! Oink oink oink! [repeat verse two more times]", - 'slug' => "piggy-dance", -]); -DB::table('show_songs')->insert([ - 'id' => 25, - 'title' => "The Flim Flam Brothers", - 'lyrics' => "[Flim] + 'slug' => "piggy-dance", + ]); + DB::table('show_songs')->insert([ + 'id' => 25, + 'title' => "The Flim Flam Brothers", + 'lyrics' => "[Flim] Well, lookie what we got here, brother of mine, it's the same in every town Ponies with thirsty throats, dry tongues, and not a drop of cider to be found Maybe they're not aware that there's really no need for this teary despair @@ -1195,12 +1197,12 @@ Traveling salesponies nonpareil [Flim and Flam] Yeah!", - 'slug' => "the-flim-flam-brothers", -]); -DB::table('show_songs')->insert([ - 'id' => 26, - 'title' => "The Perfect Stallion", - 'lyrics' => "[Sweetie Belle] + 'slug' => "the-flim-flam-brothers", + ]); + DB::table('show_songs')->insert([ + 'id' => 26, + 'title' => "The Perfect Stallion", + 'lyrics' => "[Sweetie Belle] Cheerilee is sweet and kind. She's the best teacher we could hope for. The perfect stallion you and I must find. @@ -1278,12 +1280,12 @@ We did it girls. We've found the one. Who will send our teacher's heart aflutter. Apple Bloom: Wait a minute. Let me get this straight. Are you talking about my brother?", - 'slug' => "the-perfect-stallion", -]); -DB::table('show_songs')->insert([ - 'id' => 27, - 'title' => "Smile Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "the-perfect-stallion", + ]); + DB::table('show_songs')->insert([ + 'id' => 27, + 'title' => "Smile Song", + 'lyrics' => "[Pinkie Pie] My name is Pinkie Pie (Hello!) And I am here to say (How ya doin'?) I'm gonna make you smile, and I will brighten up your day-aaay! @@ -1354,21 +1356,21 @@ Smile, smile, smile, smile, smile! [Pinkie Pie] Come on and smile Come on and smile!", - 'slug' => "smile-song", -]); -DB::table('show_songs')->insert([ - 'id' => 28, - 'title' => "Cranky Doodle Donkey", - 'lyrics' => "[Pinkie Pie] + 'slug' => "smile-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 28, + 'title' => "Cranky Doodle Donkey", + 'lyrics' => "[Pinkie Pie] You're a Cranky Doodle Donkey guy. A Cranky Doodle Donkey. I never met you but you're my new friend and I'm your best friend Pinkie Pie!", - 'slug' => "cranky-doodle-donkey", -]); -DB::table('show_songs')->insert([ - 'id' => 29, - 'title' => "Welcome Song", - 'lyrics' => "[Pinkie Pie] + 'slug' => "cranky-doodle-donkey", + ]); + DB::table('show_songs')->insert([ + 'id' => 29, + 'title' => "Welcome Song", + 'lyrics' => "[Pinkie Pie] Welcome welcome welcome A fine welcome to you Welcome welcome welcome @@ -1379,12 +1381,12 @@ Welcome welcome welcome To Ponyville today Pinkie Pie: Wait for it!", - 'slug' => "welcome-song", -]); -DB::table('show_songs')->insert([ - 'id' => 30, - 'title' => "Cranky Doodle Joy", - 'lyrics' => "[Pinkie Pie] + 'slug' => "welcome-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 30, + 'title' => "Cranky Doodle Joy", + 'lyrics' => "[Pinkie Pie] He had a Cranky Doodle sweetheart She's his cranky doodle joy I helped the Cranky Doodle boy, yeah! @@ -1392,12 +1394,12 @@ I helped the Cranky Doodle boy! Cranky Doodle Donkey and Matilda: Pinkie! Pinkie Pie: Whoops, privacy. Sorry.", - 'slug' => "cranky-doodle-joy", -]); -DB::table('show_songs')->insert([ - 'id' => 31, - 'title' => "Big Brother Best Friend Forever (B.B.B.F.F.)", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "cranky-doodle-joy", + ]); + DB::table('show_songs')->insert([ + 'id' => 31, + 'title' => "Big Brother Best Friend Forever (B.B.B.F.F.)", + 'lyrics' => "[Twilight Sparkle] When I was just a filly, I found it rather silly To see how many other ponies I could meet I had my books to read, didn't know that I would ever need @@ -1424,12 +1426,12 @@ I hoped that he would stay My big brother best friend Forever... Forever...", - 'slug' => "big-brother-best-friend-forever-bbbff", -]); -DB::table('show_songs')->insert([ - 'id' => 32, - 'title' => "This Day Aria", - 'lyrics' => "[Queen Chrysalis] + 'slug' => "big-brother-best-friend-forever-bbbff", + ]); + DB::table('show_songs')->insert([ + 'id' => 32, + 'title' => "This Day Aria", + 'lyrics' => "[Queen Chrysalis] This day is going to be perfect The kind of day of which I've dreamed since I was small Everypony will gather 'round @@ -1475,12 +1477,12 @@ He'll end up marrying a fake Shining Armor will be [Queen Chrysalis]: ...mine, all mine. [evil laugh]", - 'slug' => "this-day-aria", - ]); -DB::table('show_songs')->insert([ - 'id' => 33, - 'title' => "Love Is In Bloom", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "this-day-aria", + ]); + DB::table('show_songs')->insert([ + 'id' => 33, + 'title' => "Love Is In Bloom", + 'lyrics' => "[Twilight Sparkle] Love is in bloom A beautiful bride, a handsome groom, Two hearts becoming one @@ -1502,12 +1504,12 @@ A beautiful bride, a handsome groom I said love is in bloom You're starting a life and making room For us, (For us... For us...Aah...)", - 'slug' => "love-is-in-bloom", - ]); -DB::table('show_songs')->insert([ - 'id' => 34, - 'title' => "The Failure Song", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "love-is-in-bloom", + ]); + DB::table('show_songs')->insert([ + 'id' => 34, + 'title' => "The Failure Song", + 'lyrics' => "[Twilight Sparkle] I was prepared to do my best Thought I could handle any test For I can do so many tricks @@ -1554,12 +1556,12 @@ No I wasn't [Twilight Sparkle and Spike] Prepared... for this!", - 'slug' => "the-failure-song", - ]); -DB::table('show_songs')->insert([ - 'id' => 35, - 'title' => "The Ballad of the Crystal Empire", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "the-failure-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 35, + 'title' => "The Ballad of the Crystal Empire", + 'lyrics' => "[Twilight Sparkle] Princess Cadence needs our help Her magic will not last forever I think we can do it @@ -1597,12 +1599,12 @@ Can you learn it in a day? Oh, we have to get this right Yes we have to make them see We can save the Crystal Ponies... with their history!", - 'slug' => "the-ballad-of-the-crystal-empire", - ]); -DB::table('show_songs')->insert([ - 'id' => 36, - 'title' => "The Success Song", - 'lyrics' => "[Rarity] + 'slug' => "the-ballad-of-the-crystal-empire", + ]); + DB::table('show_songs')->insert([ + 'id' => 36, + 'title' => "The Success Song", + 'lyrics' => "[Rarity] You were prepared to do your best Had what it takes to pass the test All those doubts you can dismiss @@ -1644,12 +1646,12 @@ Turns out you were [Spike, Applejack, Rainbow Dash, Rarity, Pinkie Pie, Fluttershy, and Twilight Sparkle] Prepared... for this!", - 'slug' => "the-success-song", - ]); -DB::table('show_songs')->insert([ - 'id' => 37, - 'title' => "Babs Seed", - 'lyrics' => "[Cutie Mark Crusaders] + 'slug' => "the-success-song", + ]); + DB::table('show_songs')->insert([ + 'id' => 37, + 'title' => "Babs Seed", + 'lyrics' => "[Cutie Mark Crusaders] Yeah, yeah, yeah Yeah, yeah, yeah Yeah, yeah, yeah, yeah, yeah @@ -1708,12 +1710,12 @@ Babs Seed, Babs Seed- [Scootaloo] She's just a bad, bad seed", - 'slug' => "babs-seed", - ]); -DB::table('show_songs')->insert([ - 'id' => 38, - 'title' => "Raise This Barn", - 'lyrics' => "[Applejack] + 'slug' => "babs-seed", + ]); + DB::table('show_songs')->insert([ + 'id' => 38, + 'title' => "Raise This Barn", + 'lyrics' => "[Applejack] Yee-hoo! Raise this barn, raise this barn @@ -1803,12 +1805,12 @@ All we need to strive to be Is part of the Apple family Apple Bloom: Yeah!", - 'slug' => "raise-this-barn", - ]); -DB::table('show_songs')->insert([ - 'id' => 39, - 'title' => "Morning in Ponyville", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "raise-this-barn", + ]); + DB::table('show_songs')->insert([ + 'id' => 39, + 'title' => "Morning in Ponyville", + 'lyrics' => "[Twilight Sparkle] Morning in Ponyville shimmers Morning in Ponyville shines And I know for absolute certain @@ -1828,12 +1830,12 @@ Morning in Ponyville shimmers Morning in Ponyville shines And I know for absolute certain That everything is certainly...", - 'slug' => "morning-in-ponyville", - ]); -DB::table('show_songs')->insert([ - 'id' => 40, - 'title' => "What My Cutie Mark Is Telling Me", - 'lyrics' => "[Rainbow Dash] + 'slug' => "morning-in-ponyville", + ]); + DB::table('show_songs')->insert([ + 'id' => 40, + 'title' => "What My Cutie Mark Is Telling Me", + 'lyrics' => "[Rainbow Dash] These animals don't listen, no, not one little bit They run around out of control and throw their hissy fits It's up to me to stop them, 'cause plainly you can see @@ -1880,12 +1882,12 @@ It's what my cutie mark [All] Yes, it's what my cutie mark is telling me!", - 'slug' => "what-my-cutie-mark-is-telling-me", - ]); -DB::table('show_songs')->insert([ - 'id' => 41, - 'title' => "I've Got to Find a Way", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "what-my-cutie-mark-is-telling-me", + ]); + DB::table('show_songs')->insert([ + 'id' => 41, + 'title' => "I've Got to Find a Way", + 'lyrics' => "[Twilight Sparkle] I have to find a way To make this all okay I can't believe this small mistake @@ -1899,12 +1901,12 @@ I don't know what to do I fear I won't get through to you Oh why, oh why", - 'slug' => "ive-got-to-find-a-way", - ]); -DB::table('show_songs')->insert([ - 'id' => 42, - 'title' => "A True, True Friend", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "ive-got-to-find-a-way", + ]); + DB::table('show_songs')->insert([ + 'id' => 42, + 'title' => "A True, True Friend", + 'lyrics' => "[Twilight Sparkle] A true, true friend helps a friend in need A friend will be there to help them see @@ -1982,12 +1984,12 @@ A true, true friend helps a friend in need To see the light (to see the light) That shines (that shines) From a true, true friend!", - 'slug' => "a-true-true-friend", - ]); -DB::table('show_songs')->insert([ - 'id' => 43, - 'title' => "Celestia's Ballad", - 'lyrics' => "[Princess Celestia] + 'slug' => "a-true-true-friend", + ]); + DB::table('show_songs')->insert([ + 'id' => 43, + 'title' => "Celestia's Ballad", + 'lyrics' => "[Princess Celestia] You've come such a long, long way And I've watched you from that very first day To see how you might grow @@ -2001,12 +2003,12 @@ To go where you will go To see what you will see To find what you will be For it's time for you to fulfill your destiny", - 'slug' => "celestias-ballad", - ]); -DB::table('show_songs')->insert([ - 'id' => 44, - 'title' => "Behold, Princess Twilight Sparkle", - 'lyrics' => "[Choir] + 'slug' => "celestias-ballad", + ]); + DB::table('show_songs')->insert([ + 'id' => 44, + 'title' => "Behold, Princess Twilight Sparkle", + 'lyrics' => "[Choir] Thou Princess Twilight cometh Behold, behold A Princess here before us @@ -2017,12 +2019,12 @@ The Princess Twilight cometh Behold, behold (behold, behold) The Princess is The Princess is here", - 'slug' => "behold-princess-twilight-sparkle", - ]); -DB::table('show_songs')->insert([ - 'id' => 45, - 'title' => "Life in Equestria", - 'lyrics' => "[Twilight Sparkle] + 'slug' => "behold-princess-twilight-sparkle", + ]); + DB::table('show_songs')->insert([ + 'id' => 45, + 'title' => "Life in Equestria", + 'lyrics' => "[Twilight Sparkle] Life in Equestria shimmers Life in Equestria shines And I know for absolute certain @@ -2034,17 +2036,18 @@ Yes, everything is certainly fine It’s fine Twilight Sparkle: Yes! Everything’s going to be just fine!", - 'slug' => "life-in-equestria", - ]); - } + 'slug' => "life-in-equestria", + ]); + } - public function down() { - Schema::table('show_song_track', function($table){ - $table->dropForeign('show_song_track_track_id_foreign'); - $table->dropForeign('show_song_track_show_song_id_foreign'); - }); + public function down() + { + Schema::table('show_song_track', function ($table) { + $table->dropForeign('show_song_track_track_id_foreign'); + $table->dropForeign('show_song_track_show_song_id_foreign'); + }); - Schema::drop('show_song_track'); - Schema::drop('show_songs'); - } + Schema::drop('show_song_track'); + Schema::drop('show_songs'); + } } \ No newline at end of file diff --git a/database/migrations/2013_07_28_060804_create_albums.php b/database/migrations/2013_07_28_060804_create_albums.php new file mode 100644 index 00000000..4cba16c3 --- /dev/null +++ b/database/migrations/2013_07_28_060804_create_albums.php @@ -0,0 +1,48 @@ +increments('id'); + $table->integer('user_id')->unsigned(); + $table->string('title')->index(); + $table->string('slug')->index(); + $table->text('description'); + $table->integer('cover_id')->unsigned()->nullable(); + + $table->integer('track_count')->unsigned(); + $table->integer('view_count')->unsigned(); + $table->integer('download_count')->unsigned(); + $table->integer('favourite_count')->unsigned(); + $table->integer('comment_count')->unsigned(); + + $table->timestamps(); + $table->timestamp('deleted_at')->nullable()->index(); + + $table->foreign('cover_id')->references('id')->on('images'); + $table->foreign('user_id')->references('id')->on('users'); + }); + + Schema::table('tracks', function ($table) { + $table->integer('album_id')->unsigned()->nullable(); + $table->integer('track_number')->unsigned()->nullable(); + + $table->foreign('album_id')->references('id')->on('albums'); + }); + } + + public function down() + { + Schema::table('tracks', function ($table) { + $table->dropForeign('tracks_album_id_foreign'); + $table->dropColumn('album_id'); + $table->dropColumn('track_number'); + }); + + Schema::drop('albums'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_07_28_135136_create_playlists.php b/database/migrations/2013_07_28_135136_create_playlists.php new file mode 100644 index 00000000..c07ef855 --- /dev/null +++ b/database/migrations/2013_07_28_135136_create_playlists.php @@ -0,0 +1,70 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + $table->string('title'); + $table->string('slug'); + $table->text('description'); + $table->boolean('is_public'); + + $table->integer('track_count')->unsigned(); + $table->integer('view_count')->unsigned(); + $table->integer('download_count')->unsigned(); + $table->integer('favourite_count')->unsigned(); + $table->integer('follow_count')->unsigned(); + $table->integer('comment_count')->unsigned(); + + $table->timestamps(); + $table->date('deleted_at')->nullable()->index(); + + $table->foreign('user_id')->references('id')->on('users')->on_update('cascade'); + }); + + Schema::create('playlist_track', function ($table) { + $table->increments('id'); + $table->timestamps(); + $table->integer('playlist_id')->unsigned()->index(); + $table->integer('track_id')->unsigned()->index(); + $table->integer('position')->unsigned(); + + $table->foreign('playlist_id')->references('id')->on('playlists')->on_update('cascade')->on_delete('cascade'); + $table->foreign('track_id')->references('id')->on('tracks')->on_update('cascade'); + }); + + Schema::create('pinned_playlists', function ($table) { + $table->increments('id'); + $table->integer('user_id')->unsigned()->index(); + $table->integer('playlist_id')->unsigned()->index(); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->on_update('cascade'); + $table->foreign('playlist_id')->references('id')->on('playlists')->on_update('cascade'); + }); + } + + public function down() + { + Schema::table('playlist_track', function ($table) { + $table->dropForeign('playlist_track_playlist_id_foreign'); + $table->dropForeign('playlist_track_track_id_foreign'); + }); + + Schema::drop('playlist_track'); + + Schema::drop('pinned_playlists'); + + Schema::table('playlists', function ($table) { + $table->dropForeign('playlists_user_id_foreign'); + }); + + Schema::drop('playlists'); + } + +} \ No newline at end of file diff --git a/database/migrations/2013_08_01_051337_create_comments.php b/database/migrations/2013_08_01_051337_create_comments.php new file mode 100644 index 00000000..b9a570ff --- /dev/null +++ b/database/migrations/2013_08_01_051337_create_comments.php @@ -0,0 +1,41 @@ +increments('id'); + $table->integer('user_id')->unsigned(); + $table->string('ip_address', 46); + $table->text('content'); + + $table->timestamps(); + $table->timestamp('deleted_at')->nullable()->index(); + + $table->integer('profile_id')->unsigned()->nullable()->index(); + $table->integer('track_id')->unsigned()->nullable()->index(); + $table->integer('album_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + + $table->foreign('profile_id')->references('id')->on('users'); + $table->foreign('user_id')->references('id')->on('users'); + $table->foreign('track_id')->references('id')->on('tracks'); + $table->foreign('album_id')->references('id')->on('albums'); + $table->foreign('playlist_id')->references('id')->on('playlists'); + }); + } + + public function down() + { + Schema::table('comments', function ($table) { + $table->dropForeign('comments_user_id_foreign'); + $table->dropForeign('comments_track_id_foreign'); + $table->dropForeign('comments_album_id_foreign'); + $table->dropForeign('comments_playlist_id_foreign'); + }); + Schema::drop('comments'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_08_18_041928_create_user_tables.php b/database/migrations/2013_08_18_041928_create_user_tables.php new file mode 100644 index 00000000..2b83c0db --- /dev/null +++ b/database/migrations/2013_08_18_041928_create_user_tables.php @@ -0,0 +1,60 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + + $table->integer('track_id')->unsigned()->nullable()->index(); + $table->integer('album_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + $table->integer('artist_id')->unsigned()->nullable()->index(); + + $table->boolean('is_followed'); + $table->boolean('is_favourited'); + $table->boolean('is_pinned'); + + $table->integer('view_count'); + $table->integer('play_count'); + $table->integer('download_count'); + + $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('track_id')->references('id')->on('tracks')->on_delete('cascade');; + $table->foreign('album_id')->references('id')->on('albums')->on_delete('cascade');; + $table->foreign('playlist_id')->references('id')->on('playlists')->on_delete('cascade');; + + $table->unique(['user_id', 'track_id', 'album_id', 'playlist_id', 'artist_id'], 'resource_unique'); + }); + + Schema::create('resource_log_items', function ($table) { + $table->increments('id'); + $table->integer('user_id')->unsigned()->nullable()->index(); + $table->integer('log_type')->unsigned(); + $table->string('ip_address', 46)->index(); + $table->integer('track_format_id')->unsigned()->nullable(); + + $table->integer('track_id')->unsigned()->nullable()->index(); + $table->integer('album_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + + $table->timestamp('created_at'); + + $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('track_id')->references('id')->on('tracks'); + $table->foreign('album_id')->references('id')->on('albums'); + $table->foreign('playlist_id')->references('id')->on('playlists'); + }); + } + + public function down() + { + Schema::drop('resource_users'); + Schema::drop('resource_log_items'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_08_18_045248_create_favourites.php b/database/migrations/2013_08_18_045248_create_favourites.php new file mode 100644 index 00000000..7aea2c8a --- /dev/null +++ b/database/migrations/2013_08_18_045248_create_favourites.php @@ -0,0 +1,37 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + + $table->integer('track_id')->unsigned()->nullable()->index(); + $table->integer('album_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + + $table->timestamp('created_at'); + + $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('track_id')->references('id')->on('tracks'); + $table->foreign('album_id')->references('id')->on('albums'); + $table->foreign('playlist_id')->references('id')->on('playlists'); + }); + } + + public function down() + { + Schema::table('favourites', function ($table) { + $table->dropForeign('favourites_user_id_foreign'); + $table->dropForeign('favourites_track_id_foreign'); + $table->dropForeign('favourites_album_id_foreign'); + $table->dropForeign('favourites_playlist_id_foreign'); + }); + + Schema::drop('favourites'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_08_29_025516_create_followers.php b/database/migrations/2013_08_29_025516_create_followers.php new file mode 100644 index 00000000..7ff0c76b --- /dev/null +++ b/database/migrations/2013_08_29_025516_create_followers.php @@ -0,0 +1,28 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + + $table->integer('artist_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + + $table->timestamp('created_at'); + + $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('playlist_id')->references('id')->on('playlists'); + }); + } + + public function down() + { + Schema::drop('followers'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_09_01_025031_oauth.php b/database/migrations/2013_09_01_025031_oauth.php new file mode 100644 index 00000000..9d97cad5 --- /dev/null +++ b/database/migrations/2013_09_01_025031_oauth.php @@ -0,0 +1,25 @@ +increments('id'); + $table->integer('user_id'); + $table->integer('external_user_id'); + $table->text('access_token'); + $table->timestamp('expires'); + $table->text('refresh_token'); + $table->string('type'); + $table->string('service'); + }); + } + + public function down() + { + Schema::drop('oauth2_tokens'); + } +} \ No newline at end of file diff --git a/database/migrations/2013_09_01_232520_create_news_table.php b/database/migrations/2013_09_01_232520_create_news_table.php new file mode 100644 index 00000000..179a42b9 --- /dev/null +++ b/database/migrations/2013_09_01_232520_create_news_table.php @@ -0,0 +1,24 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + $table->string('post_hash', 32)->index(); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + } + + public function down() + { + Schema::drop('news'); + } + +} \ No newline at end of file diff --git a/app/database/migrations/2013_09_10_014644_create_latest_column.php b/database/migrations/2013_09_10_014644_create_latest_column.php similarity index 51% rename from app/database/migrations/2013_09_10_014644_create_latest_column.php rename to database/migrations/2013_09_10_014644_create_latest_column.php index 38b8e6c7..d76b3b1c 100644 --- a/app/database/migrations/2013_09_10_014644_create_latest_column.php +++ b/database/migrations/2013_09_10_014644_create_latest_column.php @@ -2,13 +2,15 @@ use Illuminate\Database\Migrations\Migration; -class CreateLatestColumn extends Migration { - public function up() { - Schema::table('tracks', function($table) { - $table->boolean('is_latest')->notNullable()->indexed(); - }); +class CreateLatestColumn extends Migration +{ + public function up() + { + Schema::table('tracks', function ($table) { + $table->boolean('is_latest')->notNullable()->indexed(); + }); - DB::update(' + DB::update(' UPDATE tracks SET @@ -27,11 +29,12 @@ class CreateLatestColumn extends Migration { ) = tracks.id AND published_at IS NOT NULL'); - } + } - public function down() { - Schema::table('tracks', function($table) { - $table->dropColumn('is_latest'); - }); - } + public function down() + { + Schema::table('tracks', function ($table) { + $table->dropColumn('is_latest'); + }); + } } \ No newline at end of file diff --git a/database/migrations/2013_09_23_031316_create_track_hashes.php b/database/migrations/2013_09_23_031316_create_track_hashes.php new file mode 100644 index 00000000..6fe14832 --- /dev/null +++ b/database/migrations/2013_09_23_031316_create_track_hashes.php @@ -0,0 +1,26 @@ +string('hash', 32)->notNullable()->indexed(); + }); + + foreach (Track::with('user')->get() as $track) { + $track->updateHash(); + $track->save(); + } + } + + public function down() + { + Schema::table('tracks', function ($table) { + $table->dropColumn('hash'); + }); + } +} \ No newline at end of file diff --git a/database/migrations/2013_09_24_055911_track_is_listed.php b/database/migrations/2013_09_24_055911_track_is_listed.php new file mode 100644 index 00000000..25d8caa8 --- /dev/null +++ b/database/migrations/2013_09_24_055911_track_is_listed.php @@ -0,0 +1,26 @@ +boolean('is_listed')->notNullable()->indexed(); + }); + + DB::update(' + UPDATE + tracks + SET + is_listed = true'); + } + + public function down() + { + Schema::table('tracks', function ($table) { + $table->dropColumn('is_listed'); + }); + } +} \ No newline at end of file diff --git a/database/migrations/2014_05_28_071738_update_track_hash.php b/database/migrations/2014_05_28_071738_update_track_hash.php new file mode 100644 index 00000000..6f2d43bb --- /dev/null +++ b/database/migrations/2014_05_28_071738_update_track_hash.php @@ -0,0 +1,19 @@ +get() as $track) { + $track->updateHash(); + $track->save(); + } + } + + public function down() + { + } +} \ No newline at end of file diff --git a/database/migrations/2015_04_30_064436_add_remember_me_field.php b/database/migrations/2015_04_30_064436_add_remember_me_field.php new file mode 100644 index 00000000..00f2b6f0 --- /dev/null +++ b/database/migrations/2015_04_30_064436_add_remember_me_field.php @@ -0,0 +1,20 @@ +string('remember_token', 100)->nullable()->indexed(); + }); + } + + public function down() + { + Schema::table('users', function ($table) { + $table->dropColumn('remember_token'); + }); + } +} \ No newline at end of file diff --git a/database/migrations/2015_05_20_155236_add_archived_profile_field.php b/database/migrations/2015_05_20_155236_add_archived_profile_field.php new file mode 100644 index 00000000..6fe301af --- /dev/null +++ b/database/migrations/2015_05_20_155236_add_archived_profile_field.php @@ -0,0 +1,32 @@ +boolean('is_archived')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function ($table) { + $table->dropColumn('is_archived'); + }); + } + +} \ No newline at end of file diff --git a/database/migrations/2015_05_25_011121_create_track_files_table.php b/database/migrations/2015_05_25_011121_create_track_files_table.php new file mode 100644 index 00000000..6ac15cd3 --- /dev/null +++ b/database/migrations/2015_05_25_011121_create_track_files_table.php @@ -0,0 +1,55 @@ +increments('id'); + $table->integer('track_id')->unsigned()->indexed(); + $table->boolean('is_master')->default(false)->indexed(); + $table->string('format')->indexed(); + + $table->foreign('track_id')->references('id')->on('tracks'); + $table->timestamps(); + }); + + foreach (Track::all() as $track) { + foreach (Track::$Formats as $name => $item) { + DB::table('track_files')->insert( + [ + 'track_id' => $track->id, + 'is_master' => $name === 'FLAC' ? true : false, + 'format' => $name, + 'created_at' => $track->created_at, + 'updated_at' => Carbon\Carbon::now() + ] + ); + } + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('track_files'); + } + +} \ No newline at end of file diff --git a/database/migrations/2015_09_10_105709_make_email_nullable.php b/database/migrations/2015_09_10_105709_make_email_nullable.php new file mode 100644 index 00000000..302611eb --- /dev/null +++ b/database/migrations/2015_09_10_105709_make_email_nullable.php @@ -0,0 +1,27 @@ +index('hash'); + }); + + Schema::table('track_files', function ($table) { + $table->index('is_master'); + $table->index('format'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + DB::statement('ALTER TABLE `show_songs` DROP INDEX show_songs_title_fulltext'); + + Schema::table('images', function ($table) { + $table->dropIndex('images_hash_index'); + }); + + Schema::table('track_files', function ($table) { + $table->dropIndex('track_files_is_master_index'); + $table->dropIndex('track_files_format_index'); + }); + } +} diff --git a/database/migrations/2015_09_10_105956_create_mlpma_table.php b/database/migrations/2015_09_10_105956_create_mlpma_table.php new file mode 100644 index 00000000..806a317a --- /dev/null +++ b/database/migrations/2015_09_10_105956_create_mlpma_table.php @@ -0,0 +1,38 @@ +increments('id'); + $table->integer('track_id')->unsigned()->index(); + $table->string('path')->index(); + $table->string('filename')->index(); + $table->string('extension')->index(); + $table->dateTime('imported_at'); + $table->longText('parsed_tags'); + $table->longText('raw_tags'); + + $table->foreign('track_id')->references('id')->on('tracks'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('mlpma_tracks'); + } +} diff --git a/database/migrations/2015_09_12_225021_create_session_table.php b/database/migrations/2015_09_12_225021_create_session_table.php new file mode 100644 index 00000000..ab28f1ab --- /dev/null +++ b/database/migrations/2015_09_12_225021_create_session_table.php @@ -0,0 +1,31 @@ +string('id')->unique(); + $table->text('payload'); + $table->integer('last_activity'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('sessions'); + } +} diff --git a/app/database/migrations/.gitkeep b/database/seeds/.gitkeep similarity index 100% rename from app/database/migrations/.gitkeep rename to database/seeds/.gitkeep diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php new file mode 100644 index 00000000..988ea210 --- /dev/null +++ b/database/seeds/DatabaseSeeder.php @@ -0,0 +1,21 @@ +call(UserTableSeeder::class); + + Model::reguard(); + } +} diff --git a/gulpfile.js b/gulpfile.js index cdf1e55e..d655858d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,176 +3,176 @@ var gulp = require("gulp"), argv = require("yargs").argv; var plumberOptions = { - errorHandler: plug.notify.onError("Error: <%= error.message %>") + errorHandler: plug.notify.onError("Error: <%= error.message %>") }; gulp.task("scripts-app", function() { - var paths = [ - "app/scripts/app/**/*.{coffee,js}", - "app/scripts/base/**/*.{coffee,js}", - "app/scripts/shared/**/*.{coffee,js}" - ]; + var paths = [ + "resources/assets/scripts/app/**/*.{coffee,js}", + "resources/assets/scripts/base/**/*.{coffee,js}", + "resources/assets/scripts/shared/**/*.{coffee,js}" + ]; - if (!argv.production) { - paths.push("app/scripts/debug/**/*.{coffee,js}"); + if (!argv.production) { + paths.push("resources/assets/scripts/debug/**/*.{coffee,js}"); - // we also want to add the embed stuff, since we're in development mode - // we want to watch embed files and re-compile them. However, we want - // to leave this path out in production so that embed files are not bloating - // the js file - paths.push("app/scripts/embed/**/*.{coffee,js}"); - } + // we also want to add the embed stuff, since we're in development mode + // we want to watch embed files and re-compile them. However, we want + // to leave this path out in production so that embed files are not bloating + // the js file + paths.push("resources/assets/scripts/embed/**/*.{coffee,js}"); + } - return argv.production - // Production pipeline - ? gulp.src(paths, {base: "app/scripts"}) - .pipe(plug.plumber(plumberOptions)) - .pipe(plug.order([ - "app/scripts/base/jquery-2.0.2.js", - "app/scripts/base/angular.js", - "app/scripts/base/*.{coffee,js}", - "app/scripts/shared/*.{coffee,js}", - "app/scripts/app/*.{coffee,js}", - "app/scripts/app/services/*.{coffee,js}", - "app/scripts/app/filters/*.{coffee,js}", - "app/scripts/app/directives/*.{coffee,js}", - "app/scripts/app/controllers/*.{coffee,js}", - "app/scripts/**/*.{coffee,js}" - ], {base: "."})) - .pipe(plug.if(/\.coffee/, plug.coffee())) - .pipe(plug.concat("app.js")) - .pipe(plug.uglify()) - .pipe(gulp.dest("public/build/scripts")) - // Development/watch pipeline - : gulp.src(paths, {base: "app/scripts"}) - .pipe(plug.plumber(plumberOptions)) - .pipe(plug.cached('scripts')) - .pipe(plug.sourcemaps.init()) - .pipe(plug.if(/\.coffee/, plug.coffee())) - .pipe(plug.sourcemaps.write({ - includeContent: false, - sourceRoot: "/dev-scripts/" - })) - .pipe(gulp.dest("public/build/scripts")); + return argv.production + // Production pipeline + ? gulp.src(paths, {base: "resources/assets/scripts"}) + .pipe(plug.plumber(plumberOptions)) + .pipe(plug.order([ + "resources/assets/scripts/base/jquery-2.0.2.js", + "resources/assets/scripts/base/angular.js", + "resources/assets/scripts/base/*.{coffee,js}", + "resources/assets/scripts/shared/*.{coffee,js}", + "resources/assets/scripts/app/*.{coffee,js}", + "resources/assets/scripts/app/services/*.{coffee,js}", + "resources/assets/scripts/app/filters/*.{coffee,js}", + "resources/assets/scripts/app/directives/*.{coffee,js}", + "resources/assets/scripts/app/controllers/*.{coffee,js}", + "resources/assets/scripts/**/*.{coffee,js}" + ], {base: "."})) + .pipe(plug.if(/\.coffee/, plug.coffee())) + .pipe(plug.concat("app.js")) + .pipe(plug.uglify()) + .pipe(gulp.dest("public/build/scripts")) + // Development/watch pipeline + : gulp.src(paths, {base: "resources/assets/scripts"}) + .pipe(plug.plumber(plumberOptions)) + .pipe(plug.cached('scripts')) + .pipe(plug.sourcemaps.init()) + .pipe(plug.if(/\.coffee/, plug.coffee())) + .pipe(plug.sourcemaps.write({ + includeContent: false, + sourceRoot: "/dev-scripts/" + })) + .pipe(gulp.dest("public/build/scripts")); }); gulp.task("scripts-embed", function() { - // note that this task should really only ever be invoked for production - // since development-mode watches and builds include the embed scripts - // already + // note that this task should really only ever be invoked for production + // since development-mode watches and builds include the embed scripts + // already - var includedScripts = [ - "app/scripts/base/jquery-2.0.2.js", - "app/scripts/base/jquery.viewport.js", - "app/scripts/base/underscore.js", - "app/scripts/base/moment.js", - "app/scripts/base/jquery.timeago.js", - "app/scripts/base/soundmanager2-nodebug.js", - "app/scripts/embed/*.coffee" - ]; - - return gulp.src(includedScripts, {base: "app/scripts"}) - .pipe(plug.plumber(plumberOptions)) - .pipe(plug.if(/\.coffee/, plug.coffee())) - .pipe(plug.order(includedScripts, {base: "."})) - .pipe(plug.concat("embed.js")) - .pipe(plug.uglify()) - .pipe(gulp.dest("public/build/scripts")); + var includedScripts = [ + "resources/assets/scripts/base/jquery-2.0.2.js", + "resources/assets/scripts/base/jquery.viewport.js", + "resources/assets/scripts/base/underscore.js", + "resources/assets/scripts/base/moment.js", + "resources/assets/scripts/base/jquery.timeago.js", + "resources/assets/scripts/base/soundmanager2-nodebug.js", + "resources/assets/scripts/embed/*.coffee" + ]; + + return gulp.src(includedScripts, {base: "resources/assets/scripts"}) + .pipe(plug.plumber(plumberOptions)) + .pipe(plug.if(/\.coffee/, plug.coffee())) + .pipe(plug.order(includedScripts, {base: "."})) + .pipe(plug.concat("embed.js")) + .pipe(plug.uglify()) + .pipe(gulp.dest("public/build/scripts")); }); gulp.task("styles-app", function() { - var includedStyles = [ - "app/styles/base/jquery-ui.css", - "app/styles/base/colorbox.css", - "app/styles/app.less" - ]; + var includedStyles = [ + "resources/assets/styles/base/jquery-ui.css", + "resources/assets/styles/base/colorbox.css", + "resources/assets/styles/app.less" + ]; - if (!argv.production) { - includedStyles.push("app/styles/profiler.less"); - includedStyles.push("app/styles/prettify.css"); + if (!argv.production) { + includedStyles.push("resources/assets/styles/profiler.less"); + includedStyles.push("resources/assets/styles/prettify.css"); - // we also want to add the embed stuff, since we're in development mode - // we want to watch embed files and re-compile them. However, we want - // to leave this path out in production so that embed files are not bloating - // the css file - includedStyles.push("app/styles/embed.css"); + // we also want to add the embed stuff, since we're in development mode + // we want to watch embed files and re-compile them. However, we want + // to leave this path out in production so that embed files are not bloating + // the css file + includedStyles.push("resources/assets/styles/embed.css"); - // Remove app.less from the cache so that it gets recompiled - var styleCache = plug.cached.caches.styles; - for (var file in styleCache) { - if (!styleCache.hasOwnProperty(file)) - continue; + // Remove app.less from the cache so that it gets recompiled + var styleCache = plug.cached.caches.styles; + for (var file in styleCache) { + if (!styleCache.hasOwnProperty(file)) + continue; - if (!endsWith(file, "app.less")) - continue; + if (!endsWith(file, "app.less")) + continue; - delete styleCache[file]; - } - } + delete styleCache[file]; + } + } - // note that we're not doing autoprefixer on dev builds for now to shave off roughly 600-700 milliseconds per - // build. It's already taking forever to recompile the less + // note that we're not doing autoprefixer on dev builds for now to shave off roughly 600-700 milliseconds per + // build. It's already taking forever to recompile the less - return argv.production - // Production pipeline - ? gulp.src(includedStyles, {base: "app/styles"}) - .pipe(plug.plumber(plumberOptions)) - .pipe(plug.if(/\.less/, plug.less())) - .pipe(plug.autoprefixer({browsers: ["last 2 versions"], cascade: false})) - .pipe(plug.concat("app.css")) - .pipe(plug.minifyCss()) - .pipe(gulp.dest("public/build/styles")) - // Development pipeline - : gulp.src(includedStyles, {base: "app/styles"}) - .pipe(plug.plumber(plumberOptions)) - .pipe(plug.cached("styles")) - .pipe(plug.sourcemaps.init()) - .pipe(plug.if(/\.less/, plug.less())) - .pipe(plug.sourcemaps.write({ - includeContent: false, - sourceRoot: "/dev-styles/" - })) - .pipe(gulp.dest("public/build/styles")) - .pipe(plug.livereload()); + return argv.production + // Production pipeline + ? gulp.src(includedStyles, {base: "resources/assets/styles"}) + .pipe(plug.plumber(plumberOptions)) + .pipe(plug.if(/\.less/, plug.less())) + .pipe(plug.autoprefixer({browsers: ["last 2 versions"], cascade: false})) + .pipe(plug.concat("app.css")) + .pipe(plug.minifyCss()) + .pipe(gulp.dest("public/build/styles")) + // Development pipeline + : gulp.src(includedStyles, {base: "resources/assets/styles"}) + .pipe(plug.plumber(plumberOptions)) + .pipe(plug.cached("styles")) + .pipe(plug.sourcemaps.init()) + .pipe(plug.if(/\.less/, plug.less())) + .pipe(plug.sourcemaps.write({ + includeContent: false, + sourceRoot: "/dev-styles/" + })) + .pipe(gulp.dest("public/build/styles")) + .pipe(plug.livereload()); }); gulp.task("styles-embed", function() { - // note that this task should really only ever be invoked for production - // since development-mode watches and builds include the embed styles - // already + // note that this task should really only ever be invoked for production + // since development-mode watches and builds include the embed styles + // already - return gulp.src(["app/styles/embed.less"], {base: "app/styles"}) - .pipe(plug.less()) - .pipe(plug.autoprefixer({browsers: ["last 2 versions"], cascade: false})) - .pipe(plug.concat("embed.css")) - .pipe(plug.minifyCss()) - .pipe(gulp.dest("public/build/styles")); + return gulp.src(["resources/assets/styles/embed.less"], {base: "resources/assets/styles"}) + .pipe(plug.less()) + .pipe(plug.autoprefixer({browsers: ["last 2 versions"], cascade: false})) + .pipe(plug.concat("embed.css")) + .pipe(plug.minifyCss()) + .pipe(gulp.dest("public/build/styles")); }); gulp.task('copy:templates', function() { - gulp.src([ - 'public/templates/**/*.html' - ]) - .pipe(plug.angularTemplatecache({ - module: "ponyfm", - root: "/templates" - })) - .pipe(gulp.dest('public/build/scripts')); + gulp.src([ + 'public/templates/**/*.html' + ]) + .pipe(plug.angularTemplatecache({ + module: "ponyfm", + root: "/templates" + })) + .pipe(gulp.dest('public/build/scripts')); }); gulp.task('build', [ - 'scripts-app', - 'styles-app', - 'scripts-embed', - 'styles-embed' + 'scripts-app', + 'styles-app', + 'scripts-embed', + 'styles-embed', ]); gulp.task("watch", function() { - plug.livereload.listen(); - gulp.watch("app/scripts/**/*.{coffee,js}", ["scripts-app"]); - gulp.watch("app/styles/**/*.{css,less}", ["styles-app"]); + plug.livereload.listen(); + gulp.watch("resources/assets/scripts/**/*.{coffee,js}", ["scripts-app"]); + gulp.watch("resources/assets/styles/**/*.{css,less}", ["styles-app"]); }); function endsWith(str, suffix) { - return str.indexOf(suffix, str.length - suffix.length) !== -1; + return str.indexOf(suffix, str.length - suffix.length) !== -1; } \ No newline at end of file diff --git a/logs/.gitignore b/logs/.gitignore deleted file mode 100644 index c96a04f0..00000000 --- a/logs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/phpspec.yml b/phpspec.yml new file mode 100644 index 00000000..eb57939e --- /dev/null +++ b/phpspec.yml @@ -0,0 +1,5 @@ +suites: + main: + namespace: App + psr4_prefix: App + src_path: app \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index c42dc4f7..276262db 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -8,11 +8,21 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - syntaxCheck="false" -> + syntaxCheck="false"> - ./app/tests/ + ./tests/ - \ No newline at end of file + + + app/ + + + + + + + + + diff --git a/public/.htaccess b/public/.htaccess index 3cd76108..e0f22378 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,9 +1,19 @@ - Options -MultiViews - RewriteEngine On + + Options -MultiViews + + + RewriteEngine On + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.*)/$ /$1 [L,R=301] + + # Handle Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] RewriteRule ^(.*\.(?:coffee))$ /asset.php?type=coffee&file=/$1 [L,QSA,NC] RewriteRule ^(.*\.(?:less))$ /asset.php?type=less&file=/$1 [L,QSA,NC] diff --git a/public/index.php b/public/index.php index 630a0d06..c5820533 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,5 @@ run(); +$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); -/* -|-------------------------------------------------------------------------- -| Shutdown The Application -|-------------------------------------------------------------------------- -| -| Once the app has finished running, we will fire off the shutdown events -| so that any final work may be done by the application before we shut -| down the process. This is the last thing to happen to the request. -| -*/ +$response = $kernel->handle( + $request = Illuminate\Http\Request::capture() +); -$app->shutdown(); \ No newline at end of file +$response->send(); + +$kernel->terminate($request, $response); diff --git a/readme.md b/readme.md index 47ee994c..f67a6cf7 100644 --- a/readme.md +++ b/readme.md @@ -1,35 +1,27 @@ -# Starting a dev environment -To begin development, you must do three things: -1. Ensure that you have the following hosts entries: -> 192.168.33.11 pony.fm.local -> 192.168.33.11 api.pony.fm.local +## Laravel PHP Framework -2. Install the "vagrant-bindfs" plugin: `vagrant plugin install vagrant-bindfs` +[![Build Status](https://travis-ci.org/laravel/framework.svg)](https://travis-ci.org/laravel/framework) +[![Total Downloads](https://poser.pugx.org/laravel/framework/d/total.svg)](https://packagist.org/packages/laravel/framework) +[![Latest Stable Version](https://poser.pugx.org/laravel/framework/v/stable.svg)](https://packagist.org/packages/laravel/framework) +[![Latest Unstable Version](https://poser.pugx.org/laravel/framework/v/unstable.svg)](https://packagist.org/packages/laravel/framework) +[![License](https://poser.pugx.org/laravel/framework/license.svg)](https://packagist.org/packages/laravel/framework) -3. Create the directory `pony.fm.files` in the repository's parent directory +Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Laravel attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as authentication, routing, sessions, queueing, and caching. -4. Run `vagrant up` from the folder in which you cloned the repository +Laravel is accessible, yet powerful, providing powerful tools needed for large, robust applications. A superb inversion of control container, expressive migration system, and tightly integrated unit testing support give you the tools you need to build any application with which you are tasked. -Once everything is up and running, you'll be able to access the site at http://pony.fm.local. You can access the MySQL database by logging into **192.168.33.11:3306** with the username of **homestead** and the password of **secret**. The pony.fm database is named **homestead**. +## Official Documentation -# Asset pipeline -Pony.fm uses gulp to mange its asset pipeline. **Important** due to everything being awful, you must run npm and gulp from your host machine and not the VM. You must first have it installed globally: -> npm install -g gulp +Documentation for the framework can be found on the [Laravel website](http://laravel.com/docs). -And then install all of the required local packages by invoking: -> npm install +## Contributing -Finally, build all of the scripts by executing: -> gulp build +Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](http://laravel.com/docs/contributions). -During development, you should make a point to run "gulp watch". You can do this simply by executing: -> gulp watch +## Security Vulnerabilities -This will watch and compile the .less and .coffee files in real time. +If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed. -# Configuring the servers -Pony.fm uses nginx, php-fpm, redis, and MySQL. You can modify the configuration of these services by locating the appropriate config file in the "vagrant" folder. Once modified, you must reload the configuration by running the appropriate shell script (**reload-config.sh**) or bat files (**reload-config.bat** and **reload-config.vmware.bat**). These scripts simply tell Vagrant to run "copy-and-restart-config.sh" on the VM. +### License -If you need to change any other configuration file on the VM - copy the entire file over into the vagrant folder, make your changes, and update the "copy-and-restart-config.sh" script to copy the modified config back into the proper folder. All potential configuration requirements should be represented in the vagrant folder **and never only on the VM itself** as changes will not be preserved. - -**NOTE:** currently, Redis' configuration is not reloaded by the "copy-and-restart-config.sh" \ No newline at end of file +The Laravel framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) diff --git a/app/scripts/app/app.coffee b/resources/assets/scripts/app/app.coffee similarity index 100% rename from app/scripts/app/app.coffee rename to resources/assets/scripts/app/app.coffee diff --git a/app/scripts/app/controllers/account-albums-edit.coffee b/resources/assets/scripts/app/controllers/account-albums-edit.coffee similarity index 100% rename from app/scripts/app/controllers/account-albums-edit.coffee rename to resources/assets/scripts/app/controllers/account-albums-edit.coffee diff --git a/app/scripts/app/controllers/account-albums.coffee b/resources/assets/scripts/app/controllers/account-albums.coffee similarity index 100% rename from app/scripts/app/controllers/account-albums.coffee rename to resources/assets/scripts/app/controllers/account-albums.coffee diff --git a/app/scripts/app/controllers/account-image-select.coffee b/resources/assets/scripts/app/controllers/account-image-select.coffee similarity index 100% rename from app/scripts/app/controllers/account-image-select.coffee rename to resources/assets/scripts/app/controllers/account-image-select.coffee diff --git a/app/scripts/app/controllers/account-playlists.coffee b/resources/assets/scripts/app/controllers/account-playlists.coffee similarity index 100% rename from app/scripts/app/controllers/account-playlists.coffee rename to resources/assets/scripts/app/controllers/account-playlists.coffee diff --git a/app/scripts/app/controllers/account-settings.coffee b/resources/assets/scripts/app/controllers/account-settings.coffee similarity index 100% rename from app/scripts/app/controllers/account-settings.coffee rename to resources/assets/scripts/app/controllers/account-settings.coffee diff --git a/app/scripts/app/controllers/account-track.coffee b/resources/assets/scripts/app/controllers/account-track.coffee similarity index 100% rename from app/scripts/app/controllers/account-track.coffee rename to resources/assets/scripts/app/controllers/account-track.coffee diff --git a/app/scripts/app/controllers/account-tracks.coffee b/resources/assets/scripts/app/controllers/account-tracks.coffee similarity index 100% rename from app/scripts/app/controllers/account-tracks.coffee rename to resources/assets/scripts/app/controllers/account-tracks.coffee diff --git a/app/scripts/app/controllers/album.coffee b/resources/assets/scripts/app/controllers/album.coffee similarity index 100% rename from app/scripts/app/controllers/album.coffee rename to resources/assets/scripts/app/controllers/album.coffee diff --git a/app/scripts/app/controllers/albums-list.coffee b/resources/assets/scripts/app/controllers/albums-list.coffee similarity index 100% rename from app/scripts/app/controllers/albums-list.coffee rename to resources/assets/scripts/app/controllers/albums-list.coffee diff --git a/app/scripts/app/controllers/albums.coffee b/resources/assets/scripts/app/controllers/albums.coffee similarity index 100% rename from app/scripts/app/controllers/albums.coffee rename to resources/assets/scripts/app/controllers/albums.coffee diff --git a/app/scripts/app/controllers/application.coffee b/resources/assets/scripts/app/controllers/application.coffee similarity index 100% rename from app/scripts/app/controllers/application.coffee rename to resources/assets/scripts/app/controllers/application.coffee diff --git a/app/scripts/app/controllers/artist-content.coffee b/resources/assets/scripts/app/controllers/artist-content.coffee similarity index 100% rename from app/scripts/app/controllers/artist-content.coffee rename to resources/assets/scripts/app/controllers/artist-content.coffee diff --git a/app/scripts/app/controllers/artist-favourites.coffee b/resources/assets/scripts/app/controllers/artist-favourites.coffee similarity index 100% rename from app/scripts/app/controllers/artist-favourites.coffee rename to resources/assets/scripts/app/controllers/artist-favourites.coffee diff --git a/app/scripts/app/controllers/artist-profile.coffee b/resources/assets/scripts/app/controllers/artist-profile.coffee similarity index 100% rename from app/scripts/app/controllers/artist-profile.coffee rename to resources/assets/scripts/app/controllers/artist-profile.coffee diff --git a/app/scripts/app/controllers/artist.coffee b/resources/assets/scripts/app/controllers/artist.coffee similarity index 100% rename from app/scripts/app/controllers/artist.coffee rename to resources/assets/scripts/app/controllers/artist.coffee diff --git a/app/scripts/app/controllers/artists-list.coffee b/resources/assets/scripts/app/controllers/artists-list.coffee similarity index 100% rename from app/scripts/app/controllers/artists-list.coffee rename to resources/assets/scripts/app/controllers/artists-list.coffee diff --git a/app/scripts/app/controllers/artists.coffee b/resources/assets/scripts/app/controllers/artists.coffee similarity index 100% rename from app/scripts/app/controllers/artists.coffee rename to resources/assets/scripts/app/controllers/artists.coffee diff --git a/app/scripts/app/controllers/dashboard.coffee b/resources/assets/scripts/app/controllers/dashboard.coffee similarity index 100% rename from app/scripts/app/controllers/dashboard.coffee rename to resources/assets/scripts/app/controllers/dashboard.coffee diff --git a/app/scripts/app/controllers/favourites-albums.coffee b/resources/assets/scripts/app/controllers/favourites-albums.coffee similarity index 100% rename from app/scripts/app/controllers/favourites-albums.coffee rename to resources/assets/scripts/app/controllers/favourites-albums.coffee diff --git a/app/scripts/app/controllers/favourites-playlists.coffee b/resources/assets/scripts/app/controllers/favourites-playlists.coffee similarity index 100% rename from app/scripts/app/controllers/favourites-playlists.coffee rename to resources/assets/scripts/app/controllers/favourites-playlists.coffee diff --git a/app/scripts/app/controllers/favourites-tracks.coffee b/resources/assets/scripts/app/controllers/favourites-tracks.coffee similarity index 100% rename from app/scripts/app/controllers/favourites-tracks.coffee rename to resources/assets/scripts/app/controllers/favourites-tracks.coffee diff --git a/app/scripts/app/controllers/home.coffee b/resources/assets/scripts/app/controllers/home.coffee similarity index 100% rename from app/scripts/app/controllers/home.coffee rename to resources/assets/scripts/app/controllers/home.coffee diff --git a/app/scripts/app/controllers/login.coffee b/resources/assets/scripts/app/controllers/login.coffee similarity index 100% rename from app/scripts/app/controllers/login.coffee rename to resources/assets/scripts/app/controllers/login.coffee diff --git a/app/scripts/app/controllers/playlist-form.coffee b/resources/assets/scripts/app/controllers/playlist-form.coffee similarity index 100% rename from app/scripts/app/controllers/playlist-form.coffee rename to resources/assets/scripts/app/controllers/playlist-form.coffee diff --git a/app/scripts/app/controllers/playlist.coffee b/resources/assets/scripts/app/controllers/playlist.coffee similarity index 100% rename from app/scripts/app/controllers/playlist.coffee rename to resources/assets/scripts/app/controllers/playlist.coffee diff --git a/app/scripts/app/controllers/playlists-list.coffee b/resources/assets/scripts/app/controllers/playlists-list.coffee similarity index 100% rename from app/scripts/app/controllers/playlists-list.coffee rename to resources/assets/scripts/app/controllers/playlists-list.coffee diff --git a/app/scripts/app/controllers/playlists.coffee b/resources/assets/scripts/app/controllers/playlists.coffee similarity index 100% rename from app/scripts/app/controllers/playlists.coffee rename to resources/assets/scripts/app/controllers/playlists.coffee diff --git a/app/scripts/app/controllers/sidebar.coffee b/resources/assets/scripts/app/controllers/sidebar.coffee similarity index 100% rename from app/scripts/app/controllers/sidebar.coffee rename to resources/assets/scripts/app/controllers/sidebar.coffee diff --git a/app/scripts/app/controllers/track.coffee b/resources/assets/scripts/app/controllers/track.coffee similarity index 100% rename from app/scripts/app/controllers/track.coffee rename to resources/assets/scripts/app/controllers/track.coffee diff --git a/app/scripts/app/controllers/tracks-list.coffee b/resources/assets/scripts/app/controllers/tracks-list.coffee similarity index 100% rename from app/scripts/app/controllers/tracks-list.coffee rename to resources/assets/scripts/app/controllers/tracks-list.coffee diff --git a/app/scripts/app/controllers/tracks.coffee b/resources/assets/scripts/app/controllers/tracks.coffee similarity index 100% rename from app/scripts/app/controllers/tracks.coffee rename to resources/assets/scripts/app/controllers/tracks.coffee diff --git a/app/scripts/app/controllers/uploader.coffee b/resources/assets/scripts/app/controllers/uploader.coffee similarity index 100% rename from app/scripts/app/controllers/uploader.coffee rename to resources/assets/scripts/app/controllers/uploader.coffee diff --git a/app/scripts/app/directives/albums-list.coffee b/resources/assets/scripts/app/directives/albums-list.coffee similarity index 100% rename from app/scripts/app/directives/albums-list.coffee rename to resources/assets/scripts/app/directives/albums-list.coffee diff --git a/app/scripts/app/directives/comments.coffee b/resources/assets/scripts/app/directives/comments.coffee similarity index 100% rename from app/scripts/app/directives/comments.coffee rename to resources/assets/scripts/app/directives/comments.coffee diff --git a/app/scripts/app/directives/eat-click.coffee b/resources/assets/scripts/app/directives/eat-click.coffee similarity index 100% rename from app/scripts/app/directives/eat-click.coffee rename to resources/assets/scripts/app/directives/eat-click.coffee diff --git a/app/scripts/app/directives/favouriteButton.coffee b/resources/assets/scripts/app/directives/favouriteButton.coffee similarity index 100% rename from app/scripts/app/directives/favouriteButton.coffee rename to resources/assets/scripts/app/directives/favouriteButton.coffee diff --git a/app/scripts/app/directives/image-upload.coffee b/resources/assets/scripts/app/directives/image-upload.coffee similarity index 100% rename from app/scripts/app/directives/image-upload.coffee rename to resources/assets/scripts/app/directives/image-upload.coffee diff --git a/app/scripts/app/directives/player.coffee b/resources/assets/scripts/app/directives/player.coffee similarity index 100% rename from app/scripts/app/directives/player.coffee rename to resources/assets/scripts/app/directives/player.coffee diff --git a/app/scripts/app/directives/playlists-list.coffee b/resources/assets/scripts/app/directives/playlists-list.coffee similarity index 100% rename from app/scripts/app/directives/playlists-list.coffee rename to resources/assets/scripts/app/directives/playlists-list.coffee diff --git a/app/scripts/app/directives/popup.coffee b/resources/assets/scripts/app/directives/popup.coffee similarity index 100% rename from app/scripts/app/directives/popup.coffee rename to resources/assets/scripts/app/directives/popup.coffee diff --git a/app/scripts/app/directives/progress-bar.coffee b/resources/assets/scripts/app/directives/progress-bar.coffee similarity index 100% rename from app/scripts/app/directives/progress-bar.coffee rename to resources/assets/scripts/app/directives/progress-bar.coffee diff --git a/app/scripts/app/directives/scroll-recorder.coffee b/resources/assets/scripts/app/directives/scroll-recorder.coffee similarity index 100% rename from app/scripts/app/directives/scroll-recorder.coffee rename to resources/assets/scripts/app/directives/scroll-recorder.coffee diff --git a/app/scripts/app/directives/share-buttons.coffee b/resources/assets/scripts/app/directives/share-buttons.coffee similarity index 100% rename from app/scripts/app/directives/share-buttons.coffee rename to resources/assets/scripts/app/directives/share-buttons.coffee diff --git a/app/scripts/app/directives/src-loader.coffee b/resources/assets/scripts/app/directives/src-loader.coffee similarity index 100% rename from app/scripts/app/directives/src-loader.coffee rename to resources/assets/scripts/app/directives/src-loader.coffee diff --git a/app/scripts/app/directives/track-player.coffee b/resources/assets/scripts/app/directives/track-player.coffee similarity index 100% rename from app/scripts/app/directives/track-player.coffee rename to resources/assets/scripts/app/directives/track-player.coffee diff --git a/app/scripts/app/directives/tracks-list.coffee b/resources/assets/scripts/app/directives/tracks-list.coffee similarity index 100% rename from app/scripts/app/directives/tracks-list.coffee rename to resources/assets/scripts/app/directives/tracks-list.coffee diff --git a/app/scripts/app/directives/uploader.coffee b/resources/assets/scripts/app/directives/uploader.coffee similarity index 100% rename from app/scripts/app/directives/uploader.coffee rename to resources/assets/scripts/app/directives/uploader.coffee diff --git a/app/scripts/app/filters/length.coffee b/resources/assets/scripts/app/filters/length.coffee similarity index 100% rename from app/scripts/app/filters/length.coffee rename to resources/assets/scripts/app/filters/length.coffee diff --git a/app/scripts/app/filters/moment-from-now.coffee b/resources/assets/scripts/app/filters/moment-from-now.coffee similarity index 100% rename from app/scripts/app/filters/moment-from-now.coffee rename to resources/assets/scripts/app/filters/moment-from-now.coffee diff --git a/app/scripts/app/filters/newlines.coffee b/resources/assets/scripts/app/filters/newlines.coffee similarity index 100% rename from app/scripts/app/filters/newlines.coffee rename to resources/assets/scripts/app/filters/newlines.coffee diff --git a/app/scripts/app/filters/noHTML.coffee b/resources/assets/scripts/app/filters/noHTML.coffee similarity index 100% rename from app/scripts/app/filters/noHTML.coffee rename to resources/assets/scripts/app/filters/noHTML.coffee diff --git a/app/scripts/app/filters/pfm-date.js b/resources/assets/scripts/app/filters/pfm-date.js similarity index 100% rename from app/scripts/app/filters/pfm-date.js rename to resources/assets/scripts/app/filters/pfm-date.js diff --git a/app/scripts/app/filters/seconds-display.coffee b/resources/assets/scripts/app/filters/seconds-display.coffee similarity index 100% rename from app/scripts/app/filters/seconds-display.coffee rename to resources/assets/scripts/app/filters/seconds-display.coffee diff --git a/app/scripts/app/filters/trust.coffee b/resources/assets/scripts/app/filters/trust.coffee similarity index 100% rename from app/scripts/app/filters/trust.coffee rename to resources/assets/scripts/app/filters/trust.coffee diff --git a/app/scripts/app/services/account-albums.coffee b/resources/assets/scripts/app/services/account-albums.coffee similarity index 100% rename from app/scripts/app/services/account-albums.coffee rename to resources/assets/scripts/app/services/account-albums.coffee diff --git a/app/scripts/app/services/account-tracks.coffee b/resources/assets/scripts/app/services/account-tracks.coffee similarity index 100% rename from app/scripts/app/services/account-tracks.coffee rename to resources/assets/scripts/app/services/account-tracks.coffee diff --git a/app/scripts/app/services/albums.coffee b/resources/assets/scripts/app/services/albums.coffee similarity index 100% rename from app/scripts/app/services/albums.coffee rename to resources/assets/scripts/app/services/albums.coffee diff --git a/app/scripts/app/services/artists.coffee b/resources/assets/scripts/app/services/artists.coffee similarity index 100% rename from app/scripts/app/services/artists.coffee rename to resources/assets/scripts/app/services/artists.coffee diff --git a/app/scripts/app/services/auth.coffee b/resources/assets/scripts/app/services/auth.coffee similarity index 100% rename from app/scripts/app/services/auth.coffee rename to resources/assets/scripts/app/services/auth.coffee diff --git a/app/scripts/app/services/comments.coffee b/resources/assets/scripts/app/services/comments.coffee similarity index 100% rename from app/scripts/app/services/comments.coffee rename to resources/assets/scripts/app/services/comments.coffee diff --git a/app/scripts/app/services/dashboard.coffee b/resources/assets/scripts/app/services/dashboard.coffee similarity index 100% rename from app/scripts/app/services/dashboard.coffee rename to resources/assets/scripts/app/services/dashboard.coffee diff --git a/app/scripts/app/services/favourites.coffee b/resources/assets/scripts/app/services/favourites.coffee similarity index 100% rename from app/scripts/app/services/favourites.coffee rename to resources/assets/scripts/app/services/favourites.coffee diff --git a/app/scripts/app/services/follow.coffee b/resources/assets/scripts/app/services/follow.coffee similarity index 100% rename from app/scripts/app/services/follow.coffee rename to resources/assets/scripts/app/services/follow.coffee diff --git a/app/scripts/app/services/images.coffee b/resources/assets/scripts/app/services/images.coffee similarity index 100% rename from app/scripts/app/services/images.coffee rename to resources/assets/scripts/app/services/images.coffee diff --git a/app/scripts/app/services/lightbox.coffee b/resources/assets/scripts/app/services/lightbox.coffee similarity index 100% rename from app/scripts/app/services/lightbox.coffee rename to resources/assets/scripts/app/services/lightbox.coffee diff --git a/app/scripts/app/services/player.coffee b/resources/assets/scripts/app/services/player.coffee similarity index 100% rename from app/scripts/app/services/player.coffee rename to resources/assets/scripts/app/services/player.coffee diff --git a/app/scripts/app/services/playlists.coffee b/resources/assets/scripts/app/services/playlists.coffee similarity index 100% rename from app/scripts/app/services/playlists.coffee rename to resources/assets/scripts/app/services/playlists.coffee diff --git a/app/scripts/app/services/taxonomies.coffee b/resources/assets/scripts/app/services/taxonomies.coffee similarity index 100% rename from app/scripts/app/services/taxonomies.coffee rename to resources/assets/scripts/app/services/taxonomies.coffee diff --git a/app/scripts/app/services/tracks.coffee b/resources/assets/scripts/app/services/tracks.coffee similarity index 100% rename from app/scripts/app/services/tracks.coffee rename to resources/assets/scripts/app/services/tracks.coffee diff --git a/app/scripts/app/services/upload.coffee b/resources/assets/scripts/app/services/upload.coffee similarity index 100% rename from app/scripts/app/services/upload.coffee rename to resources/assets/scripts/app/services/upload.coffee diff --git a/app/scripts/base/angular-ui-date.js b/resources/assets/scripts/base/angular-ui-date.js similarity index 100% rename from app/scripts/base/angular-ui-date.js rename to resources/assets/scripts/base/angular-ui-date.js diff --git a/app/scripts/base/angular-ui-router.js b/resources/assets/scripts/base/angular-ui-router.js similarity index 100% rename from app/scripts/base/angular-ui-router.js rename to resources/assets/scripts/base/angular-ui-router.js diff --git a/app/scripts/base/angular-ui-sortable.js b/resources/assets/scripts/base/angular-ui-sortable.js similarity index 100% rename from app/scripts/base/angular-ui-sortable.js rename to resources/assets/scripts/base/angular-ui-sortable.js diff --git a/app/scripts/base/angular.js b/resources/assets/scripts/base/angular.js similarity index 100% rename from app/scripts/base/angular.js rename to resources/assets/scripts/base/angular.js diff --git a/app/scripts/base/angularytics.js b/resources/assets/scripts/base/angularytics.js similarity index 100% rename from app/scripts/base/angularytics.js rename to resources/assets/scripts/base/angularytics.js diff --git a/app/scripts/base/bindonce.js b/resources/assets/scripts/base/bindonce.js similarity index 100% rename from app/scripts/base/bindonce.js rename to resources/assets/scripts/base/bindonce.js diff --git a/app/scripts/base/jquery-2.0.2.js b/resources/assets/scripts/base/jquery-2.0.2.js similarity index 100% rename from app/scripts/base/jquery-2.0.2.js rename to resources/assets/scripts/base/jquery-2.0.2.js diff --git a/app/scripts/base/jquery-ui.js b/resources/assets/scripts/base/jquery-ui.js similarity index 100% rename from app/scripts/base/jquery-ui.js rename to resources/assets/scripts/base/jquery-ui.js diff --git a/app/scripts/base/jquery.colorbox.js b/resources/assets/scripts/base/jquery.colorbox.js similarity index 100% rename from app/scripts/base/jquery.colorbox.js rename to resources/assets/scripts/base/jquery.colorbox.js diff --git a/app/scripts/base/jquery.cookie.js b/resources/assets/scripts/base/jquery.cookie.js similarity index 100% rename from app/scripts/base/jquery.cookie.js rename to resources/assets/scripts/base/jquery.cookie.js diff --git a/app/scripts/base/jquery.timeago.js b/resources/assets/scripts/base/jquery.timeago.js similarity index 100% rename from app/scripts/base/jquery.timeago.js rename to resources/assets/scripts/base/jquery.timeago.js diff --git a/app/scripts/base/jquery.viewport.js b/resources/assets/scripts/base/jquery.viewport.js similarity index 100% rename from app/scripts/base/jquery.viewport.js rename to resources/assets/scripts/base/jquery.viewport.js diff --git a/app/scripts/base/moment.js b/resources/assets/scripts/base/moment.js similarity index 100% rename from app/scripts/base/moment.js rename to resources/assets/scripts/base/moment.js diff --git a/app/scripts/base/soundmanager2-nodebug.js b/resources/assets/scripts/base/soundmanager2-nodebug.js similarity index 100% rename from app/scripts/base/soundmanager2-nodebug.js rename to resources/assets/scripts/base/soundmanager2-nodebug.js diff --git a/app/scripts/base/tumblr.js b/resources/assets/scripts/base/tumblr.js similarity index 100% rename from app/scripts/base/tumblr.js rename to resources/assets/scripts/base/tumblr.js diff --git a/app/scripts/base/ui-bootstrap-tpls-0.4.0.js b/resources/assets/scripts/base/ui-bootstrap-tpls-0.4.0.js similarity index 100% rename from app/scripts/base/ui-bootstrap-tpls-0.4.0.js rename to resources/assets/scripts/base/ui-bootstrap-tpls-0.4.0.js diff --git a/app/scripts/base/underscore.js b/resources/assets/scripts/base/underscore.js similarity index 100% rename from app/scripts/base/underscore.js rename to resources/assets/scripts/base/underscore.js diff --git a/app/scripts/debug/prettify.js b/resources/assets/scripts/debug/prettify.js similarity index 100% rename from app/scripts/debug/prettify.js rename to resources/assets/scripts/debug/prettify.js diff --git a/app/scripts/debug/profiler.coffee b/resources/assets/scripts/debug/profiler.coffee similarity index 100% rename from app/scripts/debug/profiler.coffee rename to resources/assets/scripts/debug/profiler.coffee diff --git a/app/scripts/embed/favourite.coffee b/resources/assets/scripts/embed/favourite.coffee similarity index 100% rename from app/scripts/embed/favourite.coffee rename to resources/assets/scripts/embed/favourite.coffee diff --git a/app/scripts/embed/player.coffee b/resources/assets/scripts/embed/player.coffee similarity index 100% rename from app/scripts/embed/player.coffee rename to resources/assets/scripts/embed/player.coffee diff --git a/app/scripts/shared/init.coffee b/resources/assets/scripts/shared/init.coffee similarity index 100% rename from app/scripts/shared/init.coffee rename to resources/assets/scripts/shared/init.coffee diff --git a/app/scripts/shared/jquery-extensions.js b/resources/assets/scripts/shared/jquery-extensions.js similarity index 100% rename from app/scripts/shared/jquery-extensions.js rename to resources/assets/scripts/shared/jquery-extensions.js diff --git a/app/scripts/shared/layout.coffee b/resources/assets/scripts/shared/layout.coffee similarity index 100% rename from app/scripts/shared/layout.coffee rename to resources/assets/scripts/shared/layout.coffee diff --git a/app/scripts/shared/underscore-extensions.js b/resources/assets/scripts/shared/underscore-extensions.js similarity index 100% rename from app/scripts/shared/underscore-extensions.js rename to resources/assets/scripts/shared/underscore-extensions.js diff --git a/app/styles/account-content.less b/resources/assets/styles/account-content.less similarity index 100% rename from app/styles/account-content.less rename to resources/assets/styles/account-content.less diff --git a/app/styles/animations.less b/resources/assets/styles/animations.less similarity index 100% rename from app/styles/animations.less rename to resources/assets/styles/animations.less diff --git a/app/styles/app.less b/resources/assets/styles/app.less similarity index 100% rename from app/styles/app.less rename to resources/assets/styles/app.less diff --git a/app/styles/base/bootstrap/accordion.less b/resources/assets/styles/base/bootstrap/accordion.less similarity index 100% rename from app/styles/base/bootstrap/accordion.less rename to resources/assets/styles/base/bootstrap/accordion.less diff --git a/app/styles/base/bootstrap/alerts.less b/resources/assets/styles/base/bootstrap/alerts.less similarity index 100% rename from app/styles/base/bootstrap/alerts.less rename to resources/assets/styles/base/bootstrap/alerts.less diff --git a/app/styles/base/bootstrap/bootstrap.less b/resources/assets/styles/base/bootstrap/bootstrap.less similarity index 100% rename from app/styles/base/bootstrap/bootstrap.less rename to resources/assets/styles/base/bootstrap/bootstrap.less diff --git a/app/styles/base/bootstrap/breadcrumbs.less b/resources/assets/styles/base/bootstrap/breadcrumbs.less similarity index 100% rename from app/styles/base/bootstrap/breadcrumbs.less rename to resources/assets/styles/base/bootstrap/breadcrumbs.less diff --git a/app/styles/base/bootstrap/button-groups.less b/resources/assets/styles/base/bootstrap/button-groups.less similarity index 100% rename from app/styles/base/bootstrap/button-groups.less rename to resources/assets/styles/base/bootstrap/button-groups.less diff --git a/app/styles/base/bootstrap/buttons.less b/resources/assets/styles/base/bootstrap/buttons.less similarity index 100% rename from app/styles/base/bootstrap/buttons.less rename to resources/assets/styles/base/bootstrap/buttons.less diff --git a/app/styles/base/bootstrap/carousel.less b/resources/assets/styles/base/bootstrap/carousel.less similarity index 100% rename from app/styles/base/bootstrap/carousel.less rename to resources/assets/styles/base/bootstrap/carousel.less diff --git a/app/styles/base/bootstrap/close.less b/resources/assets/styles/base/bootstrap/close.less similarity index 100% rename from app/styles/base/bootstrap/close.less rename to resources/assets/styles/base/bootstrap/close.less diff --git a/app/styles/base/bootstrap/code.less b/resources/assets/styles/base/bootstrap/code.less similarity index 100% rename from app/styles/base/bootstrap/code.less rename to resources/assets/styles/base/bootstrap/code.less diff --git a/app/styles/base/bootstrap/component-animations.less b/resources/assets/styles/base/bootstrap/component-animations.less similarity index 100% rename from app/styles/base/bootstrap/component-animations.less rename to resources/assets/styles/base/bootstrap/component-animations.less diff --git a/app/styles/base/bootstrap/dropdowns.less b/resources/assets/styles/base/bootstrap/dropdowns.less similarity index 100% rename from app/styles/base/bootstrap/dropdowns.less rename to resources/assets/styles/base/bootstrap/dropdowns.less diff --git a/app/styles/base/bootstrap/forms.less b/resources/assets/styles/base/bootstrap/forms.less similarity index 100% rename from app/styles/base/bootstrap/forms.less rename to resources/assets/styles/base/bootstrap/forms.less diff --git a/app/styles/base/bootstrap/grid.less b/resources/assets/styles/base/bootstrap/grid.less similarity index 100% rename from app/styles/base/bootstrap/grid.less rename to resources/assets/styles/base/bootstrap/grid.less diff --git a/app/styles/base/bootstrap/hero-unit.less b/resources/assets/styles/base/bootstrap/hero-unit.less similarity index 100% rename from app/styles/base/bootstrap/hero-unit.less rename to resources/assets/styles/base/bootstrap/hero-unit.less diff --git a/app/styles/base/bootstrap/labels-badges.less b/resources/assets/styles/base/bootstrap/labels-badges.less similarity index 100% rename from app/styles/base/bootstrap/labels-badges.less rename to resources/assets/styles/base/bootstrap/labels-badges.less diff --git a/app/styles/base/bootstrap/layouts.less b/resources/assets/styles/base/bootstrap/layouts.less similarity index 100% rename from app/styles/base/bootstrap/layouts.less rename to resources/assets/styles/base/bootstrap/layouts.less diff --git a/app/styles/base/bootstrap/media.less b/resources/assets/styles/base/bootstrap/media.less similarity index 100% rename from app/styles/base/bootstrap/media.less rename to resources/assets/styles/base/bootstrap/media.less diff --git a/app/styles/base/bootstrap/mixins.less b/resources/assets/styles/base/bootstrap/mixins.less similarity index 100% rename from app/styles/base/bootstrap/mixins.less rename to resources/assets/styles/base/bootstrap/mixins.less diff --git a/app/styles/base/bootstrap/modals.less b/resources/assets/styles/base/bootstrap/modals.less similarity index 100% rename from app/styles/base/bootstrap/modals.less rename to resources/assets/styles/base/bootstrap/modals.less diff --git a/app/styles/base/bootstrap/navbar.less b/resources/assets/styles/base/bootstrap/navbar.less similarity index 100% rename from app/styles/base/bootstrap/navbar.less rename to resources/assets/styles/base/bootstrap/navbar.less diff --git a/app/styles/base/bootstrap/navs.less b/resources/assets/styles/base/bootstrap/navs.less similarity index 100% rename from app/styles/base/bootstrap/navs.less rename to resources/assets/styles/base/bootstrap/navs.less diff --git a/app/styles/base/bootstrap/pager.less b/resources/assets/styles/base/bootstrap/pager.less similarity index 100% rename from app/styles/base/bootstrap/pager.less rename to resources/assets/styles/base/bootstrap/pager.less diff --git a/app/styles/base/bootstrap/pagination.less b/resources/assets/styles/base/bootstrap/pagination.less similarity index 100% rename from app/styles/base/bootstrap/pagination.less rename to resources/assets/styles/base/bootstrap/pagination.less diff --git a/app/styles/base/bootstrap/popovers.less b/resources/assets/styles/base/bootstrap/popovers.less similarity index 100% rename from app/styles/base/bootstrap/popovers.less rename to resources/assets/styles/base/bootstrap/popovers.less diff --git a/app/styles/base/bootstrap/progress-bars.less b/resources/assets/styles/base/bootstrap/progress-bars.less similarity index 100% rename from app/styles/base/bootstrap/progress-bars.less rename to resources/assets/styles/base/bootstrap/progress-bars.less diff --git a/app/styles/base/bootstrap/reset.less b/resources/assets/styles/base/bootstrap/reset.less similarity index 100% rename from app/styles/base/bootstrap/reset.less rename to resources/assets/styles/base/bootstrap/reset.less diff --git a/app/styles/base/bootstrap/responsive-1200px-min.less b/resources/assets/styles/base/bootstrap/responsive-1200px-min.less similarity index 100% rename from app/styles/base/bootstrap/responsive-1200px-min.less rename to resources/assets/styles/base/bootstrap/responsive-1200px-min.less diff --git a/app/styles/base/bootstrap/responsive-767px-max.less b/resources/assets/styles/base/bootstrap/responsive-767px-max.less similarity index 100% rename from app/styles/base/bootstrap/responsive-767px-max.less rename to resources/assets/styles/base/bootstrap/responsive-767px-max.less diff --git a/app/styles/base/bootstrap/responsive-768px-979px.less b/resources/assets/styles/base/bootstrap/responsive-768px-979px.less similarity index 100% rename from app/styles/base/bootstrap/responsive-768px-979px.less rename to resources/assets/styles/base/bootstrap/responsive-768px-979px.less diff --git a/app/styles/base/bootstrap/responsive-navbar.less b/resources/assets/styles/base/bootstrap/responsive-navbar.less similarity index 100% rename from app/styles/base/bootstrap/responsive-navbar.less rename to resources/assets/styles/base/bootstrap/responsive-navbar.less diff --git a/app/styles/base/bootstrap/responsive-utilities.less b/resources/assets/styles/base/bootstrap/responsive-utilities.less similarity index 100% rename from app/styles/base/bootstrap/responsive-utilities.less rename to resources/assets/styles/base/bootstrap/responsive-utilities.less diff --git a/app/styles/base/bootstrap/responsive.less b/resources/assets/styles/base/bootstrap/responsive.less similarity index 100% rename from app/styles/base/bootstrap/responsive.less rename to resources/assets/styles/base/bootstrap/responsive.less diff --git a/app/styles/base/bootstrap/scaffolding.less b/resources/assets/styles/base/bootstrap/scaffolding.less similarity index 100% rename from app/styles/base/bootstrap/scaffolding.less rename to resources/assets/styles/base/bootstrap/scaffolding.less diff --git a/app/styles/base/bootstrap/sprites.less b/resources/assets/styles/base/bootstrap/sprites.less similarity index 100% rename from app/styles/base/bootstrap/sprites.less rename to resources/assets/styles/base/bootstrap/sprites.less diff --git a/app/styles/base/bootstrap/tables.less b/resources/assets/styles/base/bootstrap/tables.less similarity index 100% rename from app/styles/base/bootstrap/tables.less rename to resources/assets/styles/base/bootstrap/tables.less diff --git a/app/styles/base/bootstrap/thumbnails.less b/resources/assets/styles/base/bootstrap/thumbnails.less similarity index 100% rename from app/styles/base/bootstrap/thumbnails.less rename to resources/assets/styles/base/bootstrap/thumbnails.less diff --git a/app/styles/base/bootstrap/tooltip.less b/resources/assets/styles/base/bootstrap/tooltip.less similarity index 100% rename from app/styles/base/bootstrap/tooltip.less rename to resources/assets/styles/base/bootstrap/tooltip.less diff --git a/app/styles/base/bootstrap/type.less b/resources/assets/styles/base/bootstrap/type.less similarity index 100% rename from app/styles/base/bootstrap/type.less rename to resources/assets/styles/base/bootstrap/type.less diff --git a/app/styles/base/bootstrap/utilities.less b/resources/assets/styles/base/bootstrap/utilities.less similarity index 100% rename from app/styles/base/bootstrap/utilities.less rename to resources/assets/styles/base/bootstrap/utilities.less diff --git a/app/styles/base/bootstrap/variables.less b/resources/assets/styles/base/bootstrap/variables.less similarity index 100% rename from app/styles/base/bootstrap/variables.less rename to resources/assets/styles/base/bootstrap/variables.less diff --git a/app/styles/base/bootstrap/wells.less b/resources/assets/styles/base/bootstrap/wells.less similarity index 100% rename from app/styles/base/bootstrap/wells.less rename to resources/assets/styles/base/bootstrap/wells.less diff --git a/app/styles/base/colorbox.css b/resources/assets/styles/base/colorbox.css similarity index 100% rename from app/styles/base/colorbox.css rename to resources/assets/styles/base/colorbox.css diff --git a/app/styles/base/font-awesome/bootstrap.less b/resources/assets/styles/base/font-awesome/bootstrap.less similarity index 100% rename from app/styles/base/font-awesome/bootstrap.less rename to resources/assets/styles/base/font-awesome/bootstrap.less diff --git a/app/styles/base/font-awesome/core.less b/resources/assets/styles/base/font-awesome/core.less similarity index 100% rename from app/styles/base/font-awesome/core.less rename to resources/assets/styles/base/font-awesome/core.less diff --git a/app/styles/base/font-awesome/extras.less b/resources/assets/styles/base/font-awesome/extras.less similarity index 100% rename from app/styles/base/font-awesome/extras.less rename to resources/assets/styles/base/font-awesome/extras.less diff --git a/app/styles/base/font-awesome/font-awesome-ie7.less b/resources/assets/styles/base/font-awesome/font-awesome-ie7.less similarity index 100% rename from app/styles/base/font-awesome/font-awesome-ie7.less rename to resources/assets/styles/base/font-awesome/font-awesome-ie7.less diff --git a/app/styles/base/font-awesome/font-awesome.less b/resources/assets/styles/base/font-awesome/font-awesome.less similarity index 100% rename from app/styles/base/font-awesome/font-awesome.less rename to resources/assets/styles/base/font-awesome/font-awesome.less diff --git a/app/styles/base/font-awesome/icons.less b/resources/assets/styles/base/font-awesome/icons.less similarity index 100% rename from app/styles/base/font-awesome/icons.less rename to resources/assets/styles/base/font-awesome/icons.less diff --git a/app/styles/base/font-awesome/mixins.less b/resources/assets/styles/base/font-awesome/mixins.less similarity index 100% rename from app/styles/base/font-awesome/mixins.less rename to resources/assets/styles/base/font-awesome/mixins.less diff --git a/app/styles/base/font-awesome/path.less b/resources/assets/styles/base/font-awesome/path.less similarity index 100% rename from app/styles/base/font-awesome/path.less rename to resources/assets/styles/base/font-awesome/path.less diff --git a/app/styles/base/font-awesome/variables.less b/resources/assets/styles/base/font-awesome/variables.less similarity index 100% rename from app/styles/base/font-awesome/variables.less rename to resources/assets/styles/base/font-awesome/variables.less diff --git a/app/styles/base/images/animated-overlay.gif b/resources/assets/styles/base/images/animated-overlay.gif similarity index 100% rename from app/styles/base/images/animated-overlay.gif rename to resources/assets/styles/base/images/animated-overlay.gif diff --git a/app/styles/base/images/border.png b/resources/assets/styles/base/images/border.png similarity index 100% rename from app/styles/base/images/border.png rename to resources/assets/styles/base/images/border.png diff --git a/app/styles/base/images/controls.png b/resources/assets/styles/base/images/controls.png similarity index 100% rename from app/styles/base/images/controls.png rename to resources/assets/styles/base/images/controls.png diff --git a/app/styles/base/images/loading.gif b/resources/assets/styles/base/images/loading.gif similarity index 100% rename from app/styles/base/images/loading.gif rename to resources/assets/styles/base/images/loading.gif diff --git a/app/styles/base/images/loading_background.png b/resources/assets/styles/base/images/loading_background.png similarity index 100% rename from app/styles/base/images/loading_background.png rename to resources/assets/styles/base/images/loading_background.png diff --git a/app/styles/base/images/overlay.png b/resources/assets/styles/base/images/overlay.png similarity index 100% rename from app/styles/base/images/overlay.png rename to resources/assets/styles/base/images/overlay.png diff --git a/app/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/resources/assets/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from app/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png rename to resources/assets/styles/base/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/app/styles/base/images/ui-bg_flat_75_ffffff_40x100.png b/resources/assets/styles/base/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from app/styles/base/images/ui-bg_flat_75_ffffff_40x100.png rename to resources/assets/styles/base/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/app/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/resources/assets/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from app/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png rename to resources/assets/styles/base/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/app/styles/base/images/ui-bg_glass_65_ffffff_1x400.png b/resources/assets/styles/base/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from app/styles/base/images/ui-bg_glass_65_ffffff_1x400.png rename to resources/assets/styles/base/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/app/styles/base/images/ui-bg_glass_75_dadada_1x400.png b/resources/assets/styles/base/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from app/styles/base/images/ui-bg_glass_75_dadada_1x400.png rename to resources/assets/styles/base/images/ui-bg_glass_75_dadada_1x400.png diff --git a/app/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/resources/assets/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from app/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png rename to resources/assets/styles/base/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/app/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png b/resources/assets/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from app/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png rename to resources/assets/styles/base/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/app/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/resources/assets/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from app/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to resources/assets/styles/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/app/styles/base/images/ui-icons_222222_256x240.png b/resources/assets/styles/base/images/ui-icons_222222_256x240.png similarity index 100% rename from app/styles/base/images/ui-icons_222222_256x240.png rename to resources/assets/styles/base/images/ui-icons_222222_256x240.png diff --git a/app/styles/base/images/ui-icons_2e83ff_256x240.png b/resources/assets/styles/base/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from app/styles/base/images/ui-icons_2e83ff_256x240.png rename to resources/assets/styles/base/images/ui-icons_2e83ff_256x240.png diff --git a/app/styles/base/images/ui-icons_454545_256x240.png b/resources/assets/styles/base/images/ui-icons_454545_256x240.png similarity index 100% rename from app/styles/base/images/ui-icons_454545_256x240.png rename to resources/assets/styles/base/images/ui-icons_454545_256x240.png diff --git a/app/styles/base/images/ui-icons_888888_256x240.png b/resources/assets/styles/base/images/ui-icons_888888_256x240.png similarity index 100% rename from app/styles/base/images/ui-icons_888888_256x240.png rename to resources/assets/styles/base/images/ui-icons_888888_256x240.png diff --git a/app/styles/base/images/ui-icons_cd0a0a_256x240.png b/resources/assets/styles/base/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from app/styles/base/images/ui-icons_cd0a0a_256x240.png rename to resources/assets/styles/base/images/ui-icons_cd0a0a_256x240.png diff --git a/app/styles/base/jquery-ui.css b/resources/assets/styles/base/jquery-ui.css similarity index 100% rename from app/styles/base/jquery-ui.css rename to resources/assets/styles/base/jquery-ui.css diff --git a/app/styles/body.less b/resources/assets/styles/body.less similarity index 100% rename from app/styles/body.less rename to resources/assets/styles/body.less diff --git a/app/styles/components.less b/resources/assets/styles/components.less similarity index 100% rename from app/styles/components.less rename to resources/assets/styles/components.less diff --git a/app/styles/content.less b/resources/assets/styles/content.less similarity index 100% rename from app/styles/content.less rename to resources/assets/styles/content.less diff --git a/app/styles/dashboard.less b/resources/assets/styles/dashboard.less similarity index 100% rename from app/styles/dashboard.less rename to resources/assets/styles/dashboard.less diff --git a/app/styles/embed.less b/resources/assets/styles/embed.less similarity index 100% rename from app/styles/embed.less rename to resources/assets/styles/embed.less diff --git a/app/styles/forms.less b/resources/assets/styles/forms.less similarity index 100% rename from app/styles/forms.less rename to resources/assets/styles/forms.less diff --git a/app/styles/layout.less b/resources/assets/styles/layout.less similarity index 100% rename from app/styles/layout.less rename to resources/assets/styles/layout.less diff --git a/app/styles/mixins.less b/resources/assets/styles/mixins.less similarity index 100% rename from app/styles/mixins.less rename to resources/assets/styles/mixins.less diff --git a/app/styles/player.less b/resources/assets/styles/player.less similarity index 100% rename from app/styles/player.less rename to resources/assets/styles/player.less diff --git a/app/styles/prettify.css b/resources/assets/styles/prettify.css similarity index 100% rename from app/styles/prettify.css rename to resources/assets/styles/prettify.css diff --git a/app/styles/profiler.less b/resources/assets/styles/profiler.less similarity index 100% rename from app/styles/profiler.less rename to resources/assets/styles/profiler.less diff --git a/app/styles/uploader.less b/resources/assets/styles/uploader.less similarity index 100% rename from app/styles/uploader.less rename to resources/assets/styles/uploader.less diff --git a/app/styles/variables.less b/resources/assets/styles/variables.less similarity index 100% rename from app/styles/variables.less rename to resources/assets/styles/variables.less diff --git a/resources/environments/.env.example b/resources/environments/.env.example new file mode 100644 index 00000000..b0321a00 --- /dev/null +++ b/resources/environments/.env.example @@ -0,0 +1,24 @@ +APP_ENV=local +APP_DEBUG=true +APP_URL=http://pony.fm.local/ +APP_KEY=SomeRandomString + +DB_HOST=localhost +DB_DATABASE=homestead +DB_USERNAME=homestead +DB_PASSWORD=secret + +SESSION_HTTPS_ONLY=false +QUEUE_DRIVER=sync + +MAIL_DRIVER=smtp +MAIL_HOST=mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null + +PONI_CLIENT_ID=null +PONI_CLIENT_SECRET=null + +PONYFM_DATASTORE=null diff --git a/resources/environments/.env.local b/resources/environments/.env.local new file mode 100644 index 00000000..85eaebee --- /dev/null +++ b/resources/environments/.env.local @@ -0,0 +1,24 @@ +APP_ENV=local +APP_DEBUG=true +APP_URL=http://pony.fm.local/ +APP_KEY=q5lKAapzJwZas0izFS1CfCn3oX8Kk2jj + +DB_HOST=localhost +DB_DATABASE=homestead +DB_USERNAME=homestead +DB_PASSWORD=secret + +SESSION_HTTPS_ONLY=false +QUEUE_DRIVER=sync + +MAIL_DRIVER=smtp +MAIL_HOST=mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null + +PONI_CLIENT_ID=AAopdYDbn6JarV0Wo025gYQNxS1VXcj8GCa0raSC +PONI_CLIENT_SECRET=cxlA1jgGRZEPp8hg4VNB5v2gx7aY6DUtJSwUUHzT + +PONYFM_DATASTORE=/vagrant-files diff --git a/resources/environments/.env.production b/resources/environments/.env.production new file mode 100644 index 00000000..bcc7bf00 Binary files /dev/null and b/resources/environments/.env.production differ diff --git a/resources/environments/.env.stage b/resources/environments/.env.stage new file mode 100644 index 00000000..199dcfa4 Binary files /dev/null and b/resources/environments/.env.stage differ diff --git a/resources/lang/en/pagination.php b/resources/lang/en/pagination.php new file mode 100644 index 00000000..fcab34b2 --- /dev/null +++ b/resources/lang/en/pagination.php @@ -0,0 +1,19 @@ + '« Previous', + 'next' => 'Next »', + +]; diff --git a/resources/lang/en/passwords.php b/resources/lang/en/passwords.php new file mode 100644 index 00000000..7c10cba1 --- /dev/null +++ b/resources/lang/en/passwords.php @@ -0,0 +1,22 @@ + 'Passwords must be at least six characters and match the confirmation.', + 'user' => "We can't find a user with that e-mail address.", + 'token' => 'This password reset token is invalid.', + 'sent' => 'We have e-mailed your password reset link!', + 'reset' => 'Your password has been reset!', + +]; diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php new file mode 100644 index 00000000..74dcad01 --- /dev/null +++ b/resources/lang/en/validation.php @@ -0,0 +1,117 @@ + 'The :attribute must be accepted.', + 'active_url' => 'The :attribute is not a valid URL.', + 'after' => 'The :attribute must be a date after :date.', + 'alpha' => 'The :attribute may only contain letters.', + 'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.', + 'alpha_num' => 'The :attribute may only contain letters and numbers.', + 'array' => 'The :attribute must be an array.', + 'before' => 'The :attribute must be a date before :date.', + 'between' => [ + 'numeric' => 'The :attribute must be between :min and :max.', + 'file' => 'The :attribute must be between :min and :max kilobytes.', + 'string' => 'The :attribute must be between :min and :max characters.', + 'array' => 'The :attribute must have between :min and :max items.', + ], + 'boolean' => 'The :attribute field must be true or false.', + 'confirmed' => 'The :attribute confirmation does not match.', + 'date' => 'The :attribute is not a valid date.', + 'date_format' => 'The :attribute does not match the format :format.', + 'different' => 'The :attribute and :other must be different.', + 'digits' => 'The :attribute must be :digits digits.', + 'digits_between' => 'The :attribute must be between :min and :max digits.', + 'email' => 'The :attribute must be a valid email address.', + 'filled' => 'The :attribute field is required.', + 'exists' => 'The selected :attribute is invalid.', + 'image' => 'The :attribute must be an image.', + 'in' => 'The selected :attribute is invalid.', + 'integer' => 'The :attribute must be an integer.', + 'ip' => 'The :attribute must be a valid IP address.', + 'max' => [ + 'numeric' => 'The :attribute may not be greater than :max.', + 'file' => 'The :attribute may not be greater than :max kilobytes.', + 'string' => 'The :attribute may not be greater than :max characters.', + 'array' => 'The :attribute may not have more than :max items.', + ], + 'mimes' => 'The :attribute must be a file of type: :values.', + 'min' => [ + 'numeric' => 'The :attribute must be at least :min.', + 'file' => 'The :attribute must be at least :min kilobytes.', + 'string' => 'The :attribute must be at least :min characters.', + 'array' => 'The :attribute must have at least :min items.', + ], + 'not_in' => 'The selected :attribute is invalid.', + 'numeric' => 'The :attribute must be a number.', + 'regex' => 'The :attribute format is invalid.', + 'required' => 'The :attribute field is required.', + 'required_if' => 'The :attribute field is required when :other is :value.', + 'required_with' => 'The :attribute field is required when :values is present.', + 'required_with_all' => 'The :attribute field is required when :values is present.', + 'required_without' => 'The :attribute field is required when :values is not present.', + 'required_without_all' => 'The :attribute field is required when none of :values are present.', + 'same' => 'The :attribute and :other must match.', + 'size' => [ + 'numeric' => 'The :attribute must be :size.', + 'file' => 'The :attribute must be :size kilobytes.', + 'string' => 'The :attribute must be :size characters.', + 'array' => 'The :attribute must contain :size items.', + ], + 'string' => 'The :attribute must be a string.', + 'timezone' => 'The :attribute must be a valid zone.', + 'unique' => 'The :attribute has already been taken.', + 'url' => 'The :attribute format is invalid.', + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + 'custom' => [ + 'attribute-name' => [ + 'rule-name' => 'custom-message', + ], + ], + + "audio" => "The :attribute must be an audio file.", + "audio_channels" => "The :attribute contains an invalid number of channels.", + "audio_format" => "The :attribute does not contain audio in a valid format.", + "required_when" => "The :attribute field cannot be left blank.", + "sample_rate" => "The :attribute has an invalid sample rate.", + "min_width" => "The :attribute is not wide enough.", + "min_height" => "The :attribute is not tall enough.", + "textarea_length" => "The :attribute must be less than 250 characters long.", // @TODO: Figure out how to retrieve the parameter from the validation rule + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => [], + +]; diff --git a/app/views/albums/index.blade.php b/resources/views/albums/index.blade.php similarity index 100% rename from app/views/albums/index.blade.php rename to resources/views/albums/index.blade.php diff --git a/app/views/albums/show.blade.php b/resources/views/albums/show.blade.php similarity index 100% rename from app/views/albums/show.blade.php rename to resources/views/albums/show.blade.php diff --git a/app/views/artists/index.blade.php b/resources/views/artists/index.blade.php similarity index 100% rename from app/views/artists/index.blade.php rename to resources/views/artists/index.blade.php diff --git a/app/views/artists/profile.blade.php b/resources/views/artists/profile.blade.php similarity index 100% rename from app/views/artists/profile.blade.php rename to resources/views/artists/profile.blade.php diff --git a/app/views/auth/login.blade.php b/resources/views/auth/login.blade.php similarity index 100% rename from app/views/auth/login.blade.php rename to resources/views/auth/login.blade.php diff --git a/app/views/auth/register.blade.php b/resources/views/auth/register.blade.php similarity index 100% rename from app/views/auth/register.blade.php rename to resources/views/auth/register.blade.php diff --git a/app/views/errors/400.blade.php b/resources/views/errors/400.blade.php similarity index 100% rename from app/views/errors/400.blade.php rename to resources/views/errors/400.blade.php diff --git a/app/views/errors/403.blade.php b/resources/views/errors/403.blade.php similarity index 100% rename from app/views/errors/403.blade.php rename to resources/views/errors/403.blade.php diff --git a/app/views/errors/404.blade.php b/resources/views/errors/404.blade.php similarity index 100% rename from app/views/errors/404.blade.php rename to resources/views/errors/404.blade.php diff --git a/app/views/errors/500.blade.php b/resources/views/errors/500.blade.php similarity index 100% rename from app/views/errors/500.blade.php rename to resources/views/errors/500.blade.php diff --git a/resources/views/errors/503.blade.php b/resources/views/errors/503.blade.php new file mode 100644 index 00000000..0380666a --- /dev/null +++ b/resources/views/errors/503.blade.php @@ -0,0 +1,47 @@ + + + + Be right back. + + + + + + +
+
+
Be right back.
+
+
+ + diff --git a/app/views/home/index.blade.php b/resources/views/home/index.blade.php similarity index 100% rename from app/views/home/index.blade.php rename to resources/views/home/index.blade.php diff --git a/app/views/pages/about.blade.php b/resources/views/pages/about.blade.php similarity index 100% rename from app/views/pages/about.blade.php rename to resources/views/pages/about.blade.php diff --git a/app/views/pages/faq.blade.php b/resources/views/pages/faq.blade.php similarity index 100% rename from app/views/pages/faq.blade.php rename to resources/views/pages/faq.blade.php diff --git a/app/views/playlists/index.blade.php b/resources/views/playlists/index.blade.php similarity index 100% rename from app/views/playlists/index.blade.php rename to resources/views/playlists/index.blade.php diff --git a/app/views/playlists/show.blade.php b/resources/views/playlists/show.blade.php similarity index 100% rename from app/views/playlists/show.blade.php rename to resources/views/playlists/show.blade.php diff --git a/app/views/shared/_app_layout.blade.php b/resources/views/shared/_app_layout.blade.php similarity index 94% rename from app/views/shared/_app_layout.blade.php rename to resources/views/shared/_app_layout.blade.php index 3f8be564..40b0b7b9 100644 --- a/app/views/shared/_app_layout.blade.php +++ b/resources/views/shared/_app_layout.blade.php @@ -32,7 +32,7 @@ @if (Auth::check())