Mega commit... Following, design changes, share/embed code and more.

This commit is contained in:
nelsonlaquet 2013-08-28 22:19:24 -05:00
parent d63ef0e65c
commit 1dff7cb36f
52 changed files with 636 additions and 154 deletions

View file

@ -28,7 +28,17 @@
}
public function getShow($id) {
$album = Album::with(['tracks' => function($query) { $query->details(); }, 'tracks.cover', 'tracks.genre', 'tracks.user', 'user', 'comments' => function($query) { $query->with('user'); }])->details()->find($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);
@ -49,12 +59,12 @@
$query = Album::summary()
->with('user', 'user.avatar', 'cover')
->details()
->userDetails()
->orderBy('created_at', 'desc')
->where('track_count', '>', 0);
$count = $query->count();
$perPage = 18;
$perPage = 40;
$query->skip(($page - 1) * $perPage)->take($perPage);
$albums = [];

View file

@ -30,8 +30,8 @@
'track.user',
'album.cover',
'album.user',
'track' => function($query) { $query->details(); },
'album' => function($query) { $query->details(); }])->get();
'track' => function($query) { $query->userDetails(); },
'album' => function($query) { $query->userDetails(); }])->get();
$tracks = [];
$albums = [];
@ -56,7 +56,7 @@
if (!$user)
App::abort(404);
$query = Track::summary()->with('genre', 'cover', 'user')->details()->whereUserId($user->id)->whereNotNull('published_at');
$query = Track::summary()->with('genre', 'cover', 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at');
$tracks = [];
$singles = [];
@ -83,11 +83,11 @@
}
public function getShow($slug) {
$user = User::whereSlug($slug)->with(['comments' => function ($query) { $query->with('user'); }])->first();
$user = User::whereSlug($slug)->userDetails()->with(['comments' => function ($query) { $query->with('user'); }])->first();
if (!$user)
App::abort(404);
$trackQuery = Track::summary()->with('genre', 'cover', 'user')->details()->whereUserId($user->id)->whereNotNull('published_at')->orderBy('created_at', 'desc')->take(20);
$trackQuery = Track::summary()->with('genre', 'cover', 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at')->orderBy('created_at', 'desc')->take(20);
$latestTracks = [];
foreach ($trackQuery->get() as $track) {
@ -99,6 +99,17 @@
$comments[] = Comment::mapPublic($comment);
}
$userData = [
'is_following' => false
];
if ($user->users->count()) {
$userRow = $user->users[0];
$userData = [
'is_following' => $userRow->is_followed
];
}
return Response::json([
'artist' => [
'id' => $user->id,
@ -112,9 +123,11 @@
'followers' => [],
'following' => [],
'latest_tracks' => $latestTracks,
'comments' => ['count' => count($comments), 'list' => $comments],
'comments' => $comments,
'bio' => $user->bio,
'mlpforums_username' => $user->mlpforums_name
'mlpforums_username' => $user->mlpforums_name,
'message_url' => $user->message_url,
'user_data' => $userData
]
], 200);
}
@ -128,7 +141,7 @@
->where('track_count', '>', 0);
$count = $query->count();
$perPage = 18;
$perPage = 40;
$query->skip(($page - 1) * $perPage)->take($perPage);
$users = [];

View file

@ -14,18 +14,22 @@
class DashboardController extends \ApiControllerBase {
public function getIndex() {
$query = Track::summary()->with(['genre', 'user', 'cover'])->details()->whereNotNull('published_at')->orderBy('published_at', 'desc')->take(30);
if (!Auth::check() || !Auth::user()->can_see_explicit_content)
$query->whereIsExplicit(false);
$recentQuery = Track::summary()
->with(['genre', 'user', 'cover', 'user.avatar'])
->userDetails()
->explicitFilter()
->published()
->orderBy('published_at', 'desc')
->take(30);
$tracks = [];
$recentTracks = [];
foreach ($query->get() as $track) {
$tracks[] = Track::mapPublicTrackSummary($track);
foreach ($recentQuery->get() as $track) {
$recentTracks[] = Track::mapPublicTrackSummary($track);
}
return Response::json([
'recent_tracks' => $tracks,
'popular_tracks' => $tracks], 200);
'recent_tracks' => $recentTracks,
'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content)], 200);
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace Api\Web;
use Commands\ToggleFavouriteCommand;
use Commands\ToggleFollowingCommand;
use Illuminate\Support\Facades\Input;
class FollowController extends \ApiControllerBase {
public function postToggle() {
return $this->execute(new ToggleFollowingCommand(Input::get('type'), Input::get('id')));
}
}

View file

@ -40,13 +40,13 @@
$query = Playlist::summary()
->with('user', 'user.avatar', 'tracks', 'tracks.cover')
->details()
->userDetails()
->orderBy('created_at', 'desc')
->where('track_count', '>', 0)
->whereIsPublic(true);
$count = $query->count();
$perPage = 18;
$perPage = 40;
$query->skip(($page - 1) * $perPage)->take($perPage);
$playlists = [];
@ -59,7 +59,7 @@
}
public function getShow($id) {
$playlist = Playlist::with(['tracks.user', 'tracks.genre', 'tracks.cover', 'tracks.album', 'tracks' => function($query) { $query->details(); }, 'comments', 'comments.user'])->details()->find($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');
@ -73,7 +73,7 @@
public function getPinned() {
$query = Playlist
::details()
::userDetails()
->with('tracks', 'tracks.cover', 'tracks.user', 'user')
->join('pinned_playlists', function($join) {
$join->on('playlist_id', '=', 'playlists.id');

View file

@ -31,7 +31,7 @@
}
public function getShow($id) {
$track = Track::details()->withComments()->find($id);
$track = Track::userDetails()->withComments()->find($id);
if (!$track || !$track->canView(Auth::user()))
return $this->notFound('Track not found!');
@ -43,20 +43,6 @@
return Response::json(['track' => Track::mapPublicTrackShow($track)], 200);
}
public function getRecent() {
$query = Track::summary()->details()->with(['genre', 'user', 'cover'])->whereNotNull('published_at')->orderBy('published_at', 'desc')->take(30);
if (!Auth::check() || !Auth::user()->can_see_explicit_content)
$query->whereIsExplicit(false);
$tracks = [];
foreach ($query->get() as $track) {
$tracks[] = Track::mapPublicTrackSummary($track);
}
return Response::json($tracks, 200);
}
public function getIndex() {
$page = 1;
$perPage = 45;
@ -65,8 +51,9 @@
$page = Input::get('page');
$query = Track::summary()
->details()
->whereNotNull('published_at')
->userDetails()
->explicitFilter()
->published()
->with('user', 'genre', 'cover', 'album', 'album.user');
$this->applyFilters($query);

View file

@ -11,6 +11,7 @@ class CreateUserTables extends Migration {
$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');
@ -20,12 +21,13 @@ class CreateUserTables extends Migration {
$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');
$table->foreign('album_id')->references('id')->on('albums');
$table->foreign('playlist_id')->references('id')->on('playlists');
$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']);
$table->unique(['user_id', 'track_id', 'album_id', 'playlist_id', 'artist_id']);
});
Schema::create('resource_log_items', function($table){

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,57 @@
<?php
namespace Commands;
use Entities\Album;
use Entities\Favourite;
use Entities\Follower;
use Entities\Playlist;
use Entities\ResourceUser;
use Entities\Track;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class ToggleFollowingCommand extends CommandBase {
private $_resourceType;
private $_resourceId;
function __construct($resourceType, $resourceId) {
$this->_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]);
}
}

View file

@ -19,7 +19,7 @@
return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'cover_id', 'comment_count', 'download_count', 'view_count', 'favourite_count');
}
public function scopeDetails($query) {
public function scopeUserDetails($query) {
if (Auth::check()) {
$query->with(['users' => function($query) {
$query->whereUserId(Auth::user()->id);
@ -52,7 +52,7 @@
}
public function comments(){
return $this->hasMany('Entities\Comment');
return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc');
}
public static function mapPublicAlbumShow($album) {
@ -81,6 +81,11 @@
$data['comments'] = $comments;
$data['formats'] = $formats;
$data['description'] = $album->description;
$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;
}

View file

@ -0,0 +1,9 @@
<?php
namespace Entities;
class Follower extends \Eloquent {
protected $table = 'followers';
public $timestamps = false;
}

View file

@ -18,7 +18,7 @@
return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'is_public', 'description', 'comment_count', 'download_count', 'view_count', 'favourite_count');
}
public function scopeDetails($query) {
public function scopeUserDetails($query) {
if (Auth::check()) {
$query->with(['users' => function($query) {
$query->whereUserId(Auth::user()->id);
@ -53,6 +53,11 @@
$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;
}
@ -117,7 +122,7 @@
}
public function comments(){
return $this->hasMany('Entities\Comment');
return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc');
}
public function pins() {

View file

@ -8,6 +8,7 @@
use Helpers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
@ -31,7 +32,7 @@
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 scopeDetails($query) {
public function scopeUserDetails($query) {
if (Auth::check()) {
$query->with(['users' => function($query) {
$query->whereUserId(Auth::user()->id);
@ -41,10 +42,52 @@
return !$query;
}
public function scopePublished($query) {
$query->whereNotNull('published_at');
}
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) {
$tracks = Cache::remember('popular_tracks-' . ($allowExplicit ? 'explicit' : 'safe'), 5, function() use ($allowExplicit) {
$query = static
::with(['user', 'genre', 'cover', 'user.avatar'])
->published()
->whereIsExplicit($allowExplicit)
->join(DB::raw('
( SELECT `track_id`, `created_at`
FROM `resource_log_items`
WHERE `created_at` > now() - INTERVAL 1 DAY
) AS ranged_plays'),
'tracks.id', '=', 'ranged_plays.track_id')
->groupBy('id')
->orderBy('plays', 'desc')
->take(20);
return $query->get(['*', DB::raw('count(*) as plays')]);
});
$results = [];
$i = 0;
foreach($tracks as $track) {
if ($i < $count) {
$results[] = self::mapPublicTrackSummary($track);
$i++;
} else {
break;
}
}
return $results;
}
public static function mapPublicTrackShow($track) {
$returnValue = self::mapPublicTrackSummary($track);
$returnValue['description'] = $track->description;
@ -76,6 +119,15 @@
];
}
$returnValue['share'] = [
'url' => URL::to('/t' . $track->id),
'html' => '<iframe src="https://pony.fm/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;
@ -191,7 +243,7 @@
}
public function comments(){
return $this->hasMany('Entities\Comment');
return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc');
}
public function favourites() {

View file

@ -6,6 +6,7 @@
use Gravatar;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
use Ratchet\Wamp\Exception;
@ -14,18 +15,36 @@
protected $table = 'users';
protected $hidden = ['password_hash', 'password_salt', 'bio'];
public function scopeUserDetails($query) {
if (Auth::check()) {
$query->with(['users' => function($query) {
$query->whereUserId(Auth::user()->id);
}]);
}
return !$query;
}
public function avatar() {
return $this->belongsTo('Entities\Image');
}
public function comments(){
return $this->hasMany('Entities\Comment', 'profile_id');
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 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();
}

View file

@ -52,7 +52,6 @@
Route::get('/playlists/show/{id}', 'Api\Web\PlaylistsController@getShow');
Route::get('/tracks/recent', 'Api\Web\TracksController@getRecent');
Route::get('/tracks', 'Api\Web\TracksController@getIndex');
Route::get('/tracks/{id}', 'Api\Web\TracksController@getShow')->where('id', '\d+');
@ -90,6 +89,8 @@
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::group(['before' => 'auth'], function() {

View file

@ -1,6 +1,28 @@
@extends('shared._layout')
@section('content')
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '186765381447538',
status: true,
cookie: true,
xfbml: true
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<header>
<a href="/">Pony.fm</a>
<div class="now-playing">
@ -51,7 +73,7 @@
</ui-view>
</div>
<ng-include src="'templates/partials/upload-dialog.html'" />
<ng-include src="'templates/partials/upload-dialog.html'"></ng-include>
@endsection
@ -76,4 +98,7 @@
</script>
{{ Assets::scriptIncludes() }}
<script src="http://platform.tumblr.com/v1/share.js"></script>
@endsection

View file

@ -10,4 +10,4 @@
<IfModule xsendfile_module>
XSendFile On
</IfModule>
</IfModule>

View file

@ -5,13 +5,22 @@ window.pfm.preloaders['album'] = [
]
angular.module('ponyfm').controller "album", [
'$scope', 'albums', '$state', 'playlists', 'auth'
($scope, albums, $state, playlists, auth) ->
'$scope', 'albums', '$state', 'playlists', 'auth', '$dialog'
($scope, albums, $state, playlists, auth, $dialog) ->
album = null
albums.fetch($state.params.id).done (albumResponse) ->
$scope.album = albumResponse.album
album = albumResponse.album
$scope.playlists = []
$scope.share = () ->
dialog = $dialog.dialog
templateUrl: '/templates/partials/album-share-dialog.html',
controller: ['$scope', ($scope) -> $scope.album = album; $scope.close = () -> dialog.close()]
dialog.open()
if auth.data.isLogged
playlists.refreshOwned().done (lists) ->
$scope.playlists.push list for list in lists

View file

@ -17,5 +17,6 @@ angular.module('ponyfm').controller "albums", [
$scope.$on 'albums-feteched', (e, list) -> refreshPages(list)
$scope.gotoPage = (page) ->
return if !page
$state.transitionTo 'content.albums.list', {page: page}
]

View file

@ -9,5 +9,4 @@ angular.module('ponyfm').controller "artist-favourites", [
($scope, artists, $state) ->
artists.fetchFavourites($state.params.slug).done (artistResponse) ->
$scope.favourites = artistResponse
console.log artistResponse
]

View file

@ -5,8 +5,12 @@ window.pfm.preloaders['artist'] = [
]
angular.module('ponyfm').controller "artist", [
'$scope', 'artists', '$state'
($scope, artists, $state) ->
'$scope', 'artists', '$state', 'follow'
($scope, artists, $state, follow) ->
artists.fetch($state.params.slug).done (artistResponse) ->
$scope.artist = artistResponse.artist
$scope.toggleFollow = () ->
follow.toggle('artist', $scope.artist.id).then (res) ->
$scope.artist.user_data.is_following = res.is_followed
]

View file

@ -17,5 +17,6 @@ angular.module('ponyfm').controller "artists", [
$scope.$on 'artists-feteched', (e, list) -> refreshPages(list)
$scope.gotoPage = (page) ->
return if !page
$state.transitionTo 'content.artists.list', {page: page}
]

View file

@ -5,8 +5,17 @@ window.pfm.preloaders['playlist'] = [
]
angular.module('ponyfm').controller 'playlist', [
'$scope', '$state', 'playlists'
($scope, $state, playlists) ->
playlists.fetch($state.params.id).done (playlist) ->
$scope.playlist = playlist
'$scope', '$state', 'playlists', '$dialog'
($scope, $state, playlists, $dialog) ->
playlist = null
playlists.fetch($state.params.id).done (playlistResponse) ->
$scope.playlist = playlistResponse
playlist = playlistResponse
$scope.share = () ->
dialog = $dialog.dialog
templateUrl: '/templates/partials/playlist-share-dialog.html',
controller: ['$scope', ($scope) -> $scope.playlist = playlist; $scope.close = () -> dialog.close()]
dialog.open()
]

View file

@ -17,5 +17,6 @@ angular.module('ponyfm').controller "playlists", [
$scope.$on 'playlists-feteched', (e, list) -> refreshPages(list)
$scope.gotoPage = (page) ->
return if !page
$state.transitionTo 'content.playlists.list', {page: page}
]

View file

@ -7,8 +7,11 @@ window.pfm.preloaders['track'] = [
angular.module('ponyfm').controller "track", [
'$scope', 'tracks', '$state', 'playlists', 'auth', 'favourites', '$dialog'
($scope, tracks, $state, playlists, auth, favourites, $dialog) ->
track = null
tracks.fetch($state.params.id).done (trackResponse) ->
$scope.track = trackResponse.track
track = trackResponse.track
$scope.playlists = []
@ -24,6 +27,12 @@ angular.module('ponyfm').controller "track", [
track.is_favourited = res.is_favourited
$scope.favouriteWorking = false
$scope.share = () ->
dialog = $dialog.dialog
templateUrl: '/templates/partials/track-share-dialog.html',
controller: ['$scope', ($scope) -> $scope.track = track; $scope.close = () -> dialog.close()]
dialog.open()
$scope.addToNewPlaylist = () ->
dialog = $dialog.dialog
templateUrl: '/templates/partials/playlist-dialog.html'

View file

@ -0,0 +1,6 @@
angular.module('ponyfm').directive 'pfmShareButtons', () ->
(scope, element) ->
window.setTimeout((->
Tumblr.activate_share_on_tumblr_buttons()
FB.XFBML.parse()
), 0)

View file

@ -1,6 +1,7 @@
angular.module('ponyfm').directive 'pfmTracksList', () ->
restrict: 'E'
templateUrl: '/templates/directives/tracks-list.html'
replace: true
scope:
tracks: '=tracks',
class: '@class'

View file

@ -14,7 +14,7 @@ angular.module('ponyfm').filter('pfmdate', [
if (!value)
return false;
return value.toString() == '[object Date]';
return Object.prototype.toString.apply(value) == '[object Date]';
}
function padNumber(num, digits, trim) {
@ -81,6 +81,8 @@ angular.module('ponyfm').filter('pfmdate', [
return obj;
}
var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
NUMBER_STRING = /^\d+$/;
@ -190,8 +192,9 @@ angular.module('ponyfm').filter('pfmdate', [
date = new Date(date);
}
if (typeof(date) == 'object' && date.date)
if (typeof(date) == 'object' && date.date) {
date = new Date(date.date);
}
if (!isDate(date)) {
return date;

View file

@ -0,0 +1,13 @@
angular.module('ponyfm').factory('follow', [
'$rootScope', '$http'
($rootScope, $http) ->
self =
toggle: (type, id) ->
def = new $.Deferred()
$http.post('/api/web/follow/toggle', {type: type, id: id, _token: pfm.token}).success (res) ->
def.resolve res
def.promise()
self
])

View file

@ -11,4 +11,5 @@
@import 'animations';
@import 'body';
@import 'player';
@import 'content';
@import 'content';
@import 'dashboard';

View file

@ -1,6 +1,14 @@
@import-once 'variables';
@import-once 'base/bootstrap/bootstrap';
a {
color: #C2889C;
&:hover {
text-decoration: none;
}
}
.site-content{
.box-sizing(border-box);
padding: 10px;

View file

@ -327,6 +327,17 @@ html {
.border-radius(0px);
border: 2px solid @pfm-purple;
h2 {
font-size: 12pt;
color: #C2889C;
line-height: normal;
margin-bottom: 5px;
small {
font-size: 10pt;
}
}
}
.breadcrumb {

View file

@ -6,23 +6,41 @@
margin: 0px;
padding: 0px;
list-style: none;
overflow: hidden;
&.two-columns {
li {
width: 50%;
}
}
li {
.box-sizing(border-box);
float: left;
width: 16.6666%;
width: 25%;
padding: 5px;
line-height: normal;
a {
background: #ddd;
background: #eee;
display: block;
overflow: hidden;
position: relative;
img {
display: block;
float: left;
width: 67px;
height: 67px;
background: #ddd;
}
.title, .published {
.info {
margin-left: 72px;
display: block;
}
.title, .published, .stats {
display: block;
color: #444;
padding: 5px;
@ -32,17 +50,35 @@
.ellipsis();
font-weight: bold;
font-size: 12pt;
font-size: 11pt;
padding-left: 3px;
padding-bottom: 0px;
}
.published {
color: #777;
font-size: 8pt;
color: #555;
}
.published, .stats {
padding-top: 0px;
}
.stats {
font-size: 10pt;
color: #777;
position: absolute;
bottom: 3px;
right: 3px;
strong {
font-weight: normal;
}
}
&:hover {
text-decoration: none;
background: #ddd;
}
}
}
@ -57,6 +93,34 @@
}
}
&.artist-details {
> header {
.tabs {
clear: left;
margin: 0px;
margin-top: 5px;
border: none;
font-size: 9pt;
li.active {
a {
border: none;
background: #C1889E;
color: #fff;
}
}
}
}
}
.share-buttons {
margin-top: 5px;
.facebook, .twitter {
margin-top: 3px;
}
}
> header {
padding: 5px;
background: #eee;
@ -174,15 +238,8 @@ html .single-player .play-button {
}
}
.tracks-listing {
margin: 0px;
padding: 0px;
list-style: none;
html {
li {
.box-sizing(border-box);
overflow: hidden;
&.empty {
.border-radius(0px);
background: lighten(@pfm-purple, 30%);
@ -199,6 +256,18 @@ html .single-player .play-button {
background-color: lighten(@pfm-purple, 30%);
}
}
}
}
.tracks-listing {
margin: 0px;
padding: 0px;
list-style: none;
overflow: hidden;
li {
.box-sizing(border-box);
overflow: hidden;
line-height: normal;
padding: 0px;

View file

@ -0,0 +1,23 @@
@import-once "base/bootstrap/bootstrap";
.recent-tracks {
h1 {
a {
display: block;
float: right;
font-size: 10pt;
margin-top: 8px;
}
}
}
.dashboard {
section {
.box-sizing(border-box);
float: left;
width: 50%;
padding: 5px;
}
}

View file

@ -8,7 +8,7 @@
<li bindonce ng-repeat="format in album.formats"><a target="_blank" bo-href="format.url"><span bo-text="format.name"></span> <small bo-text="'(' + format.size + ')'"></small></a></li>
</ul>
</li>
<li><a href="#" class="btn">Share or Embed</a></li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share or Embed</a></li>
<li><pfm-favourite-button resource="album" type="album"></pfm-favourite-button></li>
</ul>
@ -23,8 +23,14 @@
<div class="right">
<img class="cover" bo-src="album.covers.normal" />
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="album.share.tumblrUrl" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('http://platform.tumblr.com/v1/share_4.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{album.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" bo-src="album.share.twitterUrl" style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Published: <strong bo-text="album.published_at | pfmdate:'short'"></strong></li>
<li>Published: <strong bo-text="album.created_at | pfmdate:'medium'"></strong></li>
<li>Views: <strong bo-text="album.stats.views"></strong></li>
<li>Downloads: <strong bo-text="album.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="album.stats.favourites"></strong></li>

View file

@ -1,33 +1,25 @@
<div class="user-details">
<ul class="breadcrumb">
<li><a href="/artists">Artist Directory</a> <span class="divider">/</span></li>
<li class="active">{{artist.name}}</li>
<div class="resource-details artist-details" bindonce="artist">
<ul class="dropdowns">
<li class="dropdown">
<a href="#" class="btn btn-small" ng-class="{'btn-primary': !artist.user_data.is_following}" ng-show="auth.isLogged && auth.user.id != artist.id" pfm-eat-click ng-click="toggleFollow()">
<span ng-hide="artist.user_data.is_following">Follow</span>
<span ng-show="artist.user_data.is_following">Following!</span>
</a>
</li>
<li>
<a target="_blank" bo-href="artist.message_url" class="btn btn-small">
Send a Message
</a>
</li>
</ul>
<div class="track-toolbar btn-group pull-right">
<a href="#" class="btn btn-small" ng-show="auth.isLogged">
Follow
</a>
<a href="#" class="btn btn-small">
Send a Message
</a>
<a href="#" class="btn btn-small">
MLP Forums Profile
</a>
</div>
<div class="header">
<h1>
{{artist.name}}
</h1>
<header>
<h1 bo-text="artist.name"></h1>
<ul class="tabs">
<li ng-class="{active: stateIncludes('artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
<li ng-class="{active: stateIncludes('artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
<li ng-class="{active: stateIncludes('artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
<li ng-class="{active: stateIncludes('content.artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
<li ng-class="{active: stateIncludes('content.artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
<li ng-class="{active: stateIncludes('content.artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
</ul>
</div>
</header>
<div class="stretch-to-bottom">
<ui-view></ui-view>
</div>

View file

@ -1,14 +1,14 @@
<div ng-show="content.albums.length">
<h2>Albums</h2>
<pfm-albums-list albums="content.albums" />
<pfm-albums-list albums="content.albums"></pfm-albums-list>
</div>
<div ng-show="content.singles.length">
<h2>Singles</h2>
<pfm-tracks-list tracks="content.singles" class="four-column no-artist"></pfm-tracks-list>
<pfm-tracks-list tracks="content.singles" class="four-columns no-artist"></pfm-tracks-list>
</div>
<div ng-show="content.albumTracks.length">
<h2>Part of an Album</h2>
<pfm-tracks-list tracks="content.albumTracks" class="four-column no-artist"></pfm-tracks-list>
<pfm-tracks-list tracks="content.albumTracks" class="four-columns no-artist"></pfm-tracks-list>
</div>

View file

@ -5,6 +5,6 @@
</div>
<div class="span6">
<h2>Albums</h2>
<pfm-albums-list albums="favourites.albums"></pfm-albums-list>
<pfm-albums-list albums="favourites.albums" class="two-columns"></pfm-albums-list>
</div>
</div>

View file

@ -1,10 +1,12 @@
<ul class="artist-listing stretch-to-bottom">
<li ng-repeat="artist in artists">
<li ng-repeat="artist in artists" bindonce>
<a href="{{artist.url}}">
<img class="image" ng-src="{{artist.avatars.normal}}" />
<span class="title">{{artist.name}}</span>
<span class="published">
joined {{artist.created_at.date | momentFromNow}}
<img class="image" bo-src="artist.avatars.small" />
<span class="info">
<span class="title" bo-text="artist.name"></span>
<span class="published">
joined <span bo-text="artist.created_at.date | momentFromNow"></span>
</span>
</span>
</a>
</li>

View file

@ -1,17 +1,16 @@
<div class="row-fluid">
<div class="span6">
<div ng-show="artist.bio.trim().length">
<div bo-show="artist.bio.trim().length">
<h2>Bio</h2>
<div class="description">
<p ng-bind-html-unsafe="artist.bio | noHTML | newlines"></p>
<p bo-html="artist.bio | noHTML | newlines"></p>
</div>
</div>
<h2>Comments</h2>
<pfm-comments type="user" resource="artist"></pfm-comments>
</div>
<div class="span6 cover-image">
<h2>Recent Tracks</h2>
<pfm-tracks-list tracks="artist.latest_tracks" class="two-column no-artist" />
<pfm-tracks-list tracks="artist.latest_tracks" class="two-columns no-artist" />
</div>
</div>

View file

@ -1,9 +1,20 @@
<section class="recent-tracks stretch-to-bottom">
<div>
<h1>
<a href="/tracks"><i class="icon-music"></i> see more</a>
The Newest Tunes
</h1>
<pfm-tracks-list tracks="recentTracks" class="two-columns"></pfm-tracks-list>
</div>
</section>
<div class="dashboard">
<section class="recent-tracks stretch-to-bottom">
<div>
<h1>
<a href="/tracks"><i class="icon-music"></i> see more</a>
The Newest Tunes
</h1>
<pfm-tracks-list tracks="recentTracks" class="two-columns"></pfm-tracks-list>
</div>
</section>
<section class="popular-tracks stretch-to-bottom">
<div>
<h1>
What's Popular Today
</h1>
<pfm-tracks-list tracks="popularTracks" class="two-columns"></pfm-tracks-list>
</div>
</section>
</div>

View file

@ -1,10 +1,17 @@
<ul class="albums-listing {{class}}">
<li ng-repeat="album in albums">
<a href="{{album.url}}">
<img class="image" ng-src="{{album.covers.normal}}" />
<span class="title">{{album.title}}</span>
<li ng-repeat="album in albums" bindonce>
<a bo-href="album.url">
<img class="image" bo-src="album.covers.small" />
<span class="info">
<span class="title" bo-text="album.title"></span>
<span class="published">
by {{album.user.name}}
by <span bo-text="album.user.name"></span>
</span>
<span class="stats">
<strong bo-text="album.stats.favourites"></strong> <i class="icon-star"></i>
<strong bo-text="album.stats.comments"></strong> <i class="icon-comment"></i>
<strong bo-text="album.stats.downloads"></strong> <i class="icon-download"></i>
</span>
</span>
</a>
</li>

View file

@ -1,14 +1,14 @@
<div class="comments" bindonce>
<h2>All Comments ({{resource.comments.length}})</h2>
<div class="alert alert-info" ng-show="resource.comments.length == 0">
There are no comments yet!
</div>
<form class="pfm-form" ng-submit="addComment()" ng-show="auth.isLogged">
<div class="form-row">
<input type="text" ng-model="content" placeholder="Write a comment..." />
</div>
</form>
<ul ng-show="resource.comments.length > 0">
<ul>
<li ng-show="resource.comments.length == 0" class="empty">
There are no comments yet!
</li>
<li bindonce ng-repeat="comment in resource.comments">
<img bo-src="comment.user.avatars.thumbnail" />
<div class="content">

View file

@ -1,10 +1,17 @@
<ul class="playlists-listing {{class}}">
<li ng-repeat="playlist in playlists">
<li ng-repeat="playlist in playlists" bindonce>
<a href="{{playlist.url}}">
<img class="image" ng-src="{{playlist.covers.normal}}" height="350" width="350" />
<span class="title">{{playlist.title}}</span>
<span class="published">
by {{playlist.user.name}}
<img class="image" ng-src="{{playlist.covers.small}}"/>
<span class="info">
<span class="title">{{playlist.title}}</span>
<span class="published">
by {{playlist.user.name}}
</span>
<span class="stats">
<strong bo-text="playlist.stats.favourites"></strong> <i class="icon-star"></i>
<strong bo-text="playlist.stats.comments"></strong> <i class="icon-comment"></i>
<strong bo-text="playlist.stats.downloads"></strong> <i class="icon-download"></i>
</span>
</span>
</a>
</li>

View file

@ -0,0 +1,13 @@
<div class="modal-header">
<h3>
<button type="button" class="close" ng-click="close()" ng-hide="isLoading">&times;</button>
{{album.title}}
</h3>
</div>
<div class="modal-body">
<h2>Shortlink</h2>
<input type="text" ng-model="album.share.url" />
</div>
<div class="modal-footer">
<a class="btn cancel" ng-click="close()" ng-disabled="isLoading">Close</a>
</div>

View file

@ -0,0 +1,13 @@
<div class="modal-header">
<h3>
<button type="button" class="close" ng-click="close()" ng-hide="isLoading">&times;</button>
{{playlist.title}}
</h3>
</div>
<div class="modal-body">
<h2>Shortlink</h2>
<input type="text" ng-model="playlist.share.url" />
</div>
<div class="modal-footer">
<a class="btn cancel" ng-click="close()" ng-disabled="isLoading">Close</a>
</div>

View file

@ -0,0 +1,19 @@
<div class="modal-header">
<h3>
<button type="button" class="close" ng-click="close()" ng-hide="isLoading">&times;</button>
{{track.title}}
</h3>
</div>
<div class="modal-body">
<h2>Shortlink</h2>
<input type="text" ng-model="track.share.url" />
<h2>HTML Embed <small>(websites, blogs)</small></h2>
<textarea type="text" ng-model="track.share.html"></textarea>
<h2>BBCode Embed <small>(forums)</small></h2>
<textarea type="text" ng-model="track.share.bbcode"></textarea>
</div>
<div class="modal-footer">
<a class="btn cancel" ng-click="close()" ng-disabled="isLoading">Close</a>
</div>

View file

@ -8,7 +8,7 @@
<li bindonce ng-repeat="format in playlist.formats"><a target="_blank" bo-href="format.url"><span bo-text="format.name"></span> <small bo-text="'(' + format.size + ')'"></small></a></li>
</ul>
</li>
<li><a href="#" class="btn">Share or Embed</a></li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share</a></li>
<li><pfm-favourite-button resource="playlist" type="playlist"></pfm-favourite-button></li>
</ul>
@ -19,13 +19,18 @@
</h2>
</header>
<div class="stretch-to-bottom details-columns">
<div class="right">
<img class="cover" bo-src="playlist.covers.normal" />
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="playlist.share.tumblrUrl" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('http://platform.tumblr.com/v1/share_4.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{playlist.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" bo-src="playlist.share.twitterUrl" style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Created: <strong bo-text="playlist.created_at.date | pfmdate:'short'"></strong></li>
<li>Created: <strong bo-text="playlist.created_at | pfmdate:'medium'"></strong></li>
<li>Views: <strong bo-text="playlist.stats.views"></strong></li>
<li>Downloads: <strong bo-text="playlist.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="playlist.stats.favourites"></strong></li>

View file

@ -22,7 +22,7 @@
<li><a href="#" class="add-btn" pfm-eat-click ng-click="addToNewPlaylist()">Add to New Playlist</a></li>
</ul>
</li>
<li><a href="#" class="btn">Share or Embed</a></li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share</a></li>
<li><pfm-favourite-button resource="track" type="track"></pfm-favourite-button></li>
</ul>
@ -42,8 +42,14 @@
<div class="right">
<img class="cover" bo-src="track.covers.normal" />
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="track.share.tumblrUrl" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('http://platform.tumblr.com/v1/share_4.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{track.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" bo-src="track.share.twitterUrl" style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Published: <strong bo-text="track.published_at | pfmdate:'short'"></strong></li>
<li>Published: <strong bo-text="track.published_at | pfmdate:'medium'"></strong></li>
<li>Views: <strong bo-text="track.stats.views"></strong></li>
<li>Plays: <strong bo-text="track.stats.plays"></strong></li>
<li>Downloads: <strong bo-text="track.stats.downloads"></strong></li>

2
vendor/autoload.php vendored
View file

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit265a5d8a5cc5c33c736711894c7e0223::getLoader();
return ComposerAutoloaderInitf5e8b08f8d3ef98cfbf31c8bbf4b6225::getLoader();

View file

@ -8,6 +8,7 @@ $baseDir = dirname($vendorDir);
return array(
'AbstractOutputProvider' => $vendorDir . '/codescale/ffmpeg-php/provider/AbstractOutputProvider.php',
'AccountController' => $baseDir . '/app/controllers/AccountController.php',
'AlbumDownloader' => $baseDir . '/app/models/AlbumDownloader.php',
'AlbumsController' => $baseDir . '/app/controllers/AlbumsController.php',
'ApiControllerBase' => $baseDir . '/app/controllers/ApiControllerBase.php',
'Api\\Web\\AccountController' => $baseDir . '/app/controllers/Api/Web/AccountController.php',
@ -19,6 +20,7 @@ return array(
'Api\\Web\\FavouritesController' => $baseDir . '/app/controllers/Api/Web/FavouritesController.php',
'Api\\Web\\ImagesController' => $baseDir . '/app/controllers/Api/Web/ImagesController.php',
'Api\\Web\\PlaylistsController' => $baseDir . '/app/controllers/Api/Web/PlaylistsController.php',
'Api\\Web\\ProfilerController' => $baseDir . '/app/controllers/Api/Web/ProfilerController.php',
'Api\\Web\\TaxonomiesController' => $baseDir . '/app/controllers/Api/Web/TaxonomiesController.php',
'Api\\Web\\TracksController' => $baseDir . '/app/controllers/Api/Web/TracksController.php',
'ArtistsController' => $baseDir . '/app/controllers/ArtistsController.php',
@ -150,6 +152,7 @@ return array(
'CreateAlbums' => $baseDir . '/app/database/migrations/2013_07_28_060804_create_albums.php',
'CreateComments' => $baseDir . '/app/database/migrations/2013_08_01_051337_create_comments.php',
'CreateFavourites' => $baseDir . '/app/database/migrations/2013_08_18_045248_create_favourites.php',
'CreateFollowers' => $baseDir . '/app/database/migrations/2013_08_29_025516_create_followers.php',
'CreateImagesTable' => $baseDir . '/app/database/migrations/2013_07_26_230827_create_images_table.php',
'CreatePlaylists' => $baseDir . '/app/database/migrations/2013_07_28_135136_create_playlists.php',
'CreateSongsTable' => $baseDir . '/app/database/migrations/2013_07_28_034328_create_songs_table.php',
@ -430,7 +433,9 @@ return array(
'Entities\\License' => $baseDir . '/app/models/Entities/License.php',
'Entities\\PinnedPlaylist' => $baseDir . '/app/models/Entities/PinnedPlaylist.php',
'Entities\\Playlist' => $baseDir . '/app/models/Entities/Playlist.php',
'Entities\\ProfileRequest' => $baseDir . '/app/models/Entities/ProfileRequest.php',
'Entities\\ResourceLogItem' => $baseDir . '/app/models/Entities/ResourceLogItem.php',
'Entities\\ResourceUser' => $baseDir . '/app/models/Entities/ResourceUser.php',
'Entities\\ShowSong' => $baseDir . '/app/models/Entities/ShowSong.php',
'Entities\\Track' => $baseDir . '/app/models/Entities/Track.php',
'Entities\\TrackType' => $baseDir . '/app/models/Entities/TrackType.php',
@ -1058,6 +1063,7 @@ return array(
'Patchwork\\PHP\\Shim\\Xml' => $vendorDir . '/patchwork/utf8/class/Patchwork/PHP/Shim/Xml.php',
'Patchwork\\Utf8' => $vendorDir . '/patchwork/utf8/class/Patchwork/Utf8.php',
'Patchwork\\Utf8\\Bootup' => $vendorDir . '/patchwork/utf8/class/Patchwork/Utf8/Bootup.php',
'PlaylistDownloader' => $baseDir . '/app/models/PlaylistDownloader.php',
'PlaylistsController' => $baseDir . '/app/controllers/PlaylistsController.php',
'Predis\\Autoloader' => $vendorDir . '/predis/predis/lib/Predis/Autoloader.php',
'Predis\\BasicClientInterface' => $vendorDir . '/predis/predis/lib/Predis/BasicClientInterface.php',
@ -1393,6 +1399,7 @@ return array(
'React\\Stream\\Util' => $vendorDir . '/react/stream/React/Stream/Util.php',
'React\\Stream\\WritableStream' => $vendorDir . '/react/stream/React/Stream/WritableStream.php',
'React\\Stream\\WritableStreamInterface' => $vendorDir . '/react/stream/React/Stream/WritableStreamInterface.php',
'RefreshCache' => $baseDir . '/app/commands/RefreshCache.php',
'SessionHandlerInterface' => $vendorDir . '/symfony/http-foundation/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php',
'StringOutputProvider' => $vendorDir . '/codescale/ffmpeg-php/provider/StringOutputProvider.php',
'Symfony\\Component\\BrowserKit\\Client' => $vendorDir . '/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php',

View file

@ -2,7 +2,7 @@
// autoload_real.php generated by Composer
class ComposerAutoloaderInit265a5d8a5cc5c33c736711894c7e0223
class ComposerAutoloaderInitf5e8b08f8d3ef98cfbf31c8bbf4b6225
{
private static $loader;
@ -19,9 +19,9 @@ class ComposerAutoloaderInit265a5d8a5cc5c33c736711894c7e0223
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit265a5d8a5cc5c33c736711894c7e0223', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitf5e8b08f8d3ef98cfbf31c8bbf4b6225', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit265a5d8a5cc5c33c736711894c7e0223', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitf5e8b08f8d3ef98cfbf31c8bbf4b6225', 'loadClassLoader'));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);