diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000..cfaf0dc1 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,10 @@ +Vagrant.configure("2") do |config| + config.vm.box = 'laravel/homestead' + + config.vm.network :private_network, ip: "192.168.33.11" + config.vm.synced_folder ".", "/vagrant", type: "nfs" + + config.vm.provision "shell", path: "vagrant/install.sh" + + config.vm.synced_folder "../pony.fm.files", "/vagrant-files" +end \ No newline at end of file diff --git a/app/start/global.php b/app/start/global.php index b507135b..6a81c394 100644 --- a/app/start/global.php +++ b/app/start/global.php @@ -74,7 +74,7 @@ App::down(function() }); Auth::extend('pfm', function() { - return new Guard(new PFMAuth(), App::make('session')); + return new Guard(new PFMAuth(), App::make('session.store')); }); Validator::resolver(function($translator, $data, $rules, $messages) diff --git a/bootstrap/compiled.php b/bootstrap/compiled.php index 2079b47f..14971c69 100644 --- a/bootstrap/compiled.php +++ b/bootstrap/compiled.php @@ -52,7 +52,10 @@ class ClassLoader } namespace Illuminate\Container; -use Closure, ArrayAccess, ReflectionParameter; +use Closure; +use ArrayAccess; +use ReflectionClass; +use ReflectionParameter; class BindingResolutionException extends \Exception { @@ -63,6 +66,7 @@ class Container implements ArrayAccess protected $instances = array(); protected $aliases = array(); protected $resolvingCallbacks = array(); + protected $globalResolvingCallbacks = array(); public function bound($abstract) { return isset($this[$abstract]) or isset($this->instances[$abstract]); @@ -146,7 +150,7 @@ class Container implements ArrayAccess if ($this->isShared($abstract)) { $this->instances[$abstract] = $object; } - $this->fireResolvingCallbacks($object); + $this->fireResolvingCallbacks($abstract, $object); return $object; } protected function getConcrete($abstract) @@ -162,7 +166,7 @@ class Container implements ArrayAccess if ($concrete instanceof Closure) { return $concrete($this, $parameters); } - $reflector = new \ReflectionClass($concrete); + $reflector = new ReflectionClass($concrete); if (!$reflector->isInstantiable()) { $message = "Target [{$concrete}] is not instantiable."; throw new BindingResolutionException($message); @@ -209,13 +213,24 @@ class Container implements ArrayAccess } } } - public function resolving(Closure $callback) + public function resolving($abstract, Closure $callback) { - $this->resolvingCallbacks[] = $callback; + $this->resolvingCallbacks[$abstract][] = $callback; } - protected function fireResolvingCallbacks($object) + public function resolvingAny(Closure $callback) { - foreach ($this->resolvingCallbacks as $callback) { + $this->globalResolvingCallbacks[] = $callback; + } + protected function fireResolvingCallbacks($abstract, $object) + { + if (isset($this->resolvingCallbacks[$abstract])) { + $this->fireCallbackArray($object, $this->resolvingCallbacks[$abstract]); + } + $this->fireCallbackArray($object, $this->globalResolvingCallbacks); + } + protected function fireCallbackArray($object, array $callbacks) + { + foreach ($callbacks as $callback) { call_user_func($callback, $object); } } @@ -256,6 +271,7 @@ class Container implements ArrayAccess public function offsetUnset($key) { unset($this->bindings[$key]); + unset($this->instances[$key]); } } namespace Symfony\Component\HttpKernel; @@ -294,15 +310,15 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\Debug\Exception\FatalErrorException; use Illuminate\Support\Contracts\ResponsePreparerInterface; -use Symfony\Component\HttpKernel\Exception\FatalErrorException; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirect; class Application extends Container implements HttpKernelInterface, ResponsePreparerInterface { - const VERSION = '4.0.7'; + const VERSION = '4.0.11'; protected $booted = false; protected $bootingCallbacks = array(); protected $bootedCallbacks = array(); @@ -314,8 +330,24 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep public function __construct(Request $request = null) { $this['request'] = $this->createRequest($request); + $this->registerBaseServiceProviders(); + } + protected function registerBaseServiceProviders() + { + foreach (array('Exception', 'Routing', 'Event') as $name) { + $this->{"register{$name}Provider"}(); + } + } + protected function registerExceptionProvider() + { $this->register(new ExceptionServiceProvider($this)); + } + protected function registerRoutingProvider() + { $this->register(new RoutingServiceProvider($this)); + } + protected function registerEventProvider() + { $this->register(new EventServiceProvider($this)); } protected function createRequest(Request $request = null) @@ -348,7 +380,7 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep } public static function getBootstrapFile() { - return 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation' . '/start.php'; + return '/vagrant/vendor/laravel/framework/src/Illuminate/Foundation' . '/start.php'; } public function startExceptionHandling() { @@ -357,7 +389,11 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep } public function environment() { - return $this['env']; + if (count(func_get_args()) > 0) { + return in_array($this['env'], func_get_args()); + } else { + return $this['env']; + } } public function detectEnvironment($environments) { @@ -415,6 +451,7 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep } $this->serviceProviders[] = $provider; $this->loadedProviders[get_class($provider)] = true; + return $provider; } protected function resolveProviderClass($provider) { @@ -530,8 +567,8 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep } public function prepareRequest(Request $request) { - if (isset($this['session'])) { - $request->setSessionStore($this['session']); + if (isset($this['session.store'])) { + $request->setSessionStore($this['session.store']); } return $request; } @@ -587,6 +624,10 @@ class Application extends Container implements HttpKernelInterface, ResponsePrep $manifest = $this['config']['app.manifest']; return new ProviderRepository(new Filesystem(), $manifest); } + public function getLocale() + { + return $this['config']->get('app.locale'); + } public function setLocale($locale) { $this['config']->set('app.locale', $locale); @@ -625,7 +666,8 @@ namespace Illuminate\Http; use Illuminate\Session\Store as SessionStore; use Symfony\Component\HttpFoundation\ParameterBag; -class Request extends \Symfony\Component\HttpFoundation\Request +use Symfony\Component\HttpFoundation\Request as SymfonyRequest; +class Request extends SymfonyRequest { protected $json; protected $sessionStore; @@ -698,7 +740,7 @@ class Request extends \Symfony\Component\HttpFoundation\Request } public function all() { - return $this->input() + $this->files->all(); + return array_merge_recursive($this->input(), $this->files->all()); } public function input($key = null, $default = null) { @@ -729,11 +771,14 @@ class Request extends \Symfony\Component\HttpFoundation\Request } public function file($key = null, $default = null) { - return $this->retrieveItem('files', $key, $default); + return array_get($this->files->all(), $key, $default); } public function hasFile($key) { - return $this->files->has($key) and !is_null($this->file($key)); + if (is_array($file = $this->file($key))) { + $file = head($file); + } + return $file instanceof \SplFileInfo; } public function header($key = null, $default = null) { @@ -894,7 +939,16 @@ class Request } public static function createFromGlobals() { - $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); + $server = $_SERVER; + if ('cli-server' === php_sapi_name()) { + if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) { + $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH']; + } + if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { + $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']; + } + } + $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $server); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); @@ -1001,7 +1055,7 @@ class Request $dup->attributes->set('_format', $this->get('_format')); } if (!$dup->getRequestFormat(null)) { - $dup->setRequestFormat($format = $this->getRequestFormat(null)); + $dup->setRequestFormat($this->getRequestFormat(null)); } return $dup; } @@ -1023,6 +1077,7 @@ class Request } public function overrideGlobals() { + $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&'))); $_GET = $this->query->all(); $_POST = $this->request->all(); $_SERVER = $this->server->all(); @@ -1036,7 +1091,7 @@ class Request } } $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE); - $requestOrder = ini_get('request_order') ?: ini_get('variable_order'); + $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = array(); foreach (str_split($requestOrder) as $order) { @@ -1104,7 +1159,16 @@ class Request } public function get($key, $default = null, $deep = false) { - return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep); + if ($this !== ($result = $this->query->get($key, $this, $deep))) { + return $result; + } + if ($this !== ($result = $this->attributes->get($key, $this, $deep))) { + return $result; + } + if ($this !== ($result = $this->request->get($key, $this, $deep))) { + return $result; + } + return $default; } public function getSession() { @@ -1125,7 +1189,7 @@ class Request public function getClientIps() { $ip = $this->server->get('REMOTE_ADDR'); - if (!self::$trustedProxies) { + if (!$this->isFromTrustedProxy()) { return array($ip); } if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) { @@ -1133,12 +1197,13 @@ class Request } $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP]))); $clientIps[] = $ip; - $trustedProxies = !self::$trustedProxies ? array($ip) : self::$trustedProxies; $ip = $clientIps[0]; foreach ($clientIps as $key => $clientIp) { - if (IpUtils::checkIp($clientIp, $trustedProxies)) { + if (preg_match('{((?:\\d+\\.){3}\\d+)\\:\\d+}', $clientIp, $match)) { + $clientIps[$key] = $clientIp = $match[1]; + } + if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { unset($clientIps[$key]); - continue; } } return $clientIps ? array_reverse($clientIps) : array($ip); @@ -1179,7 +1244,7 @@ class Request } public function getPort() { - if (self::$trustedProxies) { + if ($this->isFromTrustedProxy()) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && ($port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT]))) { return $port; } @@ -1188,8 +1253,13 @@ class Request } } if ($host = $this->headers->get('HOST')) { - if (false !== ($pos = strrpos($host, ':'))) { - return intval(substr($host, $pos + 1)); + if ($host[0] === '[') { + $pos = strpos($host, ':', strrpos($host, ']')); + } else { + $pos = strrpos($host, ':'); + } + if (false !== $pos) { + return (int) substr($host, $pos + 1); } return 'https' === $this->getScheme() ? 443 : 80; } @@ -1197,11 +1267,11 @@ class Request } public function getUser() { - return $this->server->get('PHP_AUTH_USER'); + return $this->headers->get('PHP_AUTH_USER'); } public function getPassword() { - return $this->server->get('PHP_AUTH_PW'); + return $this->headers->get('PHP_AUTH_PW'); } public function getUserInfo() { @@ -1250,14 +1320,15 @@ class Request } public function isSecure() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && ($proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO]))) { - return in_array(strtolower($proto), array('https', 'on', '1')); + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && ($proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO]))) { + return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); } - return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS'); + $https = $this->server->get('HTTPS'); + return !empty($https) && 'off' !== strtolower($https); } public function getHost() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && ($host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST]))) { + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && ($host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST]))) { $elements = explode(',', $host); $host = $elements[count($elements) - 1]; } elseif (!($host = $this->headers->get('HOST'))) { @@ -1266,7 +1337,7 @@ class Request } } $host = strtolower(preg_replace('/:\\d+$/', '', trim($host))); - if ($host && !preg_match('/^\\[?(?:[a-zA-Z0-9-:\\]_]+\\.?)+$/', $host)) { + if ($host && '' !== preg_replace('/(?:^\\[)?[a-zA-Z0-9-:\\]_]+\\.?/', '', $host)) { throw new \UnexpectedValueException('Invalid Host "' . $host . '"'); } if (count(self::$trustedHostPatterns) > 0) { @@ -1326,7 +1397,6 @@ class Request return $format; } } - return null; } public function setFormat($format, $mimeTypes) { @@ -1357,6 +1427,10 @@ class Request $this->setPhpDefaultLocale($locale); } } + public function getDefaultLocale() + { + return $this->defaultLocale; + } public function setLocale($locale) { $this->setPhpDefaultLocale($this->locale = $locale); @@ -1427,13 +1501,13 @@ class Request foreach (array_keys($languages) as $lang) { if (strstr($lang, '-')) { $codes = explode('-', $lang); - if ($codes[0] == 'i') { + if ('i' === $codes[0]) { if (count($codes) > 1) { $lang = $codes[1]; } } else { for ($i = 0, $max = count($codes); $i < $max; $i++) { - if ($i == 0) { + if ($i === 0) { $lang = strtolower($codes[0]); } else { $lang .= '_' . strtoupper($codes[$i]); @@ -1522,7 +1596,7 @@ class Request if ($baseUrl && false !== ($prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl))) { return $prefix; } - if ($baseUrl && false !== ($prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl)))) { + if ($baseUrl && false !== ($prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl) . '/'))) { return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; @@ -1592,11 +1666,15 @@ class Request return false; } $len = strlen($prefix); - if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) { + if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { return $match[0]; } return false; } + private function isFromTrustedProxy() + { + return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); + } } namespace Symfony\Component\HttpFoundation; @@ -1773,8 +1851,8 @@ class FileBag extends ParameterBag foreach (self::$fileKeys as $k) { unset($files[$k]); } - foreach (array_keys($data['name']) as $key) { - $files[$key] = $this->fixPhpFilesArray(array('error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key])); + foreach ($data['name'] as $key => $name) { + $files[$key] = $this->fixPhpFilesArray(array('error' => $data['error'][$key], 'name' => $name, 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key])); } return $files; } @@ -1805,12 +1883,12 @@ class ServerBag extends ParameterBag $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; } if (null !== $authorizationHeader) { - if (0 === stripos($authorizationHeader, 'basic')) { - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6))); + if (0 === stripos($authorizationHeader, 'basic ')) { + $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); 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')) { + } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && 0 === stripos($authorizationHeader, 'digest ')) { $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; } @@ -2006,7 +2084,6 @@ interface SessionInterface namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; interface SessionStorageInterface { public function start(); @@ -2050,7 +2127,6 @@ use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; class Session implements SessionInterface, \IteratorAggregate, \Countable { @@ -2161,7 +2237,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -2176,7 +2251,7 @@ class NativeSessionStorage implements SessionStorageInterface { session_cache_limiter(''); ini_set('session.use_cookies', 1); - if (version_compare(phpversion(), '5.4.0', '>=')) { + if (PHP_VERSION_ID >= 50400) { session_register_shutdown(); } else { register_shutdown_function('session_write_close'); @@ -2191,13 +2266,13 @@ class NativeSessionStorage implements SessionStorageInterface } public function start() { - if ($this->started && !$this->closed) { + if ($this->started) { return true; } - if (version_compare(phpversion(), '5.4.0', '>=') && \PHP_SESSION_ACTIVE === session_status()) { + if (PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } - if (version_compare(phpversion(), '5.4.0', '<') && isset($_SESSION) && session_id()) { + if (PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) { throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).'); } if (ini_get('session.use_cookies') && headers_sent($file, $line)) { @@ -2214,9 +2289,6 @@ class NativeSessionStorage implements SessionStorageInterface } public function getId() { - if (!$this->started) { - return ''; - } return $this->saveHandler->getId(); } public function setId($id) @@ -2239,19 +2311,7 @@ class NativeSessionStorage implements SessionStorageInterface if ($destroy) { $this->metadataBag->stampNew(); } - $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(); - } - $this->loadSession(); - } - return $ret; + return session_regenerate_id($destroy); } public function save() { @@ -2260,6 +2320,7 @@ class NativeSessionStorage implements SessionStorageInterface $this->saveHandler->setActive(false); } $this->closed = true; + $this->started = false; } public function clear() { @@ -2317,11 +2378,11 @@ class NativeSessionStorage implements SessionStorageInterface if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = version_compare(phpversion(), '5.4.0', '>=') ? new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy(); + $saveHandler = PHP_VERSION_ID >= 50400 ? new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy(); } $this->saveHandler = $saveHandler; if ($this->saveHandler instanceof \SessionHandlerInterface) { - if (version_compare(phpversion(), '5.4.0', '>=')) { + if (PHP_VERSION_ID >= 50400) { session_set_save_handler($this->saveHandler, false); } else { session_set_save_handler(array($this->saveHandler, 'open'), array($this->saveHandler, 'close'), array($this->saveHandler, 'read'), array($this->saveHandler, 'write'), array($this->saveHandler, 'destroy'), array($this->saveHandler, 'gc')); @@ -2660,7 +2721,7 @@ class MetadataBag implements SessionBagInterface } namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; -if (version_compare(phpversion(), '5.4.0', '>=')) { +if (PHP_VERSION_ID >= 50400) { class NativeSessionHandler extends \SessionHandler { @@ -2692,14 +2753,14 @@ abstract class AbstractProxy } public function isActive() { - if (version_compare(phpversion(), '5.4.0', '>=')) { + if (PHP_VERSION_ID >= 50400) { return $this->active = \PHP_SESSION_ACTIVE === session_status(); } return $this->active; } public function setActive($flag) { - if (version_compare(phpversion(), '5.4.0', '>=')) { + if (PHP_VERSION_ID >= 50400) { throw new \LogicException('This method is disabled in PHP 5.4.0+'); } $this->active = (bool) $flag; @@ -2751,17 +2812,17 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf $this->active = false; return (bool) $this->handler->close(); } - public function read($id) + public function read($sessionId) { - return (string) $this->handler->read($id); + return (string) $this->handler->read($sessionId); } - public function write($id, $data) + public function write($sessionId, $data) { - return (bool) $this->handler->write($id, $data); + return (bool) $this->handler->write($sessionId, $data); } - public function destroy($id) + public function destroy($sessionId) { - return (bool) $this->handler->destroy($id); + return (bool) $this->handler->destroy($sessionId); } public function gc($maxlifetime) { @@ -2935,9 +2996,6 @@ namespace Symfony\Component\Debug; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Debug\Exception\FlattenException; -if (!defined('ENT_SUBSTITUTE')) { - define('ENT_SUBSTITUTE', 8); -} class ExceptionHandler { private $debug; @@ -2966,9 +3024,12 @@ class ExceptionHandler if (!$exception instanceof FlattenException) { $exception = FlattenException::create($exception); } - header(sprintf('HTTP/1.0 %s', $exception->getStatusCode())); - foreach ($exception->getHeaders() as $name => $value) { - header($name . ': ' . $value, false); + if (!headers_sent()) { + header(sprintf('HTTP/1.0 %s', $exception->getStatusCode())); + foreach ($exception->getHeaders() as $name => $value) { + header($name . ': ' . $value, false); + } + header('Content-Type: text/html; charset=' . $this->charset); } echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception)); } @@ -2977,7 +3038,7 @@ class ExceptionHandler if (!$exception instanceof FlattenException) { $exception = FlattenException::create($exception); } - return new Response($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders()); + return Response::create($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset); } public function getContent(FlattenException $exception) { @@ -2989,6 +3050,7 @@ class ExceptionHandler $title = 'Whoops, looks like something went wrong.'; } $content = ''; + $flags = PHP_VERSION_ID >= 50400 ? ENT_QUOTES | ENT_SUBSTITUTE : ENT_QUOTES; if ($this->debug) { try { $count = count($exception->getAllPrevious()); @@ -2996,7 +3058,7 @@ class ExceptionHandler foreach ($exception->toArray() as $position => $e) { $ind = $count - $position + 1; $class = $this->abbrClass($e['class']); - $message = nl2br($e['message']); + $message = nl2br(htmlspecialchars($e['message'], $flags, $this->charset)); $content .= sprintf('

%d/%d %s: %s

@@ -3024,7 +3086,7 @@ class ExceptionHandler } } catch (\Exception $e) { if ($this->debug) { - $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($exception), $exception->getMessage()); + $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), htmlspecialchars($e->getMessage(), $flags, $this->charset)); } else { $title = 'Whoops, looks like something went wrong.'; } @@ -3087,7 +3149,7 @@ class ExceptionHandler } private function decorate($content, $css) { - return "\n\n \n \n \n \n \n \n {$content}\n \n"; + return "\n\n \n \n \n \n \n \n {$content}\n \n"; } private function abbrClass($class) { @@ -3096,6 +3158,11 @@ class ExceptionHandler } private function formatArgs(array $args) { + if (PHP_VERSION_ID >= 50400) { + $flags = ENT_QUOTES | ENT_SUBSTITUTE; + } else { + $flags = ENT_QUOTES; + } $result = array(); foreach ($args as $key => $item) { if ('object' === $item[0]) { @@ -3103,7 +3170,7 @@ class ExceptionHandler } elseif ('array' === $item[0]) { $formattedValue = sprintf('array(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); } elseif ('string' === $item[0]) { - $formattedValue = sprintf('\'%s\'', htmlspecialchars($item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset)); + $formattedValue = sprintf('\'%s\'', htmlspecialchars($item[1], $flags, $this->charset)); } elseif ('null' === $item[0]) { $formattedValue = 'null'; } elseif ('boolean' === $item[0]) { @@ -3112,7 +3179,7 @@ class ExceptionHandler $formattedValue = 'resource'; } else { $formattedValue = str_replace(' -', '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), true)); +', '', var_export(htmlspecialchars((string) $item[1], $flags, $this->charset), true)); } $result[] = is_int($key) ? $formattedValue : sprintf('\'%s\' => %s', $key, $formattedValue); } @@ -3147,7 +3214,7 @@ abstract class ServiceProvider if ($this->app['files']->isDirectory($lang)) { $this->app['translator']->addNamespace($namespace, $lang); } - $appView = $this->getAppViewPath($package, $namespace); + $appView = $this->getAppViewPath($package); if ($this->app['files']->isDirectory($appView)) { $this->app['view']->addNamespace($namespace, $appView); } @@ -3187,9 +3254,9 @@ abstract class ServiceProvider $artisan->resolveCommands($commands); }); } - protected function getAppViewPath($package, $namespace) + protected function getAppViewPath($package) { - return $this->app['path'] . "/views/packages/{$package}/{$namespace}"; + return $this->app['path'] . "/views/packages/{$package}"; } public function provides() { @@ -3203,6 +3270,7 @@ abstract class ServiceProvider namespace Illuminate\Exception; use Closure; +use Whoops\Run; use Whoops\Handler\PrettyPageHandler; use Whoops\Handler\JsonResponseHandler; use Illuminate\Support\ServiceProvider; @@ -3229,8 +3297,12 @@ class ExceptionServiceProvider extends ServiceProvider protected function registerPlainDisplayer() { $this->app['exception.plain'] = $this->app->share(function ($app) { - $handler = new KernelHandler($app['config']['app.debug']); - return new SymfonyDisplayer($handler); + if ($app->runningInConsole()) { + return $app['exception.debug']; + } else { + $handler = new KernelHandler($app['config']['app.debug']); + return new SymfonyDisplayer($handler); + } }); } protected function registerDebugDisplayer() @@ -3244,7 +3316,7 @@ class ExceptionServiceProvider extends ServiceProvider { $this->registerWhoopsHandler(); $this->app['whoops'] = $this->app->share(function ($app) { - with($whoops = new \Whoops\Run())->allowQuit(false); + with($whoops = new Run())->allowQuit(false); return $whoops->pushHandler($app['whoops.handler']); }); } @@ -3282,7 +3354,8 @@ class ExceptionServiceProvider extends ServiceProvider } protected function getResourcePath() { - return 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\laravel\\framework\\src\\Illuminate\\Exception' . '/resources'; + $base = $this->app['path.base']; + return $base . '/vendor/laravel/framework/src/Illuminate/Exception/resources'; } } namespace Illuminate\Routing; @@ -3317,8 +3390,8 @@ class RoutingServiceProvider extends ServiceProvider { $this->app['redirect'] = $this->app->share(function ($app) { $redirector = new Redirector($app['url']); - if (isset($app['session'])) { - $redirector->setSession($app['session']); + if (isset($app['session.store'])) { + $redirector->setSession($app['session.store']); } return $redirector; }); @@ -3354,11 +3427,23 @@ abstract class Facade if (static::isMock()) { $mock = static::$resolvedInstance[$name]; } else { - static::$resolvedInstance[$name] = $mock = \Mockery::mock(static::getMockableClass($name)); - static::$app->instance($name, $mock); + $mock = static::createFreshMockInstance($name); } return call_user_func_array(array($mock, 'shouldReceive'), func_get_args()); } + protected static function createFreshMockInstance($name) + { + static::$resolvedInstance[$name] = $mock = static::createMockByName($name); + if (isset(static::$app)) { + static::$app->instance($name, $mock); + } + return $mock; + } + protected static function createMockByName($name) + { + $class = static::getMockableClass($name); + return $class ? \Mockery::mock($class) : \Mockery::mock(); + } protected static function isMock() { $name = static::getFacadeAccessor(); @@ -3366,7 +3451,9 @@ abstract class Facade } protected static function getMockableClass() { - return get_class(static::getFacadeRoot()); + if ($root = static::getFacadeRoot()) { + return get_class($root); + } } public static function getFacadeRoot() { @@ -3434,10 +3521,10 @@ class Str { return lcfirst(static::studly($value)); } - public static function contains($haystack, $needle) + public static function contains($haystack, $needles) { - foreach ((array) $needle as $n) { - if (strpos($haystack, $n) !== false) { + foreach ((array) $needles as $needle) { + if ($needle != '' && strpos($haystack, $needle) !== false) { return true; } } @@ -3446,7 +3533,7 @@ class Str public static function endsWith($haystack, $needles) { foreach ((array) $needles as $needle) { - if ($needle == substr($haystack, strlen($haystack) - strlen($needle))) { + if ($needle == substr($haystack, -strlen($needle))) { return true; } } @@ -3454,7 +3541,8 @@ class Str } public static function finish($value, $cap) { - return rtrim($value, $cap) . $cap; + $quoted = preg_quote($cap, '/'); + return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap; } public static function is($pattern, $value) { @@ -3462,11 +3550,7 @@ class Str return true; } $pattern = preg_quote($pattern, '#'); - if ($pattern !== '/') { - $pattern = str_replace('\\*', '.*', $pattern) . '\\z'; - } else { - $pattern = '/$'; - } + $pattern = str_replace('\\*', '.*', $pattern) . '\\z'; return (bool) preg_match('#^' . $pattern . '#', $value); } public static function length($value) @@ -3523,6 +3607,10 @@ class Str { return mb_strtoupper($value); } + public static function title($value) + { + return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8'); + } public static function singular($value) { return Pluralizer::singular($value); @@ -3544,7 +3632,7 @@ class Str public static function startsWith($haystack, $needles) { foreach ((array) $needles as $needle) { - if (strpos($haystack, $needle) === 0) { + if ($needle != '' && strpos($haystack, $needle) === 0) { return true; } } @@ -3571,6 +3659,7 @@ namespace Symfony\Component\Debug; use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\Exception\ContextErrorException; +use Symfony\Component\Debug\Exception\DummyException; use Psr\Log\LoggerInterface; class ErrorHandler { @@ -3610,7 +3699,7 @@ class ErrorHandler } if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) { if (isset(self::$loggers['deprecation'])) { - if (version_compare(PHP_VERSION, '5.4', '<')) { + if (PHP_VERSION_ID < 50400) { $stack = array_map(function ($row) { unset($row['args']); return $row; @@ -3624,9 +3713,31 @@ class ErrorHandler } 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'; + require '/vagrant/vendor/symfony/debug/Symfony/Component/Debug' . '/Exception/ContextErrorException.php'; + } + if (!class_exists('Symfony\\Component\\Debug\\Exception\\FlattenException')) { + require '/vagrant/vendor/symfony/debug/Symfony/Component/Debug' . '/Exception/FlattenException.php'; + } + if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && is_array($context)) { + unset($context['GLOBALS']); + } + $exception = 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); + $exceptionHandler = set_exception_handler(function () { + + }); + restore_exception_handler(); + if (is_array($exceptionHandler) && $exceptionHandler[0] instanceof ExceptionHandler) { + $exceptionHandler[0]->handle($exception); + if (!class_exists('Symfony\\Component\\Debug\\Exception\\DummyException')) { + require '/vagrant/vendor/symfony/debug/Symfony/Component/Debug' . '/Exception/DummyException.php'; + } + set_exception_handler(function (\Exception $e) use($exceptionHandler) { + if (!$e instanceof DummyException) { + call_user_func($exceptionHandler, $e); + } + }); + throw new DummyException(); } - 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; } @@ -3773,7 +3884,7 @@ class Repository extends NamespacedItemResolver implements ArrayAccess } public function addNamespace($namespace, $hint) { - return $this->loader->addNamespace($namespace, $hint); + $this->loader->addNamespace($namespace, $hint); } public function getNamespaces() { @@ -3997,6 +4108,14 @@ class Filesystem { return file_put_contents($path, $contents); } + public function prepend($path, $data) + { + if ($this->exists($path)) { + return $this->put($path, $data . $this->get($path)); + } else { + return $this->put($path, $data); + } + } public function append($path, $data) { return file_put_contents($path, $data, FILE_APPEND); @@ -4067,9 +4186,13 @@ class Filesystem } return $directories; } - public function makeDirectory($path, $mode = 511, $recursive = false) + public function makeDirectory($path, $mode = 511, $recursive = false, $force = false) { - return mkdir($path, $mode, $recursive); + if ($force) { + return @mkdir($path, $mode, $recursive); + } else { + return mkdir($path, $mode, $recursive); + } } public function copyDirectory($directory, $destination, $options = null) { @@ -4099,7 +4222,7 @@ class Filesystem public function deleteDirectory($directory, $preserve = false) { if (!$this->isDirectory($directory)) { - return; + return false; } $items = new FilesystemIterator($directory); foreach ($items as $item) { @@ -4112,6 +4235,7 @@ class Filesystem if (!$preserve) { @rmdir($directory); } + return true; } public function cleanDirectory($directory) { @@ -4257,6 +4381,15 @@ namespace Illuminate\Cookie; use Illuminate\Support\ServiceProvider; class CookieServiceProvider extends ServiceProvider { + public function boot() + { + $app = $this->app; + $this->app->after(function ($request, $response) use($app) { + foreach ($app['cookie']->getQueuedCookies() as $cookie) { + $response->headers->setCookie($cookie); + } + }); + } public function register() { $this->app['cookie'] = $this->app->share(function ($app) { @@ -4317,6 +4450,7 @@ namespace Illuminate\Session; use Illuminate\Support\ServiceProvider; class SessionServiceProvider extends ServiceProvider { + protected $cookieDefaults = array('secure' => false, 'http_only' => true); public function boot() { $this->registerSessionEvents(); @@ -4335,14 +4469,14 @@ class SessionServiceProvider extends ServiceProvider } protected function registerSessionManager() { - $this->app['session.manager'] = $this->app->share(function ($app) { + $this->app['session'] = $this->app->share(function ($app) { return new SessionManager($app); }); } protected function registerSessionDriver() { - $this->app['session'] = $this->app->share(function ($app) { - $manager = $app['session.manager']; + $this->app['session.store'] = $this->app->share(function ($app) { + $manager = $app['session']; return $manager->driver(); }); } @@ -4357,7 +4491,7 @@ class SessionServiceProvider extends ServiceProvider protected function registerBootingEvent() { $this->app->booting(function ($app) { - $app['session']->start(); + $app['session.store']->start(); }); } protected function registerCloseEvent() @@ -4368,7 +4502,7 @@ class SessionServiceProvider extends ServiceProvider $this->registerCookieToucher(); $app = $this->app; $this->app->close(function () use($app) { - $app['session']->save(); + $app['session.store']->save(); }); } protected function registerCookieToucher() @@ -4382,9 +4516,9 @@ class SessionServiceProvider extends ServiceProvider } public function touchSessionCookie() { - $config = $this->app['config']['session']; + $config = array_merge($this->cookieDefaults, $this->app['config']['session']); $expire = $this->getExpireTime($config); - setcookie($config['cookie'], session_id(), $expire, $config['path'], $config['domain'], false, true); + setcookie($config['cookie'], session_id(), $expire, $config['path'], $config['domain'], $config['secure'], $config['http_only']); } protected function getExpireTime($config) { @@ -4462,7 +4596,7 @@ class ViewServiceProvider extends ServiceProvider list($app, $me) = array($this->app, $this); $app->booted(function () use($app, $me) { if ($me->sessionHasErrors($app)) { - $errors = $app['session']->get('errors'); + $errors = $app['session.store']->get('errors'); $app['view']->share('errors', $errors); } else { $app['view']->share('errors', new MessageBag()); @@ -4472,8 +4606,8 @@ class ViewServiceProvider extends ServiceProvider public function sessionHasErrors($app) { $config = $app['config']['session']; - if (isset($app['session']) and !is_null($config['driver'])) { - return $app['session']->has('errors'); + if (isset($app['session.store']) and !is_null($config['driver'])) { + return $app['session.store']->has('errors'); } } } @@ -4922,7 +5056,7 @@ class Router { foreach ((array) $names as $name) { if (!is_null($methods)) { - $methods = array_change_key_case((array) $methods); + $methods = array_map('strtolower', (array) $methods); } $this->patternFilters[$pattern][] = compact('name', 'methods'); } @@ -5257,12 +5391,12 @@ class Dispatcher public function listen($event, $listener, $priority = 0) { if (str_contains($event, '*')) { - return $this->setupWildcardListen($event, $listener, $priority = 0); + return $this->setupWildcardListen($event, $listener); } $this->listeners[$event][$priority][] = $this->makeListener($listener); unset($this->sorted[$event]); } - protected function setupWildcardListen($event, $listener, $priority) + protected function setupWildcardListen($event, $listener) { $this->wildcards[$event][] = $this->makeListener($listener); } @@ -5370,11 +5504,12 @@ namespace Illuminate\Database\Eloquent; use Closure; use DateTime; -use Carbon\Carbon; use ArrayAccess; +use Carbon\Carbon; use Illuminate\Events\Dispatcher; use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Contracts\JsonableInterface; @@ -5418,9 +5553,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa public function __construct(array $attributes = array()) { if (!isset(static::$booted[get_class($this)])) { - static::boot(); static::$booted[get_class($this)] = true; + static::boot(); } + $this->syncOriginal(); $this->fill($attributes); } protected static function boot() @@ -5448,7 +5584,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function fill(array $attributes) { - foreach ($attributes as $key => $value) { + foreach ($this->fillableFromArray($attributes) as $key => $value) { $key = $this->removeTableFromKey($key); if ($this->isFillable($key)) { $this->setAttribute($key, $value); @@ -5458,6 +5594,13 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } return $this; } + protected function fillableFromArray(array $attributes) + { + if (count($this->fillable) > 0 and !static::$unguarded) { + return array_intersect_key($attributes, array_flip($this->fillable)); + } + return $attributes; + } public function newInstance($attributes = array(), $exists = false) { $model = new static((array) $attributes); @@ -5476,6 +5619,28 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa $model->save(); return $model; } + public static function firstOrCreate(array $attributes) + { + if (!is_null($instance = static::firstByAttributes($attributes))) { + return $instance; + } + return static::create($attributes); + } + public static function firstOrNew(array $attributes) + { + if (!is_null($instance = static::firstByAttributes($attributes))) { + return $instance; + } + return new static($attributes); + } + protected static function firstByAttributes($attributes) + { + $query = static::query(); + foreach ($attributes as $key => $value) { + $query->where($key, $value); + } + return $query->first() ?: null; + } public static function query() { return with(new static())->newQuery(); @@ -5494,9 +5659,6 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa public static function find($id, $columns = array('*')) { $instance = new static(); - if (is_array($id)) { - return $instance->newQuery()->whereIn($instance->getKeyName(), $id)->get($columns); - } return $instance->newQuery()->find($id, $columns); } public static function findOrFail($id, $columns = array('*')) @@ -5513,6 +5675,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } $query = $this->newQuery()->with($relations); $query->eagerLoadRelations(array($this)); + return $this; } public static function with($relations) { @@ -5770,7 +5933,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa $this->touchOwners(); } } - protected function performUpdate($query) + protected function performUpdate(Builder $query) { $dirty = $this->getDirty(); if (count($dirty) > 0) { @@ -5786,7 +5949,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } return true; } - protected function performInsert($query) + protected function performInsert(Builder $query) { if ($this->fireModelEvent('creating') === false) { return false; @@ -5804,7 +5967,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa $this->fireModelEvent('created', false); return true; } - protected function insertAndSetId($query, $attributes) + protected function insertAndSetId(Builder $query, $attributes) { $id = $query->insertGetId($attributes, $keyName = $this->getKeyName()); $this->setAttribute($keyName, $id); @@ -5828,11 +5991,19 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa $method = $halt ? 'until' : 'fire'; return static::$dispatcher->{$method}($event, $this); } - protected function setKeysForSaveQuery($query) + protected function setKeysForSaveQuery(Builder $query) { - $query->where($this->getKeyName(), '=', $this->getKey()); + $query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery()); return $query; } + protected function getKeyForSaveQuery() + { + if (isset($this->original[$this->getKeyName()])) { + return $this->original[$this->getKeyName()]; + } else { + return $this->getAttribute($this->getKeyName()); + } + } public function touch() { $this->updateTimestamps(); @@ -5917,6 +6088,10 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa { return new Collection($models); } + public function newPivot(Model $parent, array $attributes, $table, $exists) + { + return new Pivot($parent, $attributes, $table, $exists); + } public function getTable() { if (isset($this->table)) { @@ -6185,7 +6360,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } elseif (is_numeric($value)) { $value = Carbon::createFromTimestamp($value); } elseif (preg_match('/^(\\d{4})-(\\d{2})-(\\d{2})$/', $value)) { - $value = Carbon::createFromFormat('Y-m-d', $value); + $value = Carbon::createFromFormat('Y-m-d', $value)->startOfDay(); } elseif (!$value instanceof DateTime) { $value = Carbon::createFromFormat($format, $value); } @@ -6196,7 +6371,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa if (is_numeric($value)) { return Carbon::createFromTimestamp($value); } elseif (preg_match('/^(\\d{4})-(\\d{2})-(\\d{2})$/', $value)) { - return Carbon::createFromFormat('Y-m-d', $value); + return Carbon::createFromFormat('Y-m-d', $value)->startOfDay(); } elseif (!$value instanceof DateTime) { $format = $this->getDateFormat(); return Carbon::createFromFormat($format, $value); @@ -6336,7 +6511,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function __isset($key) { - return isset($this->attributes[$key]) or isset($this->relations[$key]); + return isset($this->attributes[$key]) or isset($this->relations[$key]) or $this->hasGetMutator($key) and !is_null($this->getAttributeValue($key)); } public function __unset($key) { @@ -6400,9 +6575,14 @@ class DatabaseManager implements ConnectionResolverInterface public function reconnect($name = null) { $name = $name ?: $this->getDefaultConnection(); - unset($this->connections[$name]); + $this->disconnect($name); return $this->connection($name); } + public function disconnect($name = null) + { + $name = $name ?: $this->getDefaultConnection(); + unset($this->connections[$name]); + } protected function makeConnection($name) { $config = $this->getConfig($name); @@ -6451,6 +6631,10 @@ class DatabaseManager implements ConnectionResolverInterface { $this->extensions[$name] = $resolver; } + public function getConnections() + { + return $this->connections; + } public function __call($method, $parameters) { return call_user_func_array(array($this->connection(), $method), $parameters); @@ -6597,11 +6781,11 @@ class Store extends SymfonySession } public function flashInput(array $value) { - return $this->flash('_old_input', $value); + $this->flash('_old_input', $value); } public function reflash() { - $this->mergeNewFlashes($this->get('flash.old')); + $this->mergeNewFlashes($this->get('flash.old', array())); $this->put('flash.old', array()); } public function keep($keys = null) @@ -6627,7 +6811,7 @@ class Store extends SymfonySession } public function flush() { - return $this->clear(); + $this->clear(); } public function regenerate() { @@ -6640,7 +6824,6 @@ use Illuminate\Support\Manager; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; class SessionManager extends Manager { @@ -6755,6 +6938,7 @@ abstract class Manager public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; + return $this; } public function getDrivers() { @@ -6778,6 +6962,7 @@ class CookieJar protected $encrypter; protected $path = '/'; protected $domain = null; + protected $queued = array(); public function __construct(Request $request, Encrypter $encrypter) { $this->request = $request; @@ -6835,6 +7020,23 @@ class CookieJar { return $this->encrypter; } + public function queue() + { + if (head(func_get_args()) instanceof Cookie) { + $cookie = head(func_get_args()); + } else { + $cookie = call_user_func_array(array($this, 'make'), func_get_args()); + } + $this->queued[$cookie->getName()] = $cookie; + } + public function unqueue($name) + { + unset($this->queued[$name]); + } + public function getQueuedCookies() + { + return $this->queued; + } } namespace Illuminate\Encryption; @@ -6888,7 +7090,7 @@ class Encrypter } protected function validMac(array $payload) { - return $payload['mac'] == $this->hash($payload['iv'], $payload['value']); + return $payload['mac'] === $this->hash($payload['iv'], $payload['value']); } protected function hash($iv, $value) { @@ -6909,9 +7111,9 @@ class Encrypter $beforePad = strlen($value) - $pad; return substr($value, $beforePad) == str_repeat(substr($value, -1), $pad); } - protected function invalidPayload(array $data) + protected function invalidPayload($data) { - return !isset($data['iv']) or !isset($data['value']) or !isset($data['mac']); + return !is_array($data) or !isset($data['iv']) or !isset($data['value']) or !isset($data['mac']); } protected function getIvSize() { @@ -6952,13 +7154,14 @@ class Log extends Facade } namespace Illuminate\Log; +use Monolog\Logger; use Illuminate\Support\ServiceProvider; class LogServiceProvider extends ServiceProvider { protected $defer = true; public function register() { - $logger = new Writer(new \Monolog\Logger('log'), $this->app['events']); + $logger = new Writer(new Logger('log'), $this->app['events']); $this->app->instance('log', $logger); if (isset($this->app['log.setup'])) { call_user_func($this->app['log.setup'], $logger); @@ -7099,6 +7302,10 @@ class Logger implements LoggerInterface } return array_shift($this->handlers); } + public function getHandlers() + { + return $this->handlers; + } public function pushProcessor($callback) { if (!is_callable($callback)) { @@ -7113,18 +7320,19 @@ class Logger implements LoggerInterface } return array_shift($this->processors); } + public function getProcessors() + { + return $this->processors; + } public function addRecord($level, $message, array $context = array()) { if (!$this->handlers) { $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); } - if (!static::$timezone) { - static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); - } - $record = array('message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => static::getLevelName($level), 'channel' => $this->name, 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone), 'extra' => array()); + $levelName = static::getLevelName($level); $handlerKey = null; foreach ($this->handlers as $key => $handler) { - if ($handler->isHandling($record)) { + if ($handler->isHandling(array('level' => $level))) { $handlerKey = $key; break; } @@ -7132,6 +7340,10 @@ class Logger implements LoggerInterface if (null === $handlerKey) { return false; } + if (!static::$timezone) { + static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); + } + $record = array('message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone), 'extra' => array()); foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } @@ -7183,6 +7395,13 @@ class Logger implements LoggerInterface } return static::$levels[$level]; } + public static function toMonologLevel($level) + { + if (is_string($level) && defined(__CLASS__ . '::' . strtoupper($level))) { + return constant(__CLASS__ . '::' . strtoupper($level)); + } + return $level; + } public function isHandling($level) { $record = array('level' => $level); @@ -7276,7 +7495,7 @@ abstract class AbstractHandler implements HandlerInterface protected $processors = array(); public function __construct($level = Logger::DEBUG, $bubble = true) { - $this->level = $level; + $this->setLevel($level); $this->bubble = $bubble; } public function isHandling(array $record) @@ -7322,7 +7541,7 @@ abstract class AbstractHandler implements HandlerInterface } public function setLevel($level) { - $this->level = $level; + $this->level = Logger::toMonologLevel($level); return $this; } public function getLevel() @@ -7357,7 +7576,7 @@ abstract class AbstractProcessingHandler extends AbstractHandler { public function handle(array $record) { - if ($record['level'] < $this->level) { + if (!$this->isHandling($record)) { return false; } $record = $this->processRecord($record); @@ -7383,14 +7602,21 @@ class StreamHandler extends AbstractProcessingHandler { protected $stream; protected $url; - public function __construct($stream, $level = Logger::DEBUG, $bubble = true) + private $errorMessage; + protected $filePermission; + protected $useLocking; + public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { parent::__construct($level, $bubble); if (is_resource($stream)) { $this->stream = $stream; - } else { + } elseif (is_string($stream)) { $this->url = $stream; + } else { + throw new \InvalidArgumentException('A stream must either be a resource or a string.'); } + $this->filePermission = $filePermission; + $this->useLocking = $useLocking; } public function close() { @@ -7401,22 +7627,33 @@ class StreamHandler extends AbstractProcessingHandler } protected function write(array $record) { - if (null === $this->stream) { + if (!is_resource($this->stream)) { if (!$this->url) { throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); } - $errorMessage = null; - set_error_handler(function ($code, $msg) use(&$errorMessage) { - $errorMessage = preg_replace('{^fopen\\(.*?\\): }', '', $msg); - }); + $this->errorMessage = null; + set_error_handler(array($this, 'customErrorHandler')); $this->stream = fopen($this->url, 'a'); + if ($this->filePermission !== null) { + @chmod($this->url, $this->filePermission); + } restore_error_handler(); if (!is_resource($this->stream)) { $this->stream = null; - throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $errorMessage, $this->url)); + throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $this->url)); } } + if ($this->useLocking) { + flock($this->stream, LOCK_EX); + } fwrite($this->stream, (string) $record['formatted']); + if ($this->useLocking) { + flock($this->stream, LOCK_UN); + } + } + private function customErrorHandler($code, $msg) + { + $this->errorMessage = preg_replace('{^fopen\\(.*?\\): }', '', $msg); } } namespace Monolog\Handler; @@ -7428,12 +7665,16 @@ class RotatingFileHandler extends StreamHandler protected $maxFiles; protected $mustRotate; protected $nextRotation; - public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true) + protected $filenameFormat; + protected $dateFormat; + public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { $this->filename = $filename; $this->maxFiles = (int) $maxFiles; $this->nextRotation = new \DateTime('tomorrow'); - parent::__construct($this->getTimedFilename(), $level, $bubble); + $this->filenameFormat = '{filename}-{date}'; + $this->dateFormat = 'Y-m-d'; + parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); } public function close() { @@ -7442,6 +7683,13 @@ class RotatingFileHandler extends StreamHandler $this->rotate(); } } + public function setFilenameFormat($filenameFormat, $dateFormat) + { + $this->filenameFormat = $filenameFormat; + $this->dateFormat = $dateFormat; + $this->url = $this->getTimedFilename(); + $this->close(); + } protected function write(array $record) { if (null === $this->mustRotate) { @@ -7460,12 +7708,7 @@ class RotatingFileHandler extends StreamHandler if (0 === $this->maxFiles) { return; } - $fileInfo = pathinfo($this->filename); - $glob = $fileInfo['dirname'] . '/' . $fileInfo['filename'] . '-*'; - if (!empty($fileInfo['extension'])) { - $glob .= '.' . $fileInfo['extension']; - } - $logFiles = glob($glob); + $logFiles = glob($this->getGlobPattern()); if ($this->maxFiles >= count($logFiles)) { return; } @@ -7481,12 +7724,21 @@ class RotatingFileHandler extends StreamHandler protected function getTimedFilename() { $fileInfo = pathinfo($this->filename); - $timedFilename = $fileInfo['dirname'] . '/' . $fileInfo['filename'] . '-' . date('Y-m-d'); + $timedFilename = str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], date($this->dateFormat)), $fileInfo['dirname'] . '/' . $this->filenameFormat); if (!empty($fileInfo['extension'])) { $timedFilename .= '.' . $fileInfo['extension']; } return $timedFilename; } + protected function getGlobPattern() + { + $fileInfo = pathinfo($this->filename); + $glob = str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], '*'), $fileInfo['dirname'] . '/' . $this->filenameFormat); + if (!empty($fileInfo['extension'])) { + $glob .= '.' . $fileInfo['extension']; + } + return $glob; + } } namespace Monolog\Handler; @@ -7601,7 +7853,7 @@ class Handler { if (error_reporting() & $level) { $e = new ErrorException($message, $level, 0, $file, $line); - $this->handleException($e); + throw $e; } } public function handleException($exception) @@ -7672,8 +7924,11 @@ class Handler } protected function formatException(\Exception $e) { - $location = $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine(); - return 'Error in exception handler: ' . $location; + if ($this->debug) { + $location = $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine(); + return 'Error in exception handler: ' . $location; + } + return 'Error in exception handler.'; } public function error(Closure $callback) { @@ -7741,11 +7996,11 @@ class Route implements \Serializable } public function serialize() { - return serialize(array('path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods)); + return serialize(array('path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods, 'compiled' => $this->compiled)); } - public function unserialize($data) + public function unserialize($serialized) { - $data = unserialize($data); + $data = unserialize($serialized); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; @@ -7753,6 +8008,9 @@ class Route implements \Serializable $this->options = $data['options']; $this->schemes = $data['schemes']; $this->methods = $data['methods']; + if (isset($data['compiled'])) { + $this->compiled = $data['compiled']; + } } public function getPattern() { @@ -7797,6 +8055,10 @@ class Route implements \Serializable $this->compiled = null; return $this; } + public function hasScheme($scheme) + { + return in_array(strtolower($scheme), $this->schemes, true); + } public function getMethods() { return $this->methods; @@ -8161,6 +8423,7 @@ class FileViewFinder implements ViewFinderInterface { protected $files; protected $paths; + protected $views = array(); protected $hints = array(); protected $extensions = array('blade.php', 'php'); public function __construct(Filesystem $files, array $paths, array $extensions = null) @@ -8173,10 +8436,13 @@ class FileViewFinder implements ViewFinderInterface } public function find($name) { - if (strpos($name, '::') !== false) { - return $this->findNamedPathView($name); + if (isset($this->views[$name])) { + return $this->views[$name]; } - return $this->findInPaths($name, $this->paths); + if (strpos($name, '::') !== false) { + return $this->views[$name] = $this->findNamedPathView($name); + } + return $this->views[$name] = $this->findInPaths($name, $this->paths); } protected function findNamedPathView($name) { @@ -8499,6 +8765,10 @@ class Environment { $this->container = $container; } + public function shared($key, $default = null) + { + return array_get($this->shared, $key, $default); + } public function getShared() { return $this->shared; @@ -8521,8 +8791,8 @@ interface MessageProviderInterface namespace Illuminate\Support; use Countable; -use Illuminate\Support\Contracts\ArrayableInterface; use Illuminate\Support\Contracts\JsonableInterface; +use Illuminate\Support\Contracts\ArrayableInterface; use Illuminate\Support\Contracts\MessageProviderInterface; class MessageBag implements ArrayableInterface, Countable, JsonableInterface, MessageProviderInterface { @@ -8648,14 +8918,14 @@ class RequestContext private $parameters = array(); public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '') { - $this->baseUrl = $baseUrl; - $this->method = strtoupper($method); - $this->host = $host; - $this->scheme = strtolower($scheme); - $this->httpPort = $httpPort; - $this->httpsPort = $httpsPort; - $this->pathInfo = $path; - $this->queryString = $queryString; + $this->setBaseUrl($baseUrl); + $this->setMethod($method); + $this->setHost($host); + $this->setScheme($scheme); + $this->setHttpPort($httpPort); + $this->setHttpsPort($httpsPort); + $this->setPathInfo($path); + $this->setQueryString($queryString); } public function fromRequest(Request $request) { @@ -8666,7 +8936,7 @@ class RequestContext $this->setScheme($request->getScheme()); $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort()); $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort); - $this->setQueryString($request->server->get('QUERY_STRING')); + $this->setQueryString($request->server->get('QUERY_STRING', '')); } public function getBaseUrl() { @@ -8698,7 +8968,7 @@ class RequestContext } public function setHost($host) { - $this->host = $host; + $this->host = strtolower($host); } public function getScheme() { @@ -8714,7 +8984,7 @@ class RequestContext } public function setHttpPort($httpPort) { - $this->httpPort = $httpPort; + $this->httpPort = (int) $httpPort; } public function getHttpsPort() { @@ -8722,7 +8992,7 @@ class RequestContext } public function setHttpsPort($httpsPort) { - $this->httpsPort = $httpsPort; + $this->httpsPort = (int) $httpsPort; } public function getQueryString() { @@ -8730,7 +9000,7 @@ class RequestContext } public function setQueryString($queryString) { - $this->queryString = $queryString; + $this->queryString = (string) $queryString; } public function getParameters() { @@ -8874,18 +9144,14 @@ class RouteCompiler implements RouteCompilerInterface const SEPARATORS = '/,;.:-_~+*=@|'; public static function compile(Route $route) { - $staticPrefix = null; $hostVariables = array(); - $pathVariables = array(); $variables = array(); - $tokens = array(); - $regex = null; $hostRegex = null; $hostTokens = array(); if ('' !== ($host = $route->getHost())) { $result = self::compilePattern($route, $host, true); $hostVariables = $result['variables']; - $variables = array_merge($variables, $hostVariables); + $variables = $hostVariables; $hostTokens = $result['tokens']; $hostRegex = $result['regex']; } @@ -8953,7 +9219,7 @@ class RouteCompiler implements RouteCompilerInterface for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { $regexp .= self::computeRegexp($tokens, $i, $firstOptional); } - return array('staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', 'regex' => self::REGEX_DELIMITER . '^' . $regexp . '$' . self::REGEX_DELIMITER . 's', 'tokens' => array_reverse($tokens), 'variables' => $variables); + return array('staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', 'regex' => self::REGEX_DELIMITER . '^' . $regexp . '$' . self::REGEX_DELIMITER . 's' . ($isHost ? 'i' : ''), 'tokens' => array_reverse($tokens), 'variables' => $variables); } private static function findNextSeparator($pattern) { @@ -8987,7 +9253,7 @@ class RouteCompiler implements RouteCompilerInterface } namespace Symfony\Component\Routing; -class CompiledRoute +class CompiledRoute implements \Serializable { private $variables; private $tokens; @@ -9008,6 +9274,22 @@ class CompiledRoute $this->hostVariables = $hostVariables; $this->variables = $variables; } + public function serialize() + { + return serialize(array('vars' => $this->variables, 'path_prefix' => $this->staticPrefix, 'path_regex' => $this->regex, 'path_tokens' => $this->tokens, 'path_vars' => $this->pathVariables, 'host_regex' => $this->hostRegex, 'host_tokens' => $this->hostTokens, 'host_vars' => $this->hostVariables)); + } + public function unserialize($serialized) + { + $data = unserialize($serialized); + $this->variables = $data['vars']; + $this->staticPrefix = $data['path_prefix']; + $this->regex = $data['path_regex']; + $this->tokens = $data['path_tokens']; + $this->pathVariables = $data['path_vars']; + $this->hostRegex = $data['host_regex']; + $this->hostTokens = $data['host_tokens']; + $this->hostVariables = $data['host_vars']; + } public function getStaticPrefix() { return $this->staticPrefix; @@ -9082,7 +9364,7 @@ class View implements ArrayAccess, Renderable $env = $this->environment; $env->incrementRender(); $env->callComposer($this); - $contents = trim($this->getContents()); + $contents = $this->getContents(); $env->decrementRender(); if ($env->doneRendering()) { $env->flushSections(); @@ -9172,6 +9454,13 @@ class View implements ArrayAccess, Renderable { unset($this->data[$key]); } + public function __call($method, $parameters) + { + if (starts_with($method, 'with')) { + return $this->with(snake_case(substr($method, 4)), $parameters[0]); + } + throw new \BadMethodCallException("Method [{$method}] does not exist on view."); + } public function __toString() { return $this->render(); @@ -9202,7 +9491,7 @@ class PhpEngine implements EngineInterface } catch (\Exception $e) { $this->handleViewException($e); } - return ob_get_clean(); + return ltrim(ob_get_clean()); } protected function handleViewException($e) { @@ -9248,29 +9537,32 @@ class Response public function prepare(Request $request) { $headers = $this->headers; - if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) { + if ($this->isInformational() || $this->isEmpty()) { $this->setContent(null); - } - if (!$headers->has('Content-Type')) { - $format = $request->getRequestFormat(); - if (null !== $format && ($mimeType = $request->getMimeType($format))) { - $headers->set('Content-Type', $mimeType); - } - } - $charset = $this->charset ?: 'UTF-8'; - if (!$headers->has('Content-Type')) { - $headers->set('Content-Type', 'text/html; charset=' . $charset); - } elseif (0 === strpos($headers->get('Content-Type'), 'text/') && false === strpos($headers->get('Content-Type'), 'charset')) { - $headers->set('Content-Type', $headers->get('Content-Type') . '; charset=' . $charset); - } - if ($headers->has('Transfer-Encoding')) { + $headers->remove('Content-Type'); $headers->remove('Content-Length'); - } - if ($request->isMethod('HEAD')) { - $length = $headers->get('Content-Length'); - $this->setContent(null); - if ($length) { - $headers->set('Content-Length', $length); + } else { + if (!$headers->has('Content-Type')) { + $format = $request->getRequestFormat(); + if (null !== $format && ($mimeType = $request->getMimeType($format))) { + $headers->set('Content-Type', $mimeType); + } + } + $charset = $this->charset ?: 'UTF-8'; + if (!$headers->has('Content-Type')) { + $headers->set('Content-Type', 'text/html; charset=' . $charset); + } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { + $headers->set('Content-Type', $headers->get('Content-Type') . '; charset=' . $charset); + } + if ($headers->has('Transfer-Encoding')) { + $headers->remove('Content-Length'); + } + if ($request->isMethod('HEAD')) { + $length = $headers->get('Content-Length'); + $this->setContent(null); + if ($length) { + $headers->set('Content-Length', $length); + } } } if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { @@ -9316,7 +9608,7 @@ class Response while (($level = ob_get_level()) > 0 && $level !== $previous) { $previous = $level; if ($obStatus[$level - 1]) { - if (version_compare(PHP_VERSION, '5.4', '>=')) { + if (PHP_VERSION_ID >= 50400) { if (isset($obStatus[$level - 1]['flags']) && $obStatus[$level - 1]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE) { ob_end_flush(); } @@ -9470,7 +9762,6 @@ class Response if (null !== $this->getExpires()) { return $this->getExpires()->format('U') - $this->getDate()->format('U'); } - return null; } public function setMaxAge($value) { @@ -9488,7 +9779,6 @@ class Response if (null !== ($maxAge = $this->getMaxAge())) { return $maxAge - $this->getAge(); } - return null; } public function setTtl($seconds) { @@ -9579,10 +9869,14 @@ class Response } public function getVary() { - if (!($vary = $this->headers->get('Vary'))) { + if (!($vary = $this->headers->get('Vary', null, false))) { return array(); } - return is_array($vary) ? $vary : preg_split('/[\\s,]+/', $vary); + $ret = array(); + foreach ($vary as $item) { + $ret = array_merge($ret, preg_split('/[\\s,]+/', $item)); + } + return $ret; } public function setVary($headers, $replace = true) { @@ -9594,12 +9888,14 @@ class Response if (!$request->isMethodSafe()) { return false; } - $lastModified = $request->headers->get('If-Modified-Since'); $notModified = false; + $lastModified = $this->headers->get('Last-Modified'); + $modifiedSince = $request->headers->get('If-Modified-Since'); if ($etags = $request->getEtags()) { - $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified); - } elseif ($lastModified) { - $notModified = $lastModified == $this->headers->get('Last-Modified'); + $notModified = in_array($this->getEtag(), $etags) || in_array('*', $etags); + } + if ($modifiedSince && $lastModified) { + $notModified = strtotime($modifiedSince) >= strtotime($lastModified) && (!$etags || $notModified); } if ($notModified) { $this->setNotModified(); @@ -9648,12 +9944,12 @@ class Response } public function isEmpty() { - return in_array($this->statusCode, array(201, 204, 304)); + return in_array($this->statusCode, array(204, 304)); } protected function ensureIEOverSSLCompatibility(Request $request) { if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { - if (intval(preg_replace('/(MSIE )(.*?);/', '$2', $match[0])) < 9) { + if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { $this->headers->remove('Cache-Control'); } } @@ -9661,6 +9957,7 @@ class Response } namespace Illuminate\Http; +use ArrayObject; use Symfony\Component\HttpFoundation\Cookie; use Illuminate\Support\Contracts\JsonableInterface; use Illuminate\Support\Contracts\RenderableInterface; @@ -9697,7 +9994,7 @@ class Response extends \Symfony\Component\HttpFoundation\Response } protected function shouldBeJson($content) { - return $content instanceof JsonableInterface or is_array($content); + return $content instanceof JsonableInterface or $content instanceof ArrayObject or is_array($content); } public function getOriginalContent() { @@ -10143,7 +10440,7 @@ class PrettyPageHandler extends Handler return Handler::DONE; } if (!($resources = $this->getResourcesPath())) { - $resources = 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\filp\\whoops\\src\\Whoops\\Handler' . '/../Resources'; + $resources = '/vagrant/vendor/filp/whoops/src/Whoops/Handler' . '/../Resources'; } $templateFile = "{$resources}/pretty-template.php"; $cssFile = "{$resources}/pretty-page.css"; diff --git a/bootstrap/start.php b/bootstrap/start.php index 8b882aef..f48bd6bb 100644 --- a/bootstrap/start.php +++ b/bootstrap/start.php @@ -27,7 +27,7 @@ $app->redirectIfTrailingSlash(); */ $env = $app->detectEnvironment([ - 'local' => ['dev.spa.pony.fm'] + 'local' => ['pony.fm.local', 'api.pony.fm.local', 'homestead'] ]); /* diff --git a/composer.json b/composer.json index 6c00c759..de751d80 100644 --- a/composer.json +++ b/composer.json @@ -30,5 +30,5 @@ "config": { "preferred-install": "dist" }, - "minimum-stability": "dev" + "minimum-stability": "stable" } diff --git a/composer.phar b/composer.phar deleted file mode 100644 index c1b01930..00000000 Binary files a/composer.phar and /dev/null differ diff --git a/logs/.gitignore b/logs/.gitignore new file mode 100644 index 00000000..c96a04f0 --- /dev/null +++ b/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/pony.fm.iml b/pony.fm.iml new file mode 100644 index 00000000..80cc7391 --- /dev/null +++ b/pony.fm.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/public/styles/account-content.less b/public/styles/account-content.less index 1ae43147..80e07e72 100644 --- a/public/styles/account-content.less +++ b/public/styles/account-content.less @@ -1,5 +1,5 @@ -@import-once 'base/bootstrap/bootstrap'; -@import-once 'mixins'; +@import 'base/bootstrap/bootstrap'; +@import 'mixins'; ul.playlists { overflow-y: auto; diff --git a/public/styles/animations.less b/public/styles/animations.less index 448c768e..5300c089 100644 --- a/public/styles/animations.less +++ b/public/styles/animations.less @@ -1,5 +1,5 @@ -@import-once 'base/bootstrap/bootstrap'; -@import-once 'mixins'; +@import 'base/bootstrap/bootstrap'; +@import 'mixins'; .fade-hide, .fade-show { .transition(all cubic-bezier(0.250, 0.460, 0.450, 0.940) 350ms); diff --git a/public/styles/base/bootstrap/navbar.less b/public/styles/base/bootstrap/navbar.less index 93d09bca..e8548942 100644 --- a/public/styles/base/bootstrap/navbar.less +++ b/public/styles/base/bootstrap/navbar.less @@ -196,7 +196,7 @@ .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { - #grid > .core > .span(@gridColumns); + width: (@gridColumnWidth * @gridColumns) + (@gridGutterWidth * (@gridColumns - 1)); } // Fixed to top diff --git a/public/styles/body.less b/public/styles/body.less index e1c1df6a..50814aed 100644 --- a/public/styles/body.less +++ b/public/styles/body.less @@ -1,5 +1,5 @@ -@import-once 'variables'; -@import-once 'base/bootstrap/bootstrap'; +@import 'variables'; +@import 'base/bootstrap/bootstrap'; a { color: #C2889C; diff --git a/public/styles/components.less b/public/styles/components.less index ea0edba6..0ecb10c0 100644 --- a/public/styles/components.less +++ b/public/styles/components.less @@ -1,6 +1,6 @@ -@import-once 'base/bootstrap/bootstrap'; -@import-once 'mixins'; -@import-once 'variables'; +@import 'base/bootstrap/bootstrap'; +@import 'mixins'; +@import 'variables'; .stretch-to-bottom { overflow-y: auto; diff --git a/public/styles/content.less b/public/styles/content.less index b48b8d67..9eec5f1e 100644 --- a/public/styles/content.less +++ b/public/styles/content.less @@ -1,6 +1,6 @@ -@import-once 'base/bootstrap/bootstrap'; -@import-once 'mixins'; -@import-once 'variables'; +@import 'base/bootstrap/bootstrap'; +@import 'mixins'; +@import 'variables'; @media (max-width: 1300px) and (min-width: 720px) { html { diff --git a/public/styles/dashboard.less b/public/styles/dashboard.less index fb07e54c..d4950057 100644 --- a/public/styles/dashboard.less +++ b/public/styles/dashboard.less @@ -1,4 +1,4 @@ -@import-once "base/bootstrap/bootstrap"; +@import "base/bootstrap/bootstrap"; .dashboard { h1 { diff --git a/public/styles/forms.less b/public/styles/forms.less index b8fba33d..4775d55a 100644 --- a/public/styles/forms.less +++ b/public/styles/forms.less @@ -1,4 +1,4 @@ -@import-once "base/bootstrap/bootstrap"; +@import "base/bootstrap/bootstrap"; .form-row { margin-bottom: 10px; diff --git a/public/styles/layout.less b/public/styles/layout.less index b28cfd52..f9306cff 100644 --- a/public/styles/layout.less +++ b/public/styles/layout.less @@ -1,6 +1,6 @@ -@import-once 'base/bootstrap/bootstrap'; -@import-once 'mixins'; -@import-once 'variables'; +@import 'base/bootstrap/bootstrap'; +@import 'mixins'; +@import 'variables'; html, body { } diff --git a/public/styles/player.less b/public/styles/player.less index 566776e4..8f4134a7 100644 --- a/public/styles/player.less +++ b/public/styles/player.less @@ -1,5 +1,5 @@ -@import-once 'variables'; -@import-once 'mixins'; +@import 'variables'; +@import 'mixins'; body.is-logged { .track-player { diff --git a/public/styles/uploader.less b/public/styles/uploader.less index b880795b..f847ba65 100644 --- a/public/styles/uploader.less +++ b/public/styles/uploader.less @@ -1,4 +1,4 @@ -@import-once 'variables'; +@import 'variables'; .uploader { h1 { diff --git a/vagrant/config/app.php b/vagrant/config/app.php new file mode 100644 index 00000000..4e7f61fd --- /dev/null +++ b/vagrant/config/app.php @@ -0,0 +1,14 @@ + true, + 'uglify-js' => 'uglifyjs', + 'uglify-css' => 'uglifycss', + 'coffee' => 'coffee', + 'debug' => true, + 'url' => 'pony.fm.local', + 'files_directory' => '/vagrant-files/', + 'node' => null, + 'node_paths' => ['node'], + 'secure' => false, +); \ No newline at end of file diff --git a/vagrant/config/cache.php b/vagrant/config/cache.php new file mode 100644 index 00000000..90116a11 --- /dev/null +++ b/vagrant/config/cache.php @@ -0,0 +1,5 @@ + 'database', +); diff --git a/vagrant/config/database.php b/vagrant/config/database.php new file mode 100644 index 00000000..064f000b --- /dev/null +++ b/vagrant/config/database.php @@ -0,0 +1,85 @@ + 'mysql', + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => array( + + 'mysql' => array( + 'driver' => 'mysql', + 'host' => 'localhost', + 'database' => 'homestead', + 'username' => 'homestead', + 'password' => 'secret', + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', + 'prefix' => '', + ), + + ), + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk have not actually be run in the databases. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer set of commands than a typical key-value systems + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => array( + + 'cluster' => true, + + 'default' => array( + 'host' => '127.0.0.1', + 'port' => 6379, + 'database' => 0, + ), + + ), + +); \ No newline at end of file diff --git a/vagrant/config/poniverse.php b/vagrant/config/poniverse.php new file mode 100644 index 00000000..b5b019c1 --- /dev/null +++ b/vagrant/config/poniverse.php @@ -0,0 +1,12 @@ + 1, + 'urls' => [ + 'api' => 'http://api.poniverse.dev:83/v1/', + 'register' => 'http://poniverse.dev:83/register?site=ponyfm', + 'auth' => 'http://poniverse.dev:83/login/authorize', + 'token' => 'http://api.poniverse.dev:83/v1/oauth2/token' + ], + 'client_id' => 'spa-ponyfm', + 'secret' => 'mwRW6lfm19G9TaN60J0oMq2kapzU83n4' +]; \ No newline at end of file diff --git a/vagrant/config/session.php b/vagrant/config/session.php new file mode 100644 index 00000000..e11e98cd --- /dev/null +++ b/vagrant/config/session.php @@ -0,0 +1,125 @@ + 'native', + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle for it is expired. If you want them + | to immediately expire when the browser closes, set it to zero. + | + */ + + 'lifetime' => 120, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path().'/sessions', + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the database + | connection that should be used to manage your sessions. This should + | correspond to a connection in your "database" configuration file. + | + */ + + 'connection' => null, + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => array(2, 100), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => 'laravel_session', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => null, + +); diff --git a/vagrant/copy-and-restart-configs.sh b/vagrant/copy-and-restart-configs.sh new file mode 100644 index 00000000..cb81e720 --- /dev/null +++ b/vagrant/copy-and-restart-configs.sh @@ -0,0 +1,13 @@ +sudo cp /vagrant/vagrant/pony.fm.nginx.config /etc/nginx/nginx.conf +sudo cp /vagrant/vagrant/pony.fm.nginx.site.config /etc/nginx/sites-enabled/pony.fm + +sudo cp /vagrant/vagrant/pony.fm.mysql.config /etc/mysql/my.cnf + +sudo cp /vagrant/vagrant/pony.fm.redis.config /etc/redis/redis.conf + +sudo service nginx restart +sudo service php5-fpm restart + +sudo service mysql restart + +# todo: figure out how to restart redis \ No newline at end of file diff --git a/vagrant/elevator.exe b/vagrant/elevator.exe new file mode 100644 index 00000000..39f997f5 Binary files /dev/null and b/vagrant/elevator.exe differ diff --git a/vagrant/install.sh b/vagrant/install.sh new file mode 100644 index 00000000..41626aaf --- /dev/null +++ b/vagrant/install.sh @@ -0,0 +1,19 @@ +mkdir /vagrant/logs +/vagrant/vagrant/copy-and-restart-configs.sh + +cd /vagrant + +/usr/local/bin/composer self-update +composer install + +sudo npm install -g bower +sudo npm install -g coffee-script +sudo npm install -g less + +bower install --allow-root + +cp -r /vagrant/vagrant/config/* "/vagrant/app/config/local" + +php artisan migrate +php artisan migrate:refresh +php artisan db:seed \ No newline at end of file diff --git a/vagrant/pony.fm.mysql.config b/vagrant/pony.fm.mysql.config new file mode 100644 index 00000000..224a03e3 --- /dev/null +++ b/vagrant/pony.fm.mysql.config @@ -0,0 +1,127 @@ +# +# The MySQL database server configuration file. +# +# You can copy this to one of: +# - "/etc/mysql/my.cnf" to set global options, +# - "~/.my.cnf" to set user-specific options. +# +# One can use all long options that the program supports. +# Run program with --help to get a list of available options and with +# --print-defaults to see which it would actually understand and use. +# +# For explanations see +# http://dev.mysql.com/doc/mysql/en/server-system-variables.html + +# This will be passed to all mysql clients +# It has been reported that passwords should be enclosed with ticks/quotes +# escpecially if they contain "#" chars... +# Remember to edit /etc/mysql/debian.cnf when changing the socket location. +[client] +port = 3306 +socket = /var/run/mysqld/mysqld.sock + +# Here is entries for some specific programs +# The following values assume you have at least 32M ram + +# This was formally known as [safe_mysqld]. Both versions are currently parsed. +[mysqld_safe] +socket = /var/run/mysqld/mysqld.sock +nice = 0 + +[mysqld] +# +# * Basic Settings +# +user = mysql +pid-file = /var/run/mysqld/mysqld.pid +socket = /var/run/mysqld/mysqld.sock +port = 3306 +basedir = /usr +datadir = /var/lib/mysql +tmpdir = /tmp +lc-messages-dir = /usr/share/mysql +skip-external-locking +# +# Instead of skip-networking the default is now to listen only on +# localhost which is more compatible and is not less secure. +bind-address = 0.0.0.0 +# +# * Fine Tuning +# +key_buffer = 16M +max_allowed_packet = 16M +thread_stack = 192K +thread_cache_size = 8 +# This replaces the startup script and checks MyISAM tables if needed +# the first time they are touched +myisam-recover = BACKUP +#max_connections = 100 +#table_cache = 64 +#thread_concurrency = 10 +# +# * Query Cache Configuration +# +query_cache_limit = 1M +query_cache_size = 16M +# +# * Logging and Replication +# +# Both location gets rotated by the cronjob. +# Be aware that this log type is a performance killer. +# As of 5.1 you can enable the log at runtime! +#general_log_file = /var/log/mysql/mysql.log +#general_log = 1 +# +# Error log - should be very few entries. +# +log_error = /vagrant/logs/mysql-error.log +# +# Here you can see queries with especially long duration +#log_slow_queries = /var/log/mysql/mysql-slow.log +#long_query_time = 2 +#log-queries-not-using-indexes +# +# The following can be used as easy to replay backup logs or for replication. +# note: if you are setting up a replication slave, see README.Debian about +# other settings you may need to change. +#server-id = 1 +#log_bin = /var/log/mysql/mysql-bin.log +expire_logs_days = 10 +max_binlog_size = 100M +#binlog_do_db = include_database_name +#binlog_ignore_db = include_database_name +# +# * InnoDB +# +# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. +# Read the manual for more InnoDB related options. There are many! +# +# * Security Features +# +# Read the manual, too, if you want chroot! +# chroot = /var/lib/mysql/ +# +# For generating SSL certificates I recommend the OpenSSL GUI "tinyca". +# +# ssl-ca=/etc/mysql/cacert.pem +# ssl-cert=/etc/mysql/server-cert.pem +# ssl-key=/etc/mysql/server-key.pem + + + +[mysqldump] +quick +quote-names +max_allowed_packet = 16M + +[mysql] +#no-auto-rehash # faster start of mysql but no tab completition + +[isamchk] +key_buffer = 16M + +# +# * IMPORTANT: Additional settings that can override those from this file! +# The files must end with '.cnf', otherwise they'll be ignored. +# +!includedir /etc/mysql/conf.d/ diff --git a/vagrant/pony.fm.nginx.config b/vagrant/pony.fm.nginx.config new file mode 100644 index 00000000..39218dcb --- /dev/null +++ b/vagrant/pony.fm.nginx.config @@ -0,0 +1,85 @@ +user vagrant; +worker_processes 4; +pid /run/nginx.pid; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ## + # Gzip Settings + ## + + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} + + +#mail { +# # See sample authentication script at: +# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript +# +# # auth_http localhost/auth.php; +# # pop3_capabilities "TOP" "USER"; +# # imap_capabilities "IMAP4rev1" "UIDPLUS"; +# +# server { +# listen localhost:110; +# protocol pop3; +# proxy on; +# } +# +# server { +# listen localhost:143; +# protocol imap; +# proxy on; +# } +#} diff --git a/vagrant/pony.fm.nginx.site.config b/vagrant/pony.fm.nginx.site.config new file mode 100644 index 00000000..8654d7e0 --- /dev/null +++ b/vagrant/pony.fm.nginx.site.config @@ -0,0 +1,46 @@ +server { + listen 80; + + gzip on; + gzip_comp_level 4; + gzip_min_length 1280; + gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/bmp application/json; + gzip_vary on; + + server_name pony.fm.local api.pony.fm.local; + access_log /vagrant/logs/nginx-access.log; + error_log /vagrant/logs/nginx-error.log; + root /vagrant/public; + + location / { + index index.html index.php; + location ~* \.(?:ttf|ttc|otf|eot|woff|font.css)$ { + add_header "Access-Control-Allow-Origin" "*"; + } + + if (!-e $request_filename) { + rewrite ^/(.*)$ /index.php?/$1 last; + break; + } + } + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/var/run/php5-fpm.sock; + fastcgi_index index.php; + include fastcgi_params; + } + + expires off; + + rewrite ^/(.*\.(?:coffee))$ /asset.php?type=coffee&file=/$1 break; + rewrite ^/(.*\.(?:less))$ /asset.php?type=less&file=/$1 break; + + error_page 404 /index.php; + error_page 403 /403.html; + + location /vagrant-files { + internal; + alias /vagrant-files/; + } +} \ No newline at end of file diff --git a/vagrant/pony.fm.redis.config b/vagrant/pony.fm.redis.config new file mode 100644 index 00000000..d5f743e1 --- /dev/null +++ b/vagrant/pony.fm.redis.config @@ -0,0 +1,696 @@ +# Redis configuration file example + +# Note on units: when memory size is needed, it is possible to specify +# it in the usual form of 1k 5GB 4M and so forth: +# +# 1k => 1000 bytes +# 1kb => 1024 bytes +# 1m => 1000000 bytes +# 1mb => 1024*1024 bytes +# 1g => 1000000000 bytes +# 1gb => 1024*1024*1024 bytes +# +# units are case insensitive so 1GB 1Gb 1gB are all the same. + +# By default Redis does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +daemonize yes + +# When running daemonized, Redis writes a pid file in /var/run/redis.pid by +# default. You can specify a custom pid file location here. +pidfile /var/run/redis/redis.pid + +# Accept connections on the specified port, default is 6379. +# If port 0 is specified Redis will not listen on a TCP socket. +port 6379 + +# By default Redis listens for connections from all the network interfaces +# available on the server. It is possible to listen to just one or multiple +# interfaces using the "bind" configuration directive, followed by one or +# more IP addresses. +# +# Examples: +# +# bind 192.168.1.100 10.0.0.1 +# bind 127.0.0.1 + +# Specify the path for the unix socket that will be used to listen for +# incoming connections. There is no default, so Redis will not listen +# on a unix socket when not specified. +# +# unixsocket /tmp/redis.sock +# unixsocketperm 755 + +# Close the connection after a client is idle for N seconds (0 to disable) +timeout 0 + +# TCP keepalive. +# +# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence +# of communication. This is useful for two reasons: +# +# 1) Detect dead peers. +# 2) Take the connection alive from the point of view of network +# equipment in the middle. +# +# On Linux, the specified value (in seconds) is the period used to send ACKs. +# Note that to close the connection the double of the time is needed. +# On other kernels the period depends on the kernel configuration. +# +# A reasonable value for this option is 60 seconds. +tcp-keepalive 0 + +# Specify the server verbosity level. +# This can be one of: +# debug (a lot of information, useful for development/testing) +# verbose (many rarely useful info, but not a mess like the debug level) +# notice (moderately verbose, what you want in production probably) +# warning (only very important / critical messages are logged) +loglevel notice + +# Specify the log file name. Also the emptry string can be used to force +# Redis to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile /dev/null + +# To enable logging to the system logger, just set 'syslog-enabled' to yes, +# and optionally update the other syslog parameters to suit your needs. +syslog-enabled yes + +# Specify the syslog identity. +# syslog-ident redis + +# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. +# syslog-facility local0 + +# Set the number of databases. The default database is DB 0, you can select +# a different one on a per-connection basis using SELECT where +# dbid is a number between 0 and 'databases'-1 +databases 16 + +################################ SNAPSHOTTING ################################# +# +# Save the DB on disk: +# +# save +# +# Will save the DB if both the given number of seconds and the given +# number of write operations against the DB occurred. +# +# In the example below the behaviour will be to save: +# after 900 sec (15 min) if at least 1 key changed +# after 300 sec (5 min) if at least 10 keys changed +# after 60 sec if at least 10000 keys changed +# +# Note: you can disable saving at all commenting all the "save" lines. +# +# It is also possible to remove all the previously configured save +# points by adding a save directive with a single empty string argument +# like in the following example: +# +# save "" + +save 900 1 +save 300 10 +save 60 10000 + +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in an hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# distater will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usually even if there are problems with disk, +# permissions, and so forth. +stop-writes-on-bgsave-error yes + +# Compress string objects using LZF when dump .rdb databases? +# For default that's set to 'yes' as it's almost always a win. +# If you want to save some CPU in the saving child set it to 'no' but +# the dataset will likely be bigger if you have compressible values or keys. +rdbcompression yes + +# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum yes + +# The filename where to dump the DB +dbfilename redis.rdb + +# The working directory. +# +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# The Append Only File will also be created inside this directory. +# +# Note that you must specify a directory here, not a file name. +dir /var/lib/redis/ + +################################# REPLICATION ################################# + +# Master-Slave replication. Use slaveof to make a Redis instance a copy of +# another Redis server. Note that the configuration is local to the slave +# so for example it is possible to configure the slave to save the DB with a +# different interval, or to listen to another port, and so on. +# +# slaveof + +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the slave to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the slave request. +# +# masterauth + +# When a slave loses its connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of date data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale-data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +slave-serve-stale-data yes + +# You can configure a slave instance to accept writes or not. Writing against +# a slave instance may be useful to store some ephemeral data (because data +# written on a slave will be easily deleted after resync with the master) but +# may also cause problems if clients are writing to it because of a +# misconfiguration. +# +# Since Redis 2.6 by default slaves are read-only. +# +# Note: read only slaves are not designed to be exposed to untrusted clients +# on the internet. It's just a protection layer against misuse of the instance. +# Still a read only slave exports by default all the administrative commands +# such as CONFIG, DEBUG, and so forth. To a limited extend you can improve +# security of read only slaves using 'rename-command' to shadow all the +# administrative / dangerous commands. +slave-read-only yes + +# Slaves send PINGs to server in a predefined interval. It's possible to change +# this interval with the repl_ping_slave_period option. The default value is 10 +# seconds. +# +# repl-ping-slave-period 10 + +# The following option sets the replication timeout for: +# +# 1) Bulk transfer I/O during SYNC, from the point of view of slave. +# 2) Master timeout from the point of view of slaves (data, pings). +# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). +# +# It is important to make sure that this value is greater than the value +# specified for repl-ping-slave-period otherwise a timeout will be detected +# every time there is low traffic between the master and the slave. +# +# repl-timeout 60 + +# Disable TCP_NODELAY on the slave socket after SYNC? +# +# If you select "yes" Redis will use a smaller number of TCP packets and +# less bandwidth to send data to slaves. But this can add a delay for +# the data to appear on the slave side, up to 40 milliseconds with +# Linux kernels using a default configuration. +# +# If you select "no" the delay for data to appear on the slave side will +# be reduced but more bandwidth will be used for replication. +# +# By default we optimize for low latency, but in very high traffic conditions +# or when the master and slaves are many hops away, turning this to "yes" may +# be a good idea. +repl-disable-tcp-nodelay no + +# Set the replication backlog size. The backlog is a buffer that accumulates +# slave data when slaves are disconnected for some time, so that when a slave +# wants to reconnect again, often a full resync is not needed, but a partial +# resync is enough, just passing the portion of data the slave missed while +# disconnected. +# +# The biggest the replication backlog, the longer the time the slave can be +# disconnected and later be able to perform a partial resynchronization. +# +# The backlog is only allocated once there is at least a slave connected. +# +# repl-backlog-size 1mb + +# After a master has no longer connected slaves for some time, the backlog +# will be freed. The following option configures the amount of seconds that +# need to elapse, starting from the time the last slave disconnected, for +# the backlog buffer to be freed. +# +# A value of 0 means to never release the backlog. +# +# repl-backlog-ttl 3600 + +# The slave priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a slave to promote into a +# master if the master is no longer working correctly. +# +# A slave with a low priority number is considered better for promotion, so +# for instance if there are three slaves with priority 10, 100, 25 Sentinel will +# pick the one wtih priority 10, that is the lowest. +# +# However a special priority of 0 marks the slave as not able to perform the +# role of master, so a slave with priority of 0 will never be selected by +# Redis Sentinel for promotion. +# +# By default the priority is 100. +slave-priority 100 + +# It is possible for a master to stop accepting writes if there are less than +# N slaves connected, having a lag less or equal than M seconds. +# +# The N slaves need to be in "online" state. +# +# The lag in seconds, that must be <= the specified value, is calculated from +# the last ping received from the slave, that is usually sent every second. +# +# This option does not GUARANTEES that N replicas will accept the write, but +# will limit the window of exposure for lost writes in case not enough slaves +# are available, to the specified number of seconds. +# +# For example to require at least 3 slaves with a lag <= 10 seconds use: +# +# min-slaves-to-write 3 +# min-slaves-max-lag 10 +# +# Setting one or the other to 0 disables the feature. +# +# By default min-slaves-to-write is set to 0 (feature disabled) and +# min-slaves-max-lag is set to 10. + +################################## SECURITY ################################### + +# Require clients to issue AUTH before processing any other +# commands. This might be useful in environments in which you do not trust +# others with access to the host running redis-server. +# +# This should stay commented out for backward compatibility and because most +# people do not need auth (e.g. they run their own servers). +# +# Warning: since Redis is pretty fast an outside user can try up to +# 150k passwords per second against a good box. This means that you should +# use a very strong password otherwise it will be very easy to break. +# +# requirepass foobared + +# Command renaming. +# +# It is possible to change the name of dangerous commands in a shared +# environment. For instance the CONFIG command may be renamed into something +# hard to guess so that it will still be available for internal-use tools +# but not available for general clients. +# +# Example: +# +# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 +# +# It is also possible to completely kill a command by renaming it into +# an empty string: +# +# rename-command CONFIG "" +# +# Please note that changing the name of commands that are logged into the +# AOF file or transmitted to slaves may cause problems. + +################################### LIMITS #################################### + +# Set the max number of connected clients at the same time. By default +# this limit is set to 10000 clients, however if the Redis server is not +# able to configure the process file limit to allow for the specified limit +# the max number of allowed clients is set to the current file limit +# minus 32 (as Redis reserves a few file descriptors for internal uses). +# +# Once the limit is reached Redis will close all the new connections sending +# an error 'max number of clients reached'. +# +# maxclients 10000 + +# Don't use more memory than the specified amount of bytes. +# When the memory limit is reached Redis will try to remove keys +# accordingly to the eviction policy selected (see maxmemmory-policy). +# +# If Redis can't remove keys according to the policy, or if the policy is +# set to 'noeviction', Redis will start to reply with errors to commands +# that would use more memory, like SET, LPUSH, and so on, and will continue +# to reply to read-only commands like GET. +# +# This option is usually useful when using Redis as an LRU cache, or to set +# an hard memory limit for an instance (using the 'noeviction' policy). +# +# WARNING: If you have slaves attached to an instance with maxmemory on, +# the size of the output buffers needed to feed the slaves are subtracted +# from the used memory count, so that network problems / resyncs will +# not trigger a loop where keys are evicted, and in turn the output +# buffer of slaves is full with DELs of keys evicted triggering the deletion +# of more keys, and so forth until the database is completely emptied. +# +# In short... if you have slaves attached it is suggested that you set a lower +# limit for maxmemory so that there is some free RAM on the system for slave +# output buffers (but this is not needed if the policy is 'noeviction'). +# +# maxmemory + +# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory +# is reached. You can select among five behaviors: +# +# volatile-lru -> remove the key with an expire set using an LRU algorithm +# allkeys-lru -> remove any key accordingly to the LRU algorithm +# volatile-random -> remove a random key with an expire set +# allkeys-random -> remove a random key, any key +# volatile-ttl -> remove the key with the nearest expire time (minor TTL) +# noeviction -> don't expire at all, just return an error on write operations +# +# Note: with any of the above policies, Redis will return an error on write +# operations, when there are not suitable keys for eviction. +# +# At the date of writing this commands are: set setnx setex append +# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd +# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby +# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby +# getset mset msetnx exec sort +# +# The default is: +# +# maxmemory-policy volatile-lru + +# LRU and minimal TTL algorithms are not precise algorithms but approximated +# algorithms (in order to save memory), so you can select as well the sample +# size to check. For instance for default Redis will check three keys and +# pick the one that was used less recently, you can change the sample size +# using the following configuration directive. +# +# maxmemory-samples 3 + +############################## APPEND ONLY MODE ############################### + +# By default Redis asynchronously dumps the dataset on disk. This mode is +# good enough in many applications, but an issue with the Redis process or +# a power outage may result into a few minutes of writes lost (depending on +# the configured save points). +# +# The Append Only File is an alternative persistence mode that provides +# much better durability. For instance using the default data fsync policy +# (see later in the config file) Redis can lose just one second of writes in a +# dramatic event like a server power outage, or a single write if something +# wrong with the Redis process itself happens, but the operating system is +# still running correctly. +# +# AOF and RDB persistence can be enabled at the same time without problems. +# If the AOF is enabled on startup Redis will load the AOF, that is the file +# with the better durability guarantees. +# +# Please check http://redis.io/topics/persistence for more information. + +appendonly no + +# The name of the append only file (default: "appendonly.aof") +# appendfilename appendonly.aof + +# The fsync() call tells the Operating System to actually write data on disk +# instead to wait for more data in the output buffer. Some OS will really flush +# data on disk, some other OS will just try to do it ASAP. +# +# Redis supports three different modes: +# +# no: don't fsync, just let the OS flush the data when it wants. Faster. +# always: fsync after every write to the append only log . Slow, Safest. +# everysec: fsync only one time every second. Compromise. +# +# The default is "everysec", as that's usually the right compromise between +# speed and data safety. It's up to you to understand if you can relax this to +# "no" that will let the operating system flush the output buffer when +# it wants, for better performances (but if you can live with the idea of +# some data loss consider the default persistence mode that's snapshotting), +# or on the contrary, use "always" that's very slow but a bit safer than +# everysec. +# +# More details please check the following article: +# http://antirez.com/post/redis-persistence-demystified.html +# +# If unsure, use "everysec". + +# appendfsync always +appendfsync everysec +# appendfsync no + +# When the AOF fsync policy is set to always or everysec, and a background +# saving process (a background save or AOF log background rewriting) is +# performing a lot of I/O against the disk, in some Linux configurations +# Redis may block too long on the fsync() call. Note that there is no fix for +# this currently, as even performing fsync in a different thread will block +# our synchronous write(2) call. +# +# In order to mitigate this problem it's possible to use the following option +# that will prevent fsync() from being called in the main process while a +# BGSAVE or BGREWRITEAOF is in progress. +# +# This means that while another child is saving, the durability of Redis is +# the same as "appendfsync none". In practical terms, this means that it is +# possible to lose up to 30 seconds of log in the worst scenario (with the +# default Linux settings). +# +# If you have latency problems turn this to "yes". Otherwise leave it as +# "no" that is the safest pick from the point of view of durability. +no-appendfsync-on-rewrite no + +# Automatic rewrite of the append only file. +# Redis is able to automatically rewrite the log file implicitly calling +# BGREWRITEAOF when the AOF log size grows by the specified percentage. +# +# This is how it works: Redis remembers the size of the AOF file after the +# latest rewrite (if no rewrite has happened since the restart, the size of +# the AOF at startup is used). +# +# This base size is compared to the current size. If the current size is +# bigger than the specified percentage, the rewrite is triggered. Also +# you need to specify a minimal size for the AOF file to be rewritten, this +# is useful to avoid rewriting the AOF file even if the percentage increase +# is reached but it is still pretty small. +# +# Specify a percentage of zero in order to disable the automatic AOF +# rewrite feature. + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +################################ LUA SCRIPTING ############################### + +# Max execution time of a Lua script in milliseconds. +# +# If the maximum execution time is reached Redis will log that a script is +# still in execution after the maximum allowed time and will start to +# reply to queries with an error. +# +# When a long running script exceed the maximum execution time only the +# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be +# used to stop a script that did not yet called write commands. The second +# is the only way to shut down the server in the case a write commands was +# already issue by the script but the user don't want to wait for the natural +# termination of the script. +# +# Set it to 0 or a negative value for unlimited execution without warnings. +lua-time-limit 5000 + +################################## SLOW LOG ################################### + +# The Redis Slow Log is a system to log queries that exceeded a specified +# execution time. The execution time does not include the I/O operations +# like talking with the client, sending the reply and so forth, +# but just the time needed to actually execute the command (this is the only +# stage of command execution where the thread is blocked and can not serve +# other requests in the meantime). +# +# You can configure the slow log with two parameters: one tells Redis +# what is the execution time, in microseconds, to exceed in order for the +# command to get logged, and the other parameter is the length of the +# slow log. When a new command is logged the oldest one is removed from the +# queue of logged commands. + +# The following time is expressed in microseconds, so 1000000 is equivalent +# to one second. Note that a negative number disables the slow log, while +# a value of zero forces the logging of every command. +slowlog-log-slower-than 10000 + +# There is no limit to this length. Just be aware that it will consume memory. +# You can reclaim memory used by the slow log with SLOWLOG RESET. +slowlog-max-len 128 + +############################# Event notification ############################## + +# Redis can notify Pub/Sub clients about events happening in the key space. +# This feature is documented at http://redis.io/topics/keyspace-events +# +# For instance if keyspace events notification is enabled, and a client +# performs a DEL operation on key "foo" stored in the Database 0, two +# messages will be published via Pub/Sub: +# +# PUBLISH __keyspace@0__:foo del +# PUBLISH __keyevent@0__:del foo +# +# It is possible to select the events that Redis will notify among a set +# of classes. Every class is identified by a single character: +# +# K Keyspace events, published with __keyspace@__ prefix. +# E Keyevent events, published with __keyevent@__ prefix. +# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... +# $ String commands +# l List commands +# s Set commands +# h Hash commands +# z Sorted set commands +# x Expired events (events generated every time a key expires) +# e Evicted events (events generated when a key is evicted for maxmemory) +# A Alias for g$lshzxe, so that the "AKE" string means all the events. +# +# The "notify-keyspace-events" takes as argument a string that is composed +# by zero or multiple characters. The empty string means that notifications +# are disabled at all. +# +# Example: to enable list and generic events, from the point of view of the +# event name, use: +# +# notify-keyspace-events Elg +# +# Example 2: to get the stream of the expired keys subscribing to channel +# name __keyevent@0__:expired use: +# +# notify-keyspace-events Ex +# +# By default all notifications are disabled because most users don't need +# this feature and the feature has some overhead. Note that if you don't +# specify at least one of K or E, no events will be delivered. +notify-keyspace-events "" + +############################### ADVANCED CONFIG ############################### + +# Hashes are encoded using a memory efficient data structure when they have a +# small number of entries, and the biggest entry does not exceed a given +# threshold. These thresholds can be configured using the following directives. +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +# Similarly to hashes, small lists are also encoded in a special way in order +# to save a lot of space. The special representation is only used when +# you are under the following limits: +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +# Sets have a special encoding in just one case: when a set is composed +# of just strings that happens to be integers in radix 10 in the range +# of 64 bit signed integers. +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +set-max-intset-entries 512 + +# Similarly to hashes and lists, sorted sets are also specially encoded in +# order to save a lot of space. This encoding is only used when the length and +# elements of a sorted set are below the following limits: +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in +# order to help rehashing the main Redis hash table (the one mapping top-level +# keys to values). The hash table implementation Redis uses (see dict.c) +# performs a lazy rehashing: the more operation you run into an hash table +# that is rehashing, the more rehashing "steps" are performed, so if the +# server is idle the rehashing is never complete and some more memory is used +# by the hash table. +# +# The default is to use this millisecond 10 times every second in order to +# active rehashing the main dictionaries, freeing memory when possible. +# +# If unsure: +# use "activerehashing no" if you have hard latency requirements and it is +# not a good thing in your environment that Redis can reply form time to time +# to queries with 2 milliseconds delay. +# +# use "activerehashing yes" if you don't have such hard requirements but +# want to free memory asap when possible. +activerehashing yes + +# The client output buffer limits can be used to force disconnection of clients +# that are not reading data from the server fast enough for some reason (a +# common reason is that a Pub/Sub client can't consume messages as fast as the +# publisher can produce them). +# +# The limit can be set differently for the three different classes of clients: +# +# normal -> normal clients +# slave -> slave clients and MONITOR clients +# pubsub -> clients subcribed to at least one pubsub channel or pattern +# +# The syntax of every client-output-buffer-limit directive is the following: +# +# client-output-buffer-limit +# +# A client is immediately disconnected once the hard limit is reached, or if +# the soft limit is reached and remains reached for the specified number of +# seconds (continuously). +# So for instance if the hard limit is 32 megabytes and the soft limit is +# 16 megabytes / 10 seconds, the client will get disconnected immediately +# if the size of the output buffers reach 32 megabytes, but will also get +# disconnected if the client reaches 16 megabytes and continuously overcomes +# the limit for 10 seconds. +# +# By default normal clients are not limited because they don't receive data +# without asking (in a push way), but just after a request, so only +# asynchronous clients may create a scenario where data is requested faster +# than it can read. +# +# Instead there is a default limit for pubsub and slave clients, since +# subscribers and slaves receive data in a push fashion. +# +# Both the hard or the soft limit can be disabled by setting them to zero. +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +# Redis calls an internal function to perform many background tasks, like +# closing connections of clients in timeot, purging expired keys that are +# never requested, and so forth. +# +# Not all tasks are performed with the same frequency, but Redis checks for +# tasks to perform accordingly to the specified "hz" value. +# +# By default "hz" is set to 10. Raising the value will use more CPU when +# Redis is idle, but at the same time will make Redis more responsive when +# there are many keys expiring at the same time, and timeouts may be +# handled with more precision. +# +# The range is between 1 and 500, however a value over 100 is usually not +# a good idea. Most users should use the default of 10 and raise this up to +# 100 only in environments where very low latency is required. +hz 10 + +# When a child rewrites the AOF file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +aof-rewrite-incremental-fsync yes + +################################## INCLUDES ################################### + +# Include one or more other config files here. This is useful if you +# have a standard template that goes to all Redis server but also need +# to customize a few per-server settings. Include files can include +# other files, so use this wisely. +# +# include /path/to/local.conf +# include /path/to/other.conf +include /etc/redis/conf.d/local.conf diff --git a/vagrant/reload-config.bat b/vagrant/reload-config.bat new file mode 100644 index 00000000..49909bd6 --- /dev/null +++ b/vagrant/reload-config.bat @@ -0,0 +1,2 @@ +cd ../ +vagrant ssh -c /vagrant/vagrant/copy-and-restart-configs.sh \ No newline at end of file diff --git a/vagrant/reload-config.vmware.bat b/vagrant/reload-config.vmware.bat new file mode 100644 index 00000000..584cb45c --- /dev/null +++ b/vagrant/reload-config.vmware.bat @@ -0,0 +1 @@ +elevator ../ vagrant ssh -c /vagrant/vagrant/copy-and-restart-configs.sh \ No newline at end of file