Create models

This commit is contained in:
Kelvin Zhang 2015-08-30 13:29:12 +01:00
parent 270915227a
commit b15b24b772
44 changed files with 5150 additions and 144 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
Homestead.yaml Homestead.yaml
.env .env
.vagrant .vagrant
_ide_helper.php

318
app/Album.php Normal file
View file

@ -0,0 +1,318 @@
<?php
use Cover;
use Helpers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\URL;
use Traits\SlugTrait;
class Album extends Model
{
use SoftDeletes, SlugTrait;
protected $dates = ['deleted_at'];
public static function summary()
{
return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'cover_id', 'comment_count',
'download_count', 'view_count', 'favourite_count');
}
public function scopeUserDetails($query)
{
if (Auth::check()) {
$query->with([
'users' => function ($query) {
$query->whereUserId(Auth::user()->id);
}
]);
}
return !$query;
}
protected $table = 'albums';
public function user()
{
return $this->belongsTo('User');
}
public function users()
{
return $this->hasMany('ResourceUser');
}
public function favourites()
{
return $this->hasMany('Favourite');
}
public function cover()
{
return $this->belongsTo('Image');
}
public function tracks()
{
return $this->hasMany('Track')->orderBy('track_number', 'asc');
}
public function comments()
{
return $this->hasMany('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' => $userRow->view_count,
'downloads' => $userRow->download_count,
],
'is_favourited' => $userRow->is_favourited
];
}
return [
'id' => $album->id,
'track_count' => $album->track_count,
'title' => $album->title,
'slug' => $album->slug,
'created_at' => $album->created_at,
'stats' => [
'views' => $album->view_count,
'downloads' => $album->download_count,
'comments' => $album->comment_count,
'favourites' => $album->favourite_count
],
'covers' => [
'small' => $album->getCoverUrl(Image::SMALL),
'normal' => $album->getCoverUrl(Image::NORMAL)
],
'url' => $album->url,
'user' => [
'id' => $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;
}
}

79
app/Comment.php Normal file
View file

@ -0,0 +1,79 @@
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Comment extends Model
{
use SoftDeletes;
protected $table = 'comments';
protected $dates = ['deleted_at'];
public function user()
{
return $this->belongsTo('User');
}
public function track()
{
return $this->belongsTo('Track');
}
public function album()
{
return $this->belongsTo('Album');
}
public function playlist()
{
return $this->belongsTo('Playlist');
}
public function profile()
{
return $this->belongsTo('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;
}
}
}
}
}
}

63
app/Favourite.php Normal file
View file

@ -0,0 +1,63 @@
<?php
use Illuminate\Database\Eloquent\Model;
class Favourite extends Model
{
protected $table = 'favourites';
public $timestamps = false;
/*
|--------------------------------------------------------------------------
| Relationships
|--------------------------------------------------------------------------
*/
public function user()
{
return $this->belongsTo('User');
}
public function track()
{
return $this->belongsTo('Track');
}
public function album()
{
return $this->belongsTo('Album');
}
public function playlist()
{
return $this->belongsTo('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);
}
}

10
app/Follower.php Normal file
View file

@ -0,0 +1,10 @@
<?php
use Illuminate\Database\Eloquent\Model;
class Follower extends Model
{
protected $table = 'followers';
public $timestamps = false;
}

11
app/Genre.php Normal file
View file

@ -0,0 +1,11 @@
<?php
use Illuminate\Database\Eloquent\Model;
use Traits\SlugTrait;
class Genre extends Model
{
protected $table = 'genres';
use SlugTrait;
}

114
app/Image.php Normal file
View file

@ -0,0 +1,114 @@
<?php
use External;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL;
class Image extends Model
{
const NORMAL = 1;
const ORIGINAL = 2;
const THUMBNAIL = 3;
const SMALL = 4;
public static $ImageTypes = [
self::NORMAL => ['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($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, 777, true);
}
}
}

8
app/License.php Normal file
View file

@ -0,0 +1,8 @@
<?php
use Illuminate\Database\Eloquent\Model;
class License extends Model
{
protected $table = 'licenses';
}

67
app/News.php Normal file
View file

@ -0,0 +1,67 @@
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
class News extends Model
{
public static function getNews($start = 0, $end = 4)
{
$feed = new SimplePie();
$feed->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);
}
}

18
app/PinnedPlaylist.php Normal file
View file

@ -0,0 +1,18 @@
<?php
use Illuminate\Database\Eloquent\Model;
class PinnedPlaylist extends Model
{
protected $table = 'pinned_playlists';
public function user()
{
return $this->belongsTo('User');
}
public function playlist()
{
return $this->belongsTo('Playlist');
}
}

218
app/Playlist.php Normal file
View file

@ -0,0 +1,218 @@
<?php
use Helpers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\URL;
use Traits\SlugTrait;
class Playlist extends Model
{
protected $table = 'playlists';
use SoftDeletes, SlugTrait;
protected $dates = ['deleted_at'];
public static function summary()
{
return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'is_public', 'description', 'comment_count',
'download_count', 'view_count', 'favourite_count');
}
public function scopeUserDetails($query)
{
if (Auth::check()) {
$query->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' => $userRow->view_count,
'downloads' => $userRow->download_count,
],
'is_favourited' => $userRow->is_favourited
];
}
return [
'id' => $playlist->id,
'track_count' => $playlist->track_count,
'title' => $playlist->title,
'slug' => $playlist->slug,
'created_at' => $playlist->created_at,
'is_public' => $playlist->is_public,
'stats' => [
'views' => $playlist->view_count,
'downloads' => $playlist->download_count,
'comments' => $playlist->comment_count,
'favourites' => $playlist->favourite_count
],
'covers' => [
'small' => $playlist->getCoverUrl(Image::SMALL),
'normal' => $playlist->getCoverUrl(Image::NORMAL)
],
'url' => $playlist->url,
'user' => [
'id' => $playlist->user->id,
'name' => $playlist->user->display_name,
'url' => $playlist->user->url,
],
'user_data' => $userData,
'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('Track')
->withPivot('position')
->withTimestamps()
->orderBy('position', 'asc');
}
public function users()
{
return $this->hasMany('ResourceUser');
}
public function comments()
{
return $this->hasMany('Comment')->orderBy('created_at', 'desc');
}
public function pins()
{
return $this->hasMany('PinnedPlaylist');
}
public function user()
{
return $this->belongsTo('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;
}
}

74
app/ProfileRequest.php Normal file
View file

@ -0,0 +1,74 @@
<?php
use Helpers;
use Illuminate\Support\Facades\DB;
class ProfileRequest
{
private $_id = null;
private $_data = null;
public static function load($data)
{
$req = new ProfileRequest();
$req->_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
];
}
}

82
app/ResourceLogItem.php Normal file
View file

@ -0,0 +1,82 @@
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Request;
class ResourceLogItem extends Model
{
protected $table = 'resource_log_items';
public $timestamps = false;
const VIEW = 1;
const DOWNLOAD = 2;
const PLAY = 3;
public static function logItem($resourceType, $resourceId, $logType, $formatId = null)
{
$resourceIdColumn = $resourceType . '_id';
$logItem = new ResourceLogItem();
$logItem->{$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 . ')')
]);
}
}
}

36
app/ResourceUser.php Normal file
View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Eloquent\Model;
class ResourceUser extends Model
{
protected $table = 'resource_users';
public $timestamps = false;
public static function get($userId, $resourceType, $resourceId)
{
$resourceIdColumn = $resourceType . '_id';
$existing = self::where($resourceIdColumn, '=', $resourceId)->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;
}
}

8
app/ShowSong.php Normal file
View file

@ -0,0 +1,8 @@
<?php
use Illuminate\Database\Eloquent\Model;
class ShowSong extends Model
{
protected $table = 'show_songs';
}

627
app/Track.php Normal file
View file

@ -0,0 +1,627 @@
<?php
use Cover;
use External;
use getid3_writetags;
use Helpers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
use Traits\SlugTrait;
class Track extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
use SlugTrait {
SlugTrait::setTitleAttribute as setTitleAttributeSlug;
}
public static $Formats = [
'FLAC' => [
'index' => 0,
'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,
'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,
'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,
'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,
'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' => '<iframe src="' . URL::to('t' . $track->id . '/embed') . '" width="100%" height="150" allowTransparency="true" frameborder="0" seamless allowfullscreen></iframe>',
'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' => $userRow->view_count,
'plays' => $userRow->play_count,
'downloads' => $userRow->download_count,
],
'is_favourited' => $userRow->is_favourited
];
}
return [
'id' => $track->id,
'title' => $track->title,
'user' => [
'id' => $track->user->id,
'name' => $track->user->display_name,
'url' => $track->user->url
],
'stats' => [
'views' => $track->view_count,
'plays' => $track->play_count,
'downloads' => $track->download_count,
'comments' => $track->comment_count,
'favourites' => $track->favourite_count
],
'url' => $track->url,
'slug' => $track->slug,
'is_vocal' => $track->is_vocal,
'is_explicit' => $track->is_explicit,
'is_downloadable' => $track->is_downloadable,
'is_published' => $track->isPublished(),
'published_at' => $track->published_at,
'duration' => $track->duration,
'genre' => $track->genre != null
?
[
'id' => $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('Genre');
}
public function trackType()
{
return $this->belongsTo('TrackType', 'track_type_id');
}
public function comments()
{
return $this->hasMany('Comment')->orderBy('created_at', 'desc');
}
public function favourites()
{
return $this->hasMany('Favourite');
}
public function cover()
{
return $this->belongsTo('Image');
}
public function showSongs()
{
return $this->belongsToMany('ShowSong');
}
public function users()
{
return $this->hasMany('ResourceUser');
}
public function user()
{
return $this->belongsTo('User');
}
public function album()
{
return $this->belongsTo('Album');
}
public function trackFiles()
{
return $this->hasMany('TrackFile');
}
public function getYear()
{
return date('Y', strtotime($this->release_date));
}
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->attributes['released_at'] !== null) {
return $this->attributes['released_at'];
}
if ($this->attributes['published_at'] !== null) {
return Str::limit($this->$this->attributes['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, 777, 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 (self::$Formats as $format => $data) {
$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->title : '') . ' ';
$command .= '--copyright ' . escapeshellarg('© ' . $this->year . ' ' . $this->user->display_name) . ' ';
$command .= '--comment "' . 'Downloaded from: https://pony.fm/' . '" ';
$command .= '--encodingTool "' . 'Pony.fm' . '" ';
$command .= '--encodedBy "' . '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->getCoverUrl() . ' ';
}
$command .= '--overWrite';
External::execute($command);
}
/** @noinspection PhpUnusedPrivateMethodInspection */
private function updateTagsWithGetId3($format)
{
require_once(app_path() . '/library/getid3/getid3.php');
require_once(app_path() . '/library/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->title : ''],
'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->file)) {
$tagWriter->tag_data['attached_picture'][0] = [
'data' => file_get_contents($this->cover->file),
'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('There were some warnings:<br />' . implode('<br /><br />', $tagWriter->warnings));
}
} else {
Log::error('Failed to write tags!<br />' . implode('<br /><br />', $tagWriter->errors));
}
}
private function getCacheKey($key)
{
return 'track-' . $this->id . '-' . $key;
}
}

117
app/TrackFile.php Normal file
View file

@ -0,0 +1,117 @@
<?php
use Helpers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\URL;
class TrackFile extends Model
{
public function track()
{
return $this->belongsTo('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;
}
}

8
app/TrackType.php Normal file
View file

@ -0,0 +1,8 @@
<?php
use Illuminate\Database\Eloquent\Model;
class TrackType extends Model
{
protected $table = 'track_types';
}

12
app/Traits/SlugTrait.php Normal file
View file

@ -0,0 +1,12 @@
<?php
namespace Traits;
use Illuminate\Support\Str;
trait SlugTrait {
public function setTitleAttribute($value) {
$this->slug = Str::slug($value);
$this->attributes['title'] = $value;
}
}

View file

@ -1,35 +1,142 @@
<?php <?php
namespace App; use Cover;
use Gravatar;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Reminders\RemindableInterface;
use Illuminate\Auth\UserInterface;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Support\Facades\URL;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Support\Str;
use Ratchet\Wamp\Exception;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract class User extends Model implements UserInterface, RemindableInterface
{ {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users'; protected $table = 'users';
protected $hidden = ['password_hash', 'password_salt', 'bio'];
/** public function scopeUserDetails($query)
* The attributes that are mass assignable. {
* if (Auth::check()) {
* @var array $query->with([
*/ 'users' => function ($query) {
protected $fillable = ['name', 'email', 'password']; $query->whereUserId(Auth::user()->id);
}
/** ]);
* The attributes excluded from the model's JSON form. }
*
* @var array return !$query;
*/ }
protected $hidden = ['password', 'remember_token'];
public function avatar()
{
return $this->belongsTo('Image');
}
public function users()
{
return $this->hasMany('ResourceUser', 'artist_id');
}
public function comments()
{
return $this->hasMany('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&section=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";
}
} }

View file

@ -6,7 +6,11 @@
"type": "project", "type": "project",
"require": { "require": {
"php": ">=5.5.9", "php": ">=5.5.9",
"laravel/framework": "5.1.*" "laravel/framework": "5.1.*",
"codescale/ffmpeg-php": "2.7.0",
"simplepie/simplepie": "1.3.1",
"intouch/laravel-newrelic": "*",
"barryvdh/laravel-ide-helper": "^2.1"
}, },
"require-dev": { "require-dev": {
"fzaninotto/faker": "~1.4", "fzaninotto/faker": "~1.4",
@ -36,6 +40,8 @@
"php artisan clear-compiled" "php artisan clear-compiled"
], ],
"post-update-cmd": [ "post-update-cmd": [
"php artisan clear-compiled",
"php artisan ide-helper:generate",
"php artisan optimize" "php artisan optimize"
], ],
"post-root-package-install": [ "post-root-package-install": [

408
composer.lock generated
View file

@ -4,8 +4,71 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "5c6026b96e6fa11a641b51a6ba976f5e", "hash": "2a02c7e5a9f643f5362f00ae16d1ce04",
"packages": [ "packages": [
{
"name": "barryvdh/laravel-ide-helper",
"version": "v2.1.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-ide-helper.git",
"reference": "83999f8467374adcb8893f566c9171c9d9691f50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/83999f8467374adcb8893f566c9171c9d9691f50",
"reference": "83999f8467374adcb8893f566c9171c9d9691f50",
"shasum": ""
},
"require": {
"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": {
"doctrine/dbal": "~2.3"
},
"suggest": {
"doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"autoload": {
"psr-4": {
"Barryvdh\\LaravelIdeHelper\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
"keywords": [
"autocomplete",
"codeintel",
"helper",
"ide",
"laravel",
"netbeans",
"phpdoc",
"phpstorm",
"sublime"
],
"time": "2015-08-13 11:40:00"
},
{ {
"name": "classpreloader/classpreloader", "name": "classpreloader/classpreloader",
"version": "2.0.0", "version": "2.0.0",
@ -60,6 +123,50 @@
], ],
"time": "2015-06-28 21:39:13" "time": "2015-06-28 21:39:13"
}, },
{
"name": "codescale/ffmpeg-php",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/CodeScaleInc/ffmpeg-php.git",
"reference": "c4e3e71ac24116e9a8e29b423f0d5e13de980c02"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CodeScaleInc/ffmpeg-php/zipball/c4e3e71ac24116e9a8e29b423f0d5e13de980c02",
"reference": "c4e3e71ac24116e9a8e29b423f0d5e13de980c02",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"autoload": {
"classmap": [
"."
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"New BSD"
],
"authors": [
{
"name": "char0n (Vladimír Gorej, CodeScale s.r.o.)",
"email": "gorej@codescale.net",
"homepage": "http://www.codescale.net/",
"role": "Development lead"
}
],
"description": "PHP wrapper for FFmpeg application",
"homepage": "http://freecode.com/projects/ffmpegphp",
"keywords": [
"audio",
"ffmpeg",
"video"
],
"time": "2013-05-05 09:10:04"
},
{ {
"name": "danielstjules/stringy", "name": "danielstjules/stringy",
"version": "1.10.0", "version": "1.10.0",
@ -216,6 +323,91 @@
], ],
"time": "2014-12-20 21:24:13" "time": "2014-12-20 21:24:13"
}, },
{
"name": "intouch/laravel-newrelic",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/In-Touch/laravel-newrelic.git",
"reference": "7213ce8478a309c31489f9b0872e4511166dbe80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/In-Touch/laravel-newrelic/zipball/7213ce8478a309c31489f9b0872e4511166dbe80",
"reference": "7213ce8478a309c31489f9b0872e4511166dbe80",
"shasum": ""
},
"require": {
"illuminate/support": "5.*",
"intouch/newrelic": ">=1.0.2",
"php": ">=5.4.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Intouch\\LaravelNewrelic": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache 2.0"
],
"authors": [
{
"name": "Patrick Leckey",
"email": "pleckey@intouchinsight.com"
}
],
"description": "Laravel 5 NewRelic Integration",
"homepage": "https://github.com/In-Touch/laravel-newrelic",
"keywords": [
"laravel",
"new relic",
"newrelic"
],
"time": "2015-03-11 18:34:13"
},
{
"name": "intouch/newrelic",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/In-Touch/newrelic.git",
"reference": "20db6cb25a9eb88e504e16829077c56828c176cc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/In-Touch/newrelic/zipball/20db6cb25a9eb88e504e16829077c56828c176cc",
"reference": "20db6cb25a9eb88e504e16829077c56828c176cc",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Intouch\\Newrelic": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache 2.0"
],
"authors": [
{
"name": "Patrick Leckey",
"email": "pleckey@intouchinsight.com"
}
],
"description": "Namespaced Wrapper for NewRelic PHP Agent",
"homepage": "http://github.com/In-Touch/newrelic/",
"keywords": [
"new relic",
"newrelic"
],
"time": "2014-08-18 12:08:45"
},
{ {
"name": "jakub-onderka/php-console-color", "name": "jakub-onderka/php-console-color",
"version": "0.1", "version": "0.1",
@ -572,16 +764,16 @@
}, },
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "1.16.0", "version": "1.17.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Seldaek/monolog.git", "url": "https://github.com/Seldaek/monolog.git",
"reference": "c0c0b4bee3aabce7182876b0d912ef2595563db7" "reference": "877ae631713cc961952df713ae785735b90df682"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/c0c0b4bee3aabce7182876b0d912ef2595563db7", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/877ae631713cc961952df713ae785735b90df682",
"reference": "c0c0b4bee3aabce7182876b0d912ef2595563db7", "reference": "877ae631713cc961952df713ae785735b90df682",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -598,7 +790,7 @@
"php-console/php-console": "^3.1.3", "php-console/php-console": "^3.1.3",
"phpunit/phpunit": "~4.5", "phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0", "phpunit/phpunit-mock-objects": "2.3.0",
"raven/raven": "~0.8", "raven/raven": "~0.11",
"ruflin/elastica": ">=0.90 <3.0", "ruflin/elastica": ">=0.90 <3.0",
"swiftmailer/swiftmailer": "~5.3", "swiftmailer/swiftmailer": "~5.3",
"videlalvaro/php-amqplib": "~2.4" "videlalvaro/php-amqplib": "~2.4"
@ -644,7 +836,7 @@
"logging", "logging",
"psr-3" "psr-3"
], ],
"time": "2015-08-09 17:44:44" "time": "2015-08-30 11:40:25"
}, },
{ {
"name": "mtdowling/cron-expression", "name": "mtdowling/cron-expression",
@ -782,6 +974,55 @@
], ],
"time": "2015-07-14 17:31:05" "time": "2015-07-14 17:31:05"
}, },
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{ {
"name": "psr/log", "name": "psr/log",
"version": "1.0.0", "version": "1.0.0",
@ -892,6 +1133,60 @@
], ],
"time": "2015-07-16 15:26:57" "time": "2015-07-16 15:26:57"
}, },
{
"name": "simplepie/simplepie",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/ce53709778bc1e2e4deda1651b66e5081398d5cc",
"reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"type": "library",
"autoload": {
"psr-0": {
"SimplePie": "library"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ryan Parman",
"homepage": "http://ryanparman.com/",
"role": "Creator, alumnus developer"
},
{
"name": "Geoffrey Sneddon",
"homepage": "http://gsnedders.com/",
"role": "Alumnus developer"
},
{
"name": "Ryan McCue",
"email": "me@ryanmccue.info",
"homepage": "http://ryanmccue.info/",
"role": "Developer"
}
],
"description": "A simple Atom/RSS parsing library for PHP",
"homepage": "http://simplepie.org/",
"keywords": [
"atom",
"feeds",
"rss"
],
"time": "2012-10-30 17:54:03"
},
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
"version": "v5.4.1", "version": "v5.4.1",
@ -945,6 +1240,56 @@
], ],
"time": "2015-06-06 14:19:39" "time": "2015-06-06 14:19:39"
}, },
{
"name": "symfony/class-loader",
"version": "v2.7.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/ClassLoader.git",
"reference": "2fccbc544997340808801a7410cdcb96dd12edc4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ClassLoader/zipball/2fccbc544997340808801a7410cdcb96dd12edc4",
"reference": "2fccbc544997340808801a7410cdcb96dd12edc4",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
"symfony/finder": "~2.0,>=2.0.5",
"symfony/phpunit-bridge": "~2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\ClassLoader\\": ""
}
},
"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 ClassLoader Component",
"homepage": "https://symfony.com",
"time": "2015-06-25 12:52:11"
},
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v2.7.3", "version": "v2.7.3",
@ -1912,55 +2257,6 @@
], ],
"time": "2015-04-02 19:54:00" "time": "2015-04-02 19:54:00"
}, },
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{ {
"name": "phpspec/php-diff", "name": "phpspec/php-diff",
"version": "v1.0.2", "version": "v1.0.2",

View file

@ -144,6 +144,8 @@ return [
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
], ],
/* /*

View file

@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration {
public function up() {
Schema::create('users', function(Blueprint $table) {
$table->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');
}
}

View file

@ -0,0 +1,128 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateTracksTable extends Migration {
public function up() {
Schema::create('licenses', function($table){
$table->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');
}
}

View file

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateImagesTable extends Migration {
public function up() {
Schema::create('images', function($table) {
$table->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');
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateAlbums extends Migration {
public function up() {
Schema::create('albums', function($table) {
$table->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');
}
}

View file

@ -0,0 +1,67 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreatePlaylists extends Migration {
public function up() {
Schema::create('playlists', function($table) {
$table->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');
}
}

View file

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateComments extends Migration {
public function up() {
Schema::create('comments', function($table){
$table->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');
}
}

View file

@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateUserTables extends Migration {
public function up() {
Schema::create('resource_users', function($table){
$table->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');
}
}

View file

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateFavourites extends Migration {
public function up() {
Schema::create('favourites', function($table){
$table->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');
}
}

View file

@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateFollowers extends Migration {
public function up() {
Schema::create('followers', function($table){
$table->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');
}
}

View file

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
class Oauth extends Migration {
public function up() {
Schema::create('oauth2_tokens', function($table) {
$table->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');
}
}

View file

@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateNewsTable extends Migration {
public function up() {
Schema::create('news', function($table){
$table->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');
}
}

View file

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateLatestColumn extends Migration {
public function up() {
Schema::table('tracks', function($table) {
$table->boolean('is_latest')->notNullable()->indexed();
});
DB::update('
UPDATE
tracks
SET
is_latest = true
WHERE
(
SELECT
t2.id
FROM
(SELECT id, user_id FROM tracks WHERE published_at IS NOT NULL AND deleted_at IS NULL) AS t2
WHERE
t2.user_id = tracks.user_id
ORDER BY
created_at DESC
LIMIT 1
) = tracks.id
AND
published_at IS NOT NULL');
}
public function down() {
Schema::table('tracks', function($table) {
$table->dropColumn('is_latest');
});
}
}

View file

@ -0,0 +1,23 @@
<?php
use Entities\Track;
use Illuminate\Database\Migrations\Migration;
class CreateTrackHashes extends Migration {
public function up() {
Schema::table('tracks', function($table) {
$table->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');
});
}
}

View file

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
class TrackIsListed extends Migration {
public function up() {
Schema::table('tracks', function($table) {
$table->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');
});
}
}

View file

@ -0,0 +1,16 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Entities\Track;
class UpdateTrackHash extends Migration {
public function up() {
foreach (Track::with('user')->get() as $track) {
$track->updateHash();
$track->save();
}
}
public function down() {
}
}

View file

@ -1,34 +0,0 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}
}

View file

@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePasswordResetsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token')->index();
$table->timestamp('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('password_resets');
}
}

View file

@ -0,0 +1,17 @@
<?php
use Illuminate\Database\Migrations\Migration;
class AddRememberMeField extends Migration {
public function up() {
Schema::table('users', function($table) {
$table->string('remember_token', 100)->nullable()->indexed();
});
}
public function down() {
Schema::table('users', function($table) {
$table->dropColumn('remember_token');
});
}
}

View file

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
class AddArchivedProfileField extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function ( $table ) {
$table->boolean( 'is_archived' )->default(false);
} );
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table( 'users', function ( $table ) {
$table->dropColumn( 'is_archived' );
} );
}
}

View file

@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
class CreateTrackFilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Fill in the table
DB::transaction(function () {
Schema::create('track_files', function ($table) {
$table->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');
}
}