From 84f6064a1bba2bca2785ca2e5296ba774a12291c Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 1 Sep 2013 19:11:33 -0500 Subject: [PATCH] Don't want to lose these files --- .../Api/Web/DashboardController.php | 4 +- .../2013_09_01_232520_create_news_table.php | 21 + app/filters.php | 2 +- app/models/Entities/News.php | 59 +++ bootstrap/compiled.php | 358 +++++++++++++----- composer.json | 3 +- public/asset.php | 2 +- .../scripts/app/controllers/dashboard.coffee | 2 + public/styles/content.less | 6 +- public/styles/dashboard.less | 57 ++- public/templates/dashboard/index.html | 34 +- spa.pony.fm.iml | 19 +- 12 files changed, 442 insertions(+), 125 deletions(-) create mode 100644 app/database/migrations/2013_09_01_232520_create_news_table.php create mode 100644 app/models/Entities/News.php diff --git a/app/controllers/Api/Web/DashboardController.php b/app/controllers/Api/Web/DashboardController.php index 4a9936e4..b0384a9b 100644 --- a/app/controllers/Api/Web/DashboardController.php +++ b/app/controllers/Api/Web/DashboardController.php @@ -7,6 +7,7 @@ use Commands\UploadTrackCommand; use Cover; use Entities\Image; + use Entities\News; use Entities\Track; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Input; @@ -30,6 +31,7 @@ return Response::json([ 'recent_tracks' => $recentTracks, - 'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content)], 200); + 'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content), + 'news' => News::getNews(0, 10)], 200); } } \ No newline at end of file diff --git a/app/database/migrations/2013_09_01_232520_create_news_table.php b/app/database/migrations/2013_09_01_232520_create_news_table.php new file mode 100644 index 00000000..d6e9aa73 --- /dev/null +++ b/app/database/migrations/2013_09_01_232520_create_news_table.php @@ -0,0 +1,21 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + $table->string('post_hash', 32)->index(); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + } + + public function down() { + Schema::drop('news'); + } + +} \ No newline at end of file diff --git a/app/filters.php b/app/filters.php index f7af7627..9c739444 100644 --- a/app/filters.php +++ b/app/filters.php @@ -40,7 +40,7 @@ }); App::error(function($exception) { - return Response::view('errors.500', array(), 404); + // return Response::view('errors.500', array(), 404); }); } diff --git a/app/models/Entities/News.php b/app/models/Entities/News.php new file mode 100644 index 00000000..4d8b3a5a --- /dev/null +++ b/app/models/Entities/News.php @@ -0,0 +1,59 @@ +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()); + } + + $seenRecords = 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[] = [ + 'post' => [ + '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 = News::create(['user_id' => Auth::user()->id, 'post_hash' => $postHash]); + $news->save(); + } + + private static function calculateHash($postPermalink) { + return md5($postPermalink); + } + } \ No newline at end of file diff --git a/bootstrap/compiled.php b/bootstrap/compiled.php index 77fc2c3c..20026219 100644 --- a/bootstrap/compiled.php +++ b/bootstrap/compiled.php @@ -183,7 +183,7 @@ class Container implements ArrayAccess if (is_null($dependency)) { $dependencies[] = $this->resolveNonClass($parameter); } else { - $dependencies[] = $this->make($dependency->name); + $dependencies[] = $this->resolveClass($parameter); } } return (array) $dependencies; @@ -197,6 +197,18 @@ class Container implements ArrayAccess throw new BindingResolutionException($message); } } + protected function resolveClass(ReflectionParameter $parameter) + { + try { + return $this->make($parameter->getClass()->name); + } catch (BindingResolutionException $e) { + if ($parameter->isOptional()) { + return $parameter->getDefaultValue(); + } else { + throw $e; + } + } + } public function resolving(Closure $callback) { $this->resolvingCallbacks[] = $callback; @@ -290,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.2'; + const VERSION = '4.0.6'; protected $booted = false; protected $bootingCallbacks = array(); protected $bootedCallbacks = array(); @@ -298,6 +310,7 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep protected $serviceProviders = array(); protected $loadedProviders = array(); protected $deferredServices = array(); + protected static $requestClass = 'Illuminate\\Http\\Request'; public function __construct(Request $request = null) { $this['request'] = $this->createRequest($request); @@ -307,12 +320,13 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep } protected function createRequest(Request $request = null) { - return $request ?: Request::createFromGlobals(); + return $request ?: static::onRequest('createFromGlobals'); } public function setRequestForConsoleEnvironment() { $url = $this['config']->get('app.url', 'http://localhost'); - $this->instance('request', Request::create($url, 'GET', array(), array(), array(), $_SERVER)); + $parameters = array($url, 'GET', array(), array(), array(), $_SERVER); + $this->instance('request', static::onRequest('create', $parameters)); } public function redirectIfTrailingSlash() { @@ -476,10 +490,11 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep { if ($this->isDownForMaintenance()) { $response = $this['events']->until('illuminate.app.down'); - return $this->prepareResponse($response, $request); - } else { - return $this['router']->dispatch($this->prepareRequest($request)); + if (!is_null($response)) { + return $this->prepareResponse($response, $request); + } } + return $this['router']->dispatch($this->prepareRequest($request)); } public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { @@ -553,7 +568,7 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep { $this['exception']->error($callback); } - public function pushError(Closure $closure) + public function pushError(Closure $callback) { $this['exception']->pushError($callback); } @@ -586,6 +601,17 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep { $this->deferredServices = $services; } + public static function requestClass($class = null) + { + if (!is_null($class)) { + static::$requestClass = $class; + } + return static::$requestClass; + } + public static function onRequest($method, $parameters = array()) + { + return forward_static_call_array(array(static::requestClass(), $method), $parameters); + } public function __get($key) { return $this[$key]; @@ -665,7 +691,7 @@ class Request extends \Symfony\Component\HttpFoundation\Request } return true; } - if (is_array($this->input($key))) { + if (is_bool($this->input($key)) or is_array($this->input($key))) { return true; } return trim((string) $this->input($key)) !== ''; @@ -782,6 +808,15 @@ class Request extends \Symfony\Component\HttpFoundation\Request $acceptable = $this->getAcceptableContentTypes(); return isset($acceptable[0]) and $acceptable[0] == 'application/json'; } + public function format($default = 'html') + { + foreach ($this->getAcceptableContentTypes() as $type) { + if ($format = $this->getFormat($type)) { + return $format; + } + } + return $default; + } public function getSessionStore() { if (!isset($this->sessionStore)) { @@ -808,6 +843,8 @@ class Request const HEADER_CLIENT_PROTO = 'client_proto'; const HEADER_CLIENT_PORT = 'client_port'; protected static $trustedProxies = array(); + protected static $trustedHostPatterns = array(); + protected static $trustedHosts = array(); protected static $trustedHeaders = array(self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT'); protected static $httpMethodParameterOverride = false; public $attributes; @@ -952,6 +989,9 @@ class Request $dup->basePath = null; $dup->method = null; $dup->format = null; + if (!$dup->get('_format')) { + $dup->setRequestFormat($this->getRequestFormat()); + } return $dup; } public function __clone() @@ -1000,6 +1040,17 @@ class Request { return self::$trustedProxies; } + public static function setTrustedHosts(array $hostPatterns) + { + self::$trustedHostPatterns = array_map(function ($hostPattern) { + return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern)); + }, $hostPatterns); + self::$trustedHosts = array(); + } + public static function getTrustedHosts() + { + return self::$trustedHostPatterns; + } public static function setTrustedHeaderName($key, $value) { if (!array_key_exists($key, self::$trustedHeaders)) { @@ -1199,7 +1250,19 @@ class Request } $host = strtolower(preg_replace('/:\\d+$/', '', trim($host))); if ($host && !preg_match('/^\\[?(?:[a-zA-Z0-9-:\\]_]+\\.?)+$/', $host)) { - throw new \UnexpectedValueException('Invalid Host'); + throw new \UnexpectedValueException('Invalid Host "' . $host . '"'); + } + if (count(self::$trustedHostPatterns) > 0) { + if (in_array($host, self::$trustedHosts)) { + return $host; + } + foreach (self::$trustedHostPatterns as $pattern) { + if (preg_match($pattern, $host)) { + self::$trustedHosts[] = $host; + return $host; + } + } + throw new \UnexpectedValueException('Untrusted Host "' . $host . '"'); } return $host; } @@ -2152,7 +2215,18 @@ class NativeSessionStorage implements SessionStorageInterface if ($destroy) { $this->metadataBag->stampNew(); } - return session_regenerate_id($destroy); + $ret = session_regenerate_id($destroy); + if ('files' === $this->getSaveHandler()->getSaveHandlerName()) { + session_write_close(); + if (isset($_SESSION)) { + $backup = $_SESSION; + session_start(); + $_SESSION = $backup; + } else { + session_start(); + } + } + return $ret; } public function save() { @@ -3067,7 +3141,7 @@ abstract class ServiceProvider } protected function getClassChain(ReflectionClass $reflect) { - $lastName = null; + $classes = array(); while ($reflect !== false) { $classes[] = $reflect; $reflect = $reflect->getParentClass(); @@ -3081,9 +3155,9 @@ abstract class ServiceProvider } return $namespace; } - public function commands() + public function commands($commands) { - $commands = func_get_args(); + $commands = is_array($commands) ? $commands : func_get_args(); $events = $this->app['events']; $events->listen('artisan.start', function ($artisan) use($commands) { $artisan->resolveCommands($commands); @@ -3398,6 +3472,10 @@ class Str } return rtrim($matches[0]) . $end; } + public static function parseCallback($callback, $default) + { + return static::contains($callback, '@') ? explode('@', $callback, 2) : array($callback, $default); + } public static function plural($value, $count = 2) { return Pluralizer::plural($value, $count); @@ -3522,6 +3600,9 @@ class ErrorHandler return true; } if ($this->displayErrors && error_reporting() & $level && $this->level & $level) { + if (!class_exists('Symfony\\Component\\Debug\\Exception\\ContextErrorException')) { + require 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\symfony\\debug\\Symfony\\Component\\Debug' . '/Exception/ContextErrorException.php'; + } throw new ContextErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line, $context); } return false; @@ -3582,7 +3663,7 @@ class Repository extends NamespacedItemResolver implements ArrayAccess public function has($key) { $default = microtime(true); - return $this->get($key, $default) != $default; + return $this->get($key, $default) !== $default; } public function hasGroup($key) { @@ -3923,7 +4004,7 @@ class Filesystem } public function lastModified($path) { - return filemtime(realpath($path)); + return filemtime($path); } public function isDirectory($directory) { @@ -3959,7 +4040,7 @@ class Filesystem { $directories = array(); foreach (Finder::create()->in($directory)->directories()->depth(0) as $dir) { - $directories[] = $dir->getRealPath(); + $directories[] = $dir->getPathname(); } return $directories; } @@ -3980,12 +4061,12 @@ class Filesystem foreach ($items as $item) { $target = $destination . '/' . $item->getBasename(); if ($item->isDir()) { - $path = $item->getRealPath(); + $path = $item->getPathname(); if (!$this->copyDirectory($path, $target, $options)) { return false; } } else { - if (!$this->copy($item->getRealPath(), $target)) { + if (!$this->copy($item->getPathname(), $target)) { return false; } } @@ -4000,9 +4081,9 @@ class Filesystem $items = new FilesystemIterator($directory); foreach ($items as $item) { if ($item->isDir()) { - $this->deleteDirectory($item->getRealPath()); + $this->deleteDirectory($item->getPathname()); } else { - $this->delete($item->getRealPath()); + $this->delete($item->getPathname()); } } if (!$preserve) { @@ -4248,8 +4329,7 @@ class SessionServiceProvider extends ServiceProvider } protected function registerSessionEvents() { - $app = $this->app; - $config = $app['config']['session']; + $config = $this->app['config']['session']; if (!is_null($config['driver'])) { $this->registerBootingEvent(); $this->registerCloseEvent(); @@ -4257,8 +4337,7 @@ class SessionServiceProvider extends ServiceProvider } protected function registerBootingEvent() { - $app = $this->app; - $this->app->booting(function ($app) use($app) { + $this->app->booting(function ($app) { $app['session']->start(); }); } @@ -4286,7 +4365,7 @@ class SessionServiceProvider extends ServiceProvider { $config = $this->app['config']['session']; $expire = $this->getExpireTime($config); - setcookie($config['cookie'], session_id(), $expire, $config['path'], $config['domain']); + setcookie($config['cookie'], session_id(), $expire, $config['path'], $config['domain'], false, true); } protected function getExpireTime($config) { @@ -4829,21 +4908,21 @@ class Router $this->patternFilters[$pattern][] = compact('name', 'methods'); } } - public function findPatternFilters(Request $request) + public function findPatternFilters($method, $path) { $results = array(); foreach ($this->patternFilters as $pattern => $filters) { - if (str_is('/' . $pattern, $request->getPathInfo())) { - $merge = $this->filterPatternsByMethod($request, $filters); + if (str_is('/' . $pattern, $path)) { + $merge = $this->filterPatternsByMethod($method, $filters); $results = array_merge($results, $merge); } } return $results; } - protected function filterPatternsByMethod(Request $request, $filters) + protected function filterPatternsByMethod($method, $filters) { $results = array(); - $method = strtolower($request->getMethod()); + $method = strtolower($method); foreach ($filters as $filter) { if (is_null($filter['methods']) or in_array($method, $filter['methods'])) { $results[] = $filter['name']; @@ -5154,7 +5233,7 @@ class Dispatcher protected $sorted = array(); public function __construct(Container $container = null) { - $this->container = $container; + $this->container = $container ?: new Container(); } public function listen($event, $listener, $priority = 0) { @@ -5166,7 +5245,7 @@ class Dispatcher } protected function setupWildcardListen($event, $listener, $priority) { - $this->wildcards[$event][] = $listener; + $this->wildcards[$event][] = $this->makeListener($listener); } public function hasListeners($eventName) { @@ -5300,6 +5379,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa protected $relations = array(); protected $hidden = array(); protected $visible = array(); + protected $appends = array(); protected $fillable = array(); protected $guarded = array('*'); protected $touches = array(); @@ -5376,6 +5456,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa $model->save(); return $model; } + public static function query() + { + return with(new static())->newQuery(); + } public static function on($connection = null) { $instance = new static(); @@ -5526,7 +5610,8 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { $query = $this->newQuery()->where($this->getKeyName(), $this->getKey()); if ($this->softDelete) { - $query->update(array(static::DELETED_AT => new DateTime())); + $this->{static::DELETED_AT} = $time = $this->freshTimestamp(); + $query->update(array(static::DELETED_AT => $this->fromDateTime($time))); } else { $query->delete(); } @@ -5534,8 +5619,13 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa public function restore() { if ($this->softDelete) { + if ($this->fireModelEvent('restoring') === false) { + return false; + } $this->{static::DELETED_AT} = null; - return $this->save(); + $result = $this->save(); + $this->fireModelEvent('restored', false); + return $result; } } public static function saving($callback) @@ -5570,6 +5660,14 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { static::registerModelEvent('deleted', $callback); } + public static function restoring($callback) + { + static::registerModelEvent('restoring', $callback); + } + public static function restored($callback) + { + static::registerModelEvent('restored', $callback); + } public static function flushEventListeners() { if (!isset(static::$dispatcher)) { @@ -5589,7 +5687,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function getObservableEvents() { - return array('creating', 'created', 'updating', 'updated', 'deleting', 'deleted', 'saving', 'saved'); + return array('creating', 'created', 'updating', 'updated', 'deleting', 'deleted', 'saving', 'saved', 'restoring', 'restored'); } protected function increment($column, $amount = 1) { @@ -5758,6 +5856,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { return new DateTime(); } + public function freshTimestampString() + { + return $this->fromDateTime($this->freshTimestamp()); + } public function newQuery($excludeDeleted = true) { $builder = new Builder($this->newBaseQueryBuilder()); @@ -5800,7 +5902,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa if (isset($this->table)) { return $this->table; } - return str_replace('\\', '', snake_case(str_plural(get_class($this)))); + return str_replace('\\', '', snake_case(str_plural(class_basename($this)))); } public function setTable($table) { @@ -5860,6 +5962,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { $this->visible = $visible; } + public function setAppends(array $appends) + { + $this->appends = $appends; + } public function getFillable() { return $this->fillable; @@ -5941,26 +6047,26 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function attributesToArray() { - $attributes = $this->getAccessibleAttributes(); + $attributes = $this->getArrayableAttributes(); foreach ($this->getMutatedAttributes() as $key) { if (!array_key_exists($key, $attributes)) { continue; } $attributes[$key] = $this->mutateAttribute($key, $attributes[$key]); } + foreach ($this->appends as $key) { + $attributes[$key] = $this->mutateAttribute($key, null); + } return $attributes; } - protected function getAccessibleAttributes() + protected function getArrayableAttributes() { - if (count($this->visible) > 0) { - return array_intersect_key($this->attributes, array_flip($this->visible)); - } - return array_diff_key($this->attributes, array_flip($this->hidden)); + return $this->getArrayableItems($this->attributes); } public function relationsToArray() { $attributes = array(); - foreach ($this->relations as $key => $value) { + foreach ($this->getArrayableRelations() as $key => $value) { if (in_array($key, $this->hidden)) { continue; } @@ -5972,12 +6078,23 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa if (static::$snakeAttributes) { $key = snake_case($key); } - if (isset($relation)) { + if (isset($relation) or is_null($value)) { $attributes[$key] = $relation; } } return $attributes; } + protected function getArrayableRelations() + { + return $this->getArrayableItems($this->relations); + } + protected function getArrayableItems(array $values) + { + if (count($this->visible) > 0) { + return array_intersect_key($values, array_flip($this->visible)); + } + return array_diff_key($values, array_flip($this->hidden)); + } public function getAttribute($key) { $inAttributes = array_key_exists($key, $this->attributes); @@ -6039,7 +6156,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { return array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT); } - protected function fromDateTime($value) + public function fromDateTime($value) { $format = $this->getDateFormat(); if ($value instanceof DateTime) { @@ -6109,6 +6226,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } return $dirty; } + public function getRelations() + { + return $this->relations; + } public function getRelation($relation) { return $this->relations[$relation]; @@ -6134,6 +6255,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa public function setConnection($name) { $this->connection = $name; + return $this; } public static function resolveConnection($connection = null) { @@ -6256,6 +6378,7 @@ class DatabaseManager implements ConnectionResolverInterface } public function reconnect($name = null) { + $name = $name ?: $this->getDefaultConnection(); unset($this->connections[$name]); return $this->connection($name); } @@ -6265,6 +6388,10 @@ class DatabaseManager implements ConnectionResolverInterface if (isset($this->extensions[$name])) { return call_user_func($this->extensions[$name], $config); } + $driver = $config['driver']; + if (isset($this->extensions[$driver])) { + return call_user_func($this->extensions[$driver], $config); + } return $this->factory->make($config, $name); } protected function prepare(Connection $connection) @@ -6409,7 +6536,7 @@ class Store extends SymfonySession { return array_get($this->all(), $name, $default); } - public function hasOldInput($key) + public function hasOldInput($key = null) { return !is_null($this->getOldInput($key)); } @@ -6543,13 +6670,18 @@ class SessionManager extends Manager } protected function createRedisDriver() { - return $this->createCacheBased('redis'); + $handler = $this->createCacheHandler('redis'); + $handler->getCache()->getStore()->setConnection($this->app['config']['session.connection']); + return $this->buildSession($handler); } protected function createCacheBased($driver) + { + return $this->buildSession($this->createCacheHandler($driver)); + } + protected function createCacheHandler($driver) { $minutes = $this->app['config']['session.lifetime']; - $handler = new CacheBasedSessionHandler($this->app['cache']->driver($driver), $minutes); - return $this->buildSession($handler); + return new CacheBasedSessionHandler($this->app['cache']->driver($driver), $minutes); } protected function buildSession($handler) { @@ -6728,11 +6860,15 @@ class Encrypter if (!$payload or $this->invalidPayload($payload)) { throw new DecryptException('Invalid data.'); } - if ($payload['mac'] !== $this->hash($payload['iv'], $payload['value'])) { + if (!$this->validMac($payload)) { throw new DecryptException('MAC is invalid.'); } return $payload; } + protected function validMac(array $payload) + { + return $payload['mac'] == $this->hash($payload['iv'], $payload['value']); + } protected function hash($iv, $value) { return hash_hmac('sha256', $iv . $value, $this->key); @@ -6915,6 +7051,7 @@ class Logger implements LoggerInterface const CRITICAL = 500; const ALERT = 550; const EMERGENCY = 600; + const API = 1; protected static $levels = array(100 => 'DEBUG', 200 => 'INFO', 250 => 'NOTICE', 300 => 'WARNING', 400 => 'ERROR', 500 => 'CRITICAL', 550 => 'ALERT', 600 => 'EMERGENCY'); protected static $timezone; protected $name; @@ -7141,6 +7278,7 @@ abstract class AbstractHandler implements HandlerInterface throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . var_export($callback, true) . ' given'); } array_unshift($this->processors, $callback); + return $this; } public function popProcessor() { @@ -7152,6 +7290,7 @@ abstract class AbstractHandler implements HandlerInterface public function setFormatter(FormatterInterface $formatter) { $this->formatter = $formatter; + return $this; } public function getFormatter() { @@ -7163,6 +7302,7 @@ abstract class AbstractHandler implements HandlerInterface public function setLevel($level) { $this->level = $level; + return $this; } public function getLevel() { @@ -7171,6 +7311,7 @@ abstract class AbstractHandler implements HandlerInterface public function setBubble($bubble) { $this->bubble = $bubble; + return $this; } public function getBubble() { @@ -7303,18 +7444,16 @@ class RotatingFileHandler extends StreamHandler if (!empty($fileInfo['extension'])) { $glob .= '.' . $fileInfo['extension']; } - $iterator = new \GlobIterator($glob); - $count = $iterator->count(); - if ($this->maxFiles >= $count) { + $logFiles = glob($glob); + if ($this->maxFiles >= count($logFiles)) { return; } - $array = iterator_to_array($iterator); - usort($array, function ($a, $b) { - return strcmp($b->getFilename(), $a->getFilename()); + usort($logFiles, function ($a, $b) { + return strcmp($b, $a); }); - foreach (array_slice($array, $this->maxFiles) as $file) { - if ($file->isWritable()) { - unlink($file->getRealPath()); + foreach (array_slice($logFiles, $this->maxFiles) as $file) { + if (is_writable($file)) { + unlink($file); } } } @@ -7819,7 +7958,8 @@ class Route extends BaseRoute protected function getAllBeforeFilters(Request $request) { $before = $this->getBeforeFilters(); - return array_merge($before, $this->router->findPatternFilters($request)); + $patterns = $this->router->findPatternFilters($request->getMethod(), $request->getPathInfo()); + return array_merge($before, $patterns); } protected function callAfterFilters(Request $request, $response) { @@ -7935,7 +8075,7 @@ class Route extends BaseRoute } public function setBeforeFilters($value) { - $filters = is_string($value) ? explode('|', $value) : (array) $value; + $filters = $this->parseFilterValue($value); $this->setOption('_before', array_merge($this->getBeforeFilters(), $filters)); } public function getAfterFilters() @@ -7944,9 +8084,17 @@ class Route extends BaseRoute } public function setAfterFilters($value) { - $filters = is_string($value) ? explode('|', $value) : (array) $value; + $filters = $this->parseFilterValue($value); $this->setOption('_after', array_merge($this->getAfterFilters(), $filters)); } + protected function parseFilterValue($value) + { + $results = array(); + foreach ((array) $value as $filters) { + $results = array_merge($results, explode('|', $filters)); + } + return $results; + } public function setParameters($parameters) { $this->parameters = $parameters; @@ -8109,7 +8257,8 @@ class Environment { $path = $this->finder->find($view); $data = array_merge($mergeData, $this->parseData($data)); - return new View($this, $this->getEngineFromPath($path), $view, $path, $data); + $this->callCreator($view = new View($this, $this->getEngineFromPath($path), $view, $path, $data)); + return $view; } protected function parseData($data) { @@ -8170,47 +8319,64 @@ class Environment $this->share($innerKey, $innerValue); } } + public function creator($views, $callback) + { + $creators = array(); + foreach ((array) $views as $view) { + $creators[] = $this->addViewEvent($view, $callback, 'creating: '); + } + return $creators; + } public function composer($views, $callback) { $composers = array(); foreach ((array) $views as $view) { - $composers[] = $this->addComposer($view, $callback); + $composers[] = $this->addViewEvent($view, $callback); } return $composers; } - protected function addComposer($view, $callback) + protected function addViewEvent($view, $callback, $prefix = 'composing: ') { if ($callback instanceof Closure) { - $this->events->listen('composing: ' . $view, $callback); + $this->events->listen($prefix . $view, $callback); return $callback; } elseif (is_string($callback)) { - return $this->addClassComposer($view, $callback); + return $this->addClassEvent($view, $callback, $prefix); } } - protected function addClassComposer($view, $class) + protected function addClassEvent($view, $class, $prefix) { - $name = 'composing: ' . $view; - $callback = $this->buildClassComposerCallback($class); + $name = $prefix . $view; + $callback = $this->buildClassEventCallback($class, $prefix); $this->events->listen($name, $callback); return $callback; } - protected function buildClassComposerCallback($class) + protected function buildClassEventCallback($class, $prefix) { $container = $this->container; - list($class, $method) = $this->parseClassComposer($class); + list($class, $method) = $this->parseClassEvent($class, $prefix); return function () use($class, $method, $container) { $callable = array($container->make($class), $method); return call_user_func_array($callable, func_get_args()); }; } - protected function parseClassComposer($class) + protected function parseClassEvent($class, $prefix) { - return str_contains($class, '@') ? explode('@', $class) : array($class, 'compose'); + if (str_contains($class, '@')) { + return explode('@', $class); + } else { + $method = str_contains($prefix, 'composing') ? 'compose' : 'create'; + return array($class, $method); + } } public function callComposer(View $view) { $this->events->fire('composing: ' . $view->getName(), array($view)); } + public function callCreator(View $view) + { + $this->events->fire('creating: ' . $view->getName(), array($view)); + } public function startSection($section, $content = '') { if ($content === '') { @@ -8246,9 +8412,9 @@ class Environment $this->sections[$section] = $content; } } - public function yieldContent($section) + public function yieldContent($section, $default = '') { - return isset($this->sections[$section]) ? $this->sections[$section] : ''; + return isset($this->sections[$section]) ? $this->sections[$section] : $default; } public function flushSections() { @@ -8300,6 +8466,10 @@ class Environment { return $this->events; } + public function setDispatcher(Dispatcher $events) + { + $this->events = $events; + } public function getContainer() { return $this->container; @@ -8414,6 +8584,11 @@ class MessageBag implements ArrayableInterface, Countable, JsonableInterface, Me public function setFormat($format = ':message') { $this->format = $format; + return $this; + } + public function isEmpty() + { + return !$this->any(); } public function any() { @@ -9119,8 +9294,16 @@ class Response $obStatus = ob_get_status(1); while (($level = ob_get_level()) > 0 && $level !== $previous) { $previous = $level; - if ($obStatus[$level - 1] && isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) { - ob_end_flush(); + if ($obStatus[$level - 1]) { + if (version_compare(PHP_VERSION, '5.4', '>=')) { + if (isset($obStatus[$level - 1]['flags']) && $obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE) { + ob_end_flush(); + } + } else { + if (isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) { + ob_end_flush(); + } + } } } flush(); @@ -9837,15 +10020,18 @@ class Run } } $output = ob_get_clean(); - if ($this->allowQuit()) { - echo $output; - die; - } else { - if ($this->writeToOutput()) { - echo $output; + if ($this->writeToOutput()) { + if ($handlerResponse == Handler::QUIT && $this->allowQuit()) { + while (ob_get_level() > 0) { + ob_end_clean(); + } } - return $output; + echo $output; } + if ($handlerResponse == Handler::QUIT && $this->allowQuit()) { + die; + } + return $output; } public function handleError($level, $message, $file = null, $line = null) { diff --git a/composer.json b/composer.json index 5b223f3c..d1769950 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,8 @@ "require": { "laravel/framework": "4.0.*", "kriswallsmith/assetic": "1.2.*@dev", - "codescale/ffmpeg-php": "2.7.0" + "codescale/ffmpeg-php": "2.7.0", + "simplepie/simplepie": "1.3.1" }, "autoload": { "classmap": [ diff --git a/public/asset.php b/public/asset.php index ce56ef1c..b314662e 100644 --- a/public/asset.php +++ b/public/asset.php @@ -33,7 +33,7 @@ $bundle->setTargetPath($filePath); } - $bundle = new AssetCache($bundle, new FilesystemCache("$cacheDirectory/scripts")); +// $bundle = new AssetCache($bundle, new FilesystemCache("$cacheDirectory/scripts")); } else if ($_GET['type'] == 'less') { header('Content-Type: text/css'); diff --git a/public/scripts/app/controllers/dashboard.coffee b/public/scripts/app/controllers/dashboard.coffee index cf97cc84..2b0ab6a8 100644 --- a/public/scripts/app/controllers/dashboard.coffee +++ b/public/scripts/app/controllers/dashboard.coffee @@ -8,8 +8,10 @@ angular.module('ponyfm').controller "dashboard", [ ($scope, dashboard) -> $scope.recentTracks = null $scope.popularTracks = null + $scope.news = null dashboard.refresh().done (res) -> $scope.recentTracks = res.recent_tracks $scope.popularTracks = res.popular_tracks + $scope.news = res.news ] \ No newline at end of file diff --git a/public/styles/content.less b/public/styles/content.less index 4ab5f5eb..ec387d00 100644 --- a/public/styles/content.less +++ b/public/styles/content.less @@ -342,7 +342,7 @@ html { line-height: normal; padding: 0px; - margin: 5px 0px; + padding: 5px 0px; padding-right: 10px; position: relative; @@ -384,6 +384,10 @@ html { margin-top: 5px; } + .artist { + .ellipsis(); + } + .artist, .stats, .genre, .stats-expanded { color: #777; font-size: 80%; diff --git a/public/styles/dashboard.less b/public/styles/dashboard.less index 6d47c386..f960a570 100644 --- a/public/styles/dashboard.less +++ b/public/styles/dashboard.less @@ -1,13 +1,49 @@ @import-once "base/bootstrap/bootstrap"; +.dashboard { + h1 { + background: @pfm-purple; + color: #fff; + font-size: 10pt; + padding: 5px; + margin: 0px; + margin-bottom: 5px; + } +} + +@media (max-width: 1300px) and (min-width: 720px) { + html .dashboard { + .recent-tracks { + width: 50%; + + .tracks-listing > li:nth-child(1n+15) { + display: none; + } + } + + .popular-tracks { + width: 50%; + float: right; + } + + .news { + width: 50%; + clear: left; + } + } +} + .recent-tracks { h1 { a { + color: #fff; display: block; float: right; font-size: 10pt; - - margin-top: 8px; + background: darken(@pfm-purple, 20%); + margin: -5px; + margin-left: 0px; + padding: 5px; } } } @@ -16,8 +52,19 @@ section { .box-sizing(border-box); - float: left; - width: 50%; padding: 5px; + float: left; } -} \ No newline at end of file + + .recent-tracks { + width: 37.5%; + } + + .popular-tracks { + width: 37.5%; + } + + .news { + width: 25%; + } +} diff --git a/public/templates/dashboard/index.html b/public/templates/dashboard/index.html index dbc3c7c6..49fbef89 100644 --- a/public/templates/dashboard/index.html +++ b/public/templates/dashboard/index.html @@ -1,20 +1,28 @@
-
-

- see more - The Newest Tunes -

- -
+

+ see more + The Newest Tunes +

+
+ +
+

Pony.fm News

+
\ No newline at end of file diff --git a/spa.pony.fm.iml b/spa.pony.fm.iml index 4adf914e..156eebe7 100644 --- a/spa.pony.fm.iml +++ b/spa.pony.fm.iml @@ -33,6 +33,7 @@ + @@ -66,14 +67,7 @@ - - - - - - - @@ -100,9 +94,9 @@ - + @@ -112,14 +106,7 @@ - - - - - - - @@ -146,9 +133,9 @@ - +