Merged development into master

This commit is contained in:
NelsonLaQuet 2013-09-22 22:45:07 -05:00
commit 3abddfabbe
6 changed files with 187 additions and 22 deletions

View file

@ -0,0 +1,92 @@
<?php
namespace Api\V1;
use Commands\DeleteTrackCommand;
use Commands\EditTrackCommand;
use Commands\UploadTrackCommand;
use Cover;
use Entities\Favourite;
use Entities\Image;
use Entities\ResourceLogItem;
use Entities\ResourceUser;
use Entities\Track;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
class TracksController extends \ApiControllerBase {
public function getTrackRadioDetails($hash) {
$track = Track
::with('user', 'album', 'user.avatar', 'cover', 'comments', 'genre')
->published()
->whereHash($hash)->first();
if (!$track)
return Response::json(['message' => 'Track not found.'], 403);
$comments = [];
foreach ($track->comments as $comment) {
$comments[] = [
'id' => $comment->id,
'created_at' => $comment->created_at,
'content' => $comment->content,
'user' => [
'name' => $comment->user->display_name,
'id' => $comment->user->id,
'url' => $comment->user->url,
'avatars' => [
'normal' => $comment->user->getAvatarUrl(Image::NORMAL),
'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL),
'small' => $comment->user->getAvatarUrl(Image::SMALL),
]
]
];
}
return Response::json([
'id' => $track->id,
'title' => $track->title,
'user' => [
'id' => $track->user->id,
'name' => $track->user->display_name,
'url' => $track->user->url,
'avatars' => [
'thumbnail' => $track->user->getAvatarUrl(Image::THUMBNAIL),
'small' => $track->user->getAvatarUrl(Image::SMALL),
'normal' => $track->user->getAvatarUrl(Image::NORMAL)
]
],
'stats' => [
'views' => $track->view_count,
'plays' => $track->play_count,
'downloads' => $track->download_count,
'comments' => $track->comment_count,
'favourites' => $track->favourite_count
],
'url' => $track->url,
'is_vocal' => !!$track->is_vocal,
'is_explicit' => !!$track->is_explicit,
'is_downloadable' => !!$track->is_downloadable,
'published_at' => $track->published_at,
'duration' => $track->duration,
'genre' => $track->genre != null
?
[
'id' => $track->genre->id,
'name' => $track->genre->name
] : null,
'type' => [
'id' => $track->track_type->id,
'name' => $track->track_type->title
],
'covers' => [
'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL),
'small' => $track->getCoverUrl(Image::SMALL),
'normal' => $track->getCoverUrl(Image::NORMAL)
],
'comments' => $comments
], 200);
}
}

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

@ -1,6 +1,15 @@
<?php
class Helpers {
/**
* Removes whitespace and special characters from a string
* and sets all characters to lower case.
*/
public static function sanitizeInputForHashing($value) {
$value = preg_replace('/[^A-Za-z0-9]/', '', $value);
return strtolower($value);
}
public static function template($template) {
echo file_get_contents('templates/' . $template);
}

View file

@ -19,7 +19,9 @@
class Track extends \Eloquent {
protected $softDelete = true;
use SlugTrait;
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}'],
@ -257,6 +259,10 @@
return $this->belongsTo('Entities\Genre');
}
public function trackType() {
return $this->belongsTo('Entities\TrackType', 'track_type_id');
}
public function comments(){
return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc');
}
@ -289,6 +295,11 @@
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);
@ -401,6 +412,10 @@
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() {
foreach (self::$Formats as $format => $data) {
$this->{$data['tag_method']}($format);

View file

@ -49,6 +49,10 @@
Route::get('p{id}', 'PlaylistsController@getShortlink')->where('id', '\d+');
Route::get('p{id}/dl.{extension}', 'PlaylistsController@getDownload' );
Route::group(['prefix' => 'api/v1'], function() {
Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails');
});
Route::group(['prefix' => 'api/web'], function() {
Route::get('/taxonomies/all', 'Api\Web\TaxonomiesController@getAll');

View file

@ -302,7 +302,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirect;
class Application extends Container implements HttpKernelInterface, ResponsePreparerInterface
{
const VERSION = '4.0.6';
const VERSION = '4.0.7';
protected $booted = false;
protected $bootingCallbacks = array();
protected $bootedCallbacks = array();
@ -949,11 +949,19 @@ class Request
$query = $parameters;
break;
}
$queryString = '';
if (isset($components['query'])) {
parse_str(html_entity_decode($components['query']), $qs);
$query = array_replace($qs, $query);
if ($query) {
$query = array_replace($qs, $query);
$queryString = http_build_query($query, '', '&');
} else {
$query = $qs;
$queryString = $components['query'];
}
} elseif ($query) {
$queryString = http_build_query($query, '', '&');
}
$queryString = http_build_query($query, '', '&');
$server['REQUEST_URI'] = $components['path'] . ('' !== $queryString ? '?' . $queryString : '');
$server['QUERY_STRING'] = $queryString;
return new static($query, $request, array(), $cookies, $files, $server, $content);
@ -989,8 +997,11 @@ class Request
$dup->basePath = null;
$dup->method = null;
$dup->format = null;
if (!$dup->get('_format')) {
$dup->setRequestFormat($this->getRequestFormat());
if (!$dup->get('_format') && $this->get('_format')) {
$dup->attributes->set('_format', $this->get('_format'));
}
if (!$dup->getRequestFormat(null)) {
$dup->setRequestFormat($format = $this->getRequestFormat(null));
}
return $dup;
}
@ -1176,6 +1187,12 @@ class Request
return 443;
}
}
if ($host = $this->headers->get('HOST')) {
if (false !== ($pos = strrpos($host, ':'))) {
return intval(substr($host, $pos + 1));
}
return 'https' === $this->getScheme() ? 443 : 80;
}
return $this->server->get('SERVER_PORT');
}
public function getUser()
@ -1509,14 +1526,14 @@ class Request
return rtrim($prefix, '/');
}
$truncatedRequestUri = $requestUri;
if (($pos = strpos($requestUri, '?')) !== false) {
if (false !== ($pos = strpos($requestUri, '?'))) {
$truncatedRequestUri = substr($requestUri, 0, $pos);
}
$basename = basename($baseUrl);
if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
return '';
}
if (strlen($requestUri) >= strlen($baseUrl) && (false !== ($pos = strpos($requestUri, $baseUrl)) && $pos !== 0)) {
if (strlen($requestUri) >= strlen($baseUrl) && false !== ($pos = strpos($requestUri, $baseUrl)) && $pos !== 0) {
$baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
}
return rtrim($baseUrl, '/');
@ -1787,15 +1804,22 @@ class ServerBag extends ParameterBag
} elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
$authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION'];
}
if (null !== $authorizationHeader && 0 === stripos($authorizationHeader, 'basic')) {
$exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
if (count($exploded) == 2) {
list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
if (null !== $authorizationHeader) {
if (0 === stripos($authorizationHeader, 'basic')) {
$exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
if (count($exploded) == 2) {
list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
}
} elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && 0 === stripos($authorizationHeader, 'digest')) {
$headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
$this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
}
}
}
if (isset($headers['PHP_AUTH_USER'])) {
$headers['AUTHORIZATION'] = 'Basic ' . base64_encode($headers['PHP_AUTH_USER'] . ':' . $headers['PHP_AUTH_PW']);
} elseif (isset($headers['PHP_AUTH_DIGEST'])) {
$headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST'];
}
return $headers;
}
@ -2225,6 +2249,7 @@ class NativeSessionStorage implements SessionStorageInterface
} else {
session_start();
}
$this->loadSession();
}
return $ret;
}
@ -3257,8 +3282,7 @@ class ExceptionServiceProvider extends ServiceProvider
}
protected function getResourcePath()
{
$base = $this->app['path.base'];
return $base . '/vendor/laravel/framework/src/Illuminate/Exception/resources';
return 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\laravel\\framework\\src\\Illuminate\\Exception' . '/resources';
}
}
namespace Illuminate\Routing;
@ -3611,7 +3635,7 @@ class ErrorHandler
if (null === ($error = error_get_last())) {
return;
}
unset($this->reservedMemory);
$this->reservedMemory = '';
$type = $error['type'];
if (0 === $this->level || !in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) {
return;
@ -4218,10 +4242,6 @@ class ProviderRepository
$this->files->put($path, json_encode($manifest));
return $manifest;
}
protected function getManifestPath($app)
{
return $this->manifestPath;
}
protected function freshManifest(array $providers)
{
list($eager, $deferred) = array(array(), array());
@ -5381,6 +5401,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa
protected $appends = array();
protected $fillable = array();
protected $guarded = array('*');
protected $dates = array();
protected $touches = array();
protected $with = array();
public $exists = false;
@ -5853,7 +5874,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa
}
public function freshTimestamp()
{
return new DateTime();
return new Carbon();
}
public function freshTimestampString()
{
@ -6153,7 +6174,8 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa
}
public function getDates()
{
return array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT);
$defaults = array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT);
return array_merge($this->dates, $defaults);
}
public function fromDateTime($value)
{
@ -6590,7 +6612,7 @@ class Store extends SymfonySession
}
protected function mergeNewFlashes(array $keys)
{
$values = array_unique(array_merge($this->get('flash.new'), $keys));
$values = array_unique(array_merge($this->get('flash.new', array()), $keys));
$this->put('flash.new', $values);
}
protected function removeFromOldFlashData(array $keys)