bound($abstract) || $this->isAlias($abstract); } public function bound($abstract) { return isset($this->bindings[$abstract]) || isset($this->instances[$abstract]); } public function resolved($abstract) { return isset($this->resolved[$abstract]) || isset($this->instances[$abstract]); } public function isAlias($name) { return isset($this->aliases[$name]); } public function bind($abstract, $concrete = null, $shared = false) { if (is_array($abstract)) { list($abstract, $alias) = $this->extractAlias($abstract); $this->alias($abstract, $alias); } $this->dropStaleInstances($abstract); if (is_null($concrete)) { $concrete = $abstract; } if (!$concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); if ($this->resolved($abstract)) { $this->rebound($abstract); } } protected function getClosure($abstract, $concrete) { return function ($c, $parameters = array()) use($abstract, $concrete) { $method = $abstract == $concrete ? 'build' : 'make'; return $c->{$method}($concrete, $parameters); }; } public function bindIf($abstract, $concrete = null, $shared = false) { if (!$this->bound($abstract)) { $this->bind($abstract, $concrete, $shared); } } public function singleton($abstract, $concrete = null) { $this->bind($abstract, $concrete, true); } public function share(Closure $closure) { return function ($container) use($closure) { static $object; if (is_null($object)) { $object = $closure($container); } return $object; }; } public function bindShared($abstract, Closure $closure) { $this->bind($abstract, $this->share($closure), true); } public function extend($abstract, Closure $closure) { if (!isset($this->bindings[$abstract])) { throw new \InvalidArgumentException("Type {$abstract} is not bound."); } if (isset($this->instances[$abstract])) { $this->instances[$abstract] = $closure($this->instances[$abstract], $this); $this->rebound($abstract); } else { $extender = $this->getExtender($abstract, $closure); $this->bind($abstract, $extender, $this->isShared($abstract)); } } protected function getExtender($abstract, Closure $closure) { $resolver = $this->bindings[$abstract]['concrete']; return function ($container) use($resolver, $closure) { return $closure($resolver($container), $container); }; } public function instance($abstract, $instance) { if (is_array($abstract)) { list($abstract, $alias) = $this->extractAlias($abstract); $this->alias($abstract, $alias); } unset($this->aliases[$abstract]); $bound = $this->bound($abstract); $this->instances[$abstract] = $instance; if ($bound) { $this->rebound($abstract); } } public function alias($abstract, $alias) { $this->aliases[$alias] = $abstract; } protected function extractAlias(array $definition) { return array(key($definition), current($definition)); } public function rebinding($abstract, Closure $callback) { $this->reboundCallbacks[$abstract][] = $callback; if ($this->bound($abstract)) { return $this->make($abstract); } } public function refresh($abstract, $target, $method) { return $this->rebinding($abstract, function ($app, $instance) use($target, $method) { $target->{$method}($instance); }); } protected function rebound($abstract) { $instance = $this->make($abstract); foreach ($this->getReboundCallbacks($abstract) as $callback) { call_user_func($callback, $this, $instance); } } protected function getReboundCallbacks($abstract) { if (isset($this->reboundCallbacks[$abstract])) { return $this->reboundCallbacks[$abstract]; } return array(); } public function make($abstract, $parameters = array()) { $abstract = $this->getAlias($abstract); if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } $concrete = $this->getConcrete($abstract); if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete, $parameters); } else { $object = $this->make($concrete, $parameters); } if ($this->isShared($abstract)) { $this->instances[$abstract] = $object; } $this->fireResolvingCallbacks($abstract, $object); $this->resolved[$abstract] = true; return $object; } protected function getConcrete($abstract) { if (!isset($this->bindings[$abstract])) { if ($this->missingLeadingSlash($abstract) && isset($this->bindings['\\' . $abstract])) { $abstract = '\\' . $abstract; } return $abstract; } return $this->bindings[$abstract]['concrete']; } protected function missingLeadingSlash($abstract) { return is_string($abstract) && strpos($abstract, '\\') !== 0; } public function build($concrete, $parameters = array()) { if ($concrete instanceof Closure) { return $concrete($this, $parameters); } $reflector = new ReflectionClass($concrete); if (!$reflector->isInstantiable()) { $message = "Target [{$concrete}] is not instantiable."; throw new BindingResolutionException($message); } $constructor = $reflector->getConstructor(); if (is_null($constructor)) { return new $concrete(); } $dependencies = $constructor->getParameters(); $parameters = $this->keyParametersByArgument($dependencies, $parameters); $instances = $this->getDependencies($dependencies, $parameters); return $reflector->newInstanceArgs($instances); } protected function getDependencies($parameters, array $primitives = array()) { $dependencies = array(); foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); if (array_key_exists($parameter->name, $primitives)) { $dependencies[] = $primitives[$parameter->name]; } elseif (is_null($dependency)) { $dependencies[] = $this->resolveNonClass($parameter); } else { $dependencies[] = $this->resolveClass($parameter); } } return (array) $dependencies; } protected function resolveNonClass(ReflectionParameter $parameter) { if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } $message = "Unresolvable dependency resolving [{$parameter}] in class {$parameter->getDeclaringClass()->getName()}"; throw new BindingResolutionException($message); } protected function resolveClass(ReflectionParameter $parameter) { try { return $this->make($parameter->getClass()->name); } catch (BindingResolutionException $e) { if ($parameter->isOptional()) { return $parameter->getDefaultValue(); } throw $e; } } protected function keyParametersByArgument(array $dependencies, array $parameters) { foreach ($parameters as $key => $value) { if (is_numeric($key)) { unset($parameters[$key]); $parameters[$dependencies[$key]->name] = $value; } } return $parameters; } public function resolving($abstract, Closure $callback) { $this->resolvingCallbacks[$abstract][] = $callback; } public function resolvingAny(Closure $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, $this); } } public function isShared($abstract) { if (isset($this->bindings[$abstract]['shared'])) { $shared = $this->bindings[$abstract]['shared']; } else { $shared = false; } return isset($this->instances[$abstract]) || $shared === true; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof Closure; } protected function getAlias($abstract) { return isset($this->aliases[$abstract]) ? $this->aliases[$abstract] : $abstract; } public function getBindings() { return $this->bindings; } protected function dropStaleInstances($abstract) { unset($this->instances[$abstract], $this->aliases[$abstract]); } public function forgetInstance($abstract) { unset($this->instances[$abstract]); } public function forgetInstances() { $this->instances = array(); } public function offsetExists($key) { return isset($this->bindings[$key]); } public function offsetGet($key) { return $this->make($key); } public function offsetSet($key, $value) { if (!$value instanceof Closure) { $value = function () use($value) { return $value; }; } $this->bind($key, $value); } public function offsetUnset($key) { unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]); } public function __get($key) { return $this[$key]; } public function __set($key, $value) { $this[$key] = $value; } } namespace Illuminate\Support\Contracts; interface ResponsePreparerInterface { public function prepareResponse($value); public function readyForResponses(); } namespace Illuminate\Foundation; use Closure; use Stack\Builder; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Config\FileLoader; use Illuminate\Container\Container; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\Facade; use Illuminate\Events\EventServiceProvider; use Illuminate\Routing\RoutingServiceProvider; use Illuminate\Exception\ExceptionServiceProvider; use Illuminate\Config\FileEnvironmentVariablesLoader; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Debug\Exception\FatalErrorException; use Illuminate\Support\Contracts\ResponsePreparerInterface; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class Application extends Container implements HttpKernelInterface, TerminableInterface, ResponsePreparerInterface { const VERSION = '4.2.22'; protected $booted = false; protected $bootingCallbacks = array(); protected $bootedCallbacks = array(); protected $finishCallbacks = array(); protected $shutdownCallbacks = array(); protected $middlewares = array(); protected $serviceProviders = array(); protected $loadedProviders = array(); protected $deferredServices = array(); protected static $requestClass = 'Illuminate\\Http\\Request'; public function __construct(Request $request = null) { $this->registerBaseBindings($request ?: $this->createNewRequest()); $this->registerBaseServiceProviders(); $this->registerBaseMiddlewares(); } protected function createNewRequest() { return forward_static_call(array(static::$requestClass, 'createFromGlobals')); } protected function registerBaseBindings($request) { $this->instance('request', $request); $this->instance('Illuminate\\Container\\Container', $this); } protected function registerBaseServiceProviders() { foreach (array('Event', 'Exception', 'Routing') 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)); } public function bindInstallPaths(array $paths) { $this->instance('path', realpath($paths['app'])); foreach (array_except($paths, array('app')) as $key => $value) { $this->instance("path.{$key}", realpath($value)); } } public static function getBootstrapFile() { return '/project/vendor/laravel/framework/src/Illuminate/Foundation' . '/start.php'; } public function startExceptionHandling() { $this['exception']->register($this->environment()); $this['exception']->setDebug($this['config']['app.debug']); } public function environment() { if (count(func_get_args()) > 0) { return in_array($this['env'], func_get_args()); } return $this['env']; } public function isLocal() { return $this['env'] == 'local'; } public function detectEnvironment($envs) { $args = isset($_SERVER['argv']) ? $_SERVER['argv'] : null; return $this['env'] = (new EnvironmentDetector())->detect($envs, $args); } public function runningInConsole() { return php_sapi_name() == 'cli'; } public function runningUnitTests() { return $this['env'] == 'testing'; } public function forceRegister($provider, $options = array()) { return $this->register($provider, $options, true); } public function register($provider, $options = array(), $force = false) { if ($registered = $this->getRegistered($provider) && !$force) { return $registered; } if (is_string($provider)) { $provider = $this->resolveProviderClass($provider); } $provider->register(); foreach ($options as $key => $value) { $this[$key] = $value; } $this->markAsRegistered($provider); if ($this->booted) { $provider->boot(); } return $provider; } public function getRegistered($provider) { $name = is_string($provider) ? $provider : get_class($provider); if (array_key_exists($name, $this->loadedProviders)) { return array_first($this->serviceProviders, function ($key, $value) use($name) { return get_class($value) == $name; }); } } public function resolveProviderClass($provider) { return new $provider($this); } protected function markAsRegistered($provider) { $this['events']->fire($class = get_class($provider), array($provider)); $this->serviceProviders[] = $provider; $this->loadedProviders[$class] = true; } public function loadDeferredProviders() { foreach ($this->deferredServices as $service => $provider) { $this->loadDeferredProvider($service); } $this->deferredServices = array(); } protected function loadDeferredProvider($service) { $provider = $this->deferredServices[$service]; if (!isset($this->loadedProviders[$provider])) { $this->registerDeferredProvider($provider, $service); } } public function registerDeferredProvider($provider, $service = null) { if ($service) { unset($this->deferredServices[$service]); } $this->register($instance = new $provider($this)); if (!$this->booted) { $this->booting(function () use($instance) { $instance->boot(); }); } } public function make($abstract, $parameters = array()) { $abstract = $this->getAlias($abstract); if (isset($this->deferredServices[$abstract])) { $this->loadDeferredProvider($abstract); } return parent::make($abstract, $parameters); } public function bound($abstract) { return isset($this->deferredServices[$abstract]) || parent::bound($abstract); } public function extend($abstract, Closure $closure) { $abstract = $this->getAlias($abstract); if (isset($this->deferredServices[$abstract])) { $this->loadDeferredProvider($abstract); } return parent::extend($abstract, $closure); } public function before($callback) { return $this['router']->before($callback); } public function after($callback) { return $this['router']->after($callback); } public function finish($callback) { $this->finishCallbacks[] = $callback; } public function shutdown(callable $callback = null) { if (is_null($callback)) { $this->fireAppCallbacks($this->shutdownCallbacks); } else { $this->shutdownCallbacks[] = $callback; } } public function useArraySessions(Closure $callback) { $this->bind('session.reject', function () use($callback) { return $callback; }); } public function isBooted() { return $this->booted; } public function boot() { if ($this->booted) { return; } array_walk($this->serviceProviders, function ($p) { $p->boot(); }); $this->bootApplication(); } protected function bootApplication() { $this->fireAppCallbacks($this->bootingCallbacks); $this->booted = true; $this->fireAppCallbacks($this->bootedCallbacks); } public function booting($callback) { $this->bootingCallbacks[] = $callback; } public function booted($callback) { $this->bootedCallbacks[] = $callback; if ($this->isBooted()) { $this->fireAppCallbacks(array($callback)); } } public function run(SymfonyRequest $request = null) { $request = $request ?: $this['request']; $response = with($stack = $this->getStackedClient())->handle($request); $response->send(); $stack->terminate($request, $response); } protected function getStackedClient() { $sessionReject = $this->bound('session.reject') ? $this['session.reject'] : null; $client = (new Builder())->push('Illuminate\\Cookie\\Guard', $this['encrypter'])->push('Illuminate\\Cookie\\Queue', $this['cookie'])->push('Illuminate\\Session\\Middleware', $this['session'], $sessionReject); $this->mergeCustomMiddlewares($client); return $client->resolve($this); } protected function mergeCustomMiddlewares(Builder $stack) { foreach ($this->middlewares as $middleware) { list($class, $parameters) = array_values($middleware); array_unshift($parameters, $class); call_user_func_array(array($stack, 'push'), $parameters); } } protected function registerBaseMiddlewares() { } public function middleware($class, array $parameters = array()) { $this->middlewares[] = compact('class', 'parameters'); return $this; } public function forgetMiddleware($class) { $this->middlewares = array_filter($this->middlewares, function ($m) use($class) { return $m['class'] != $class; }); } public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { try { $this->refreshRequest($request = Request::createFromBase($request)); $this->boot(); return $this->dispatch($request); } catch (\Exception $e) { if (!$catch || $this->runningUnitTests()) { throw $e; } return $this['exception']->handleException($e); } catch (\Throwable $e) { if (!$catch || $this->runningUnitTests()) { throw $e; } return $this['exception']->handleException($e); } } public function dispatch(Request $request) { if ($this->isDownForMaintenance()) { $response = $this['events']->until('illuminate.app.down'); if (!is_null($response)) { return $this->prepareResponse($response, $request); } } if ($this->runningUnitTests() && !$this['session']->isStarted()) { $this['session']->start(); } return $this['router']->dispatch($this->prepareRequest($request)); } public function terminate(SymfonyRequest $request, SymfonyResponse $response) { $this->callFinishCallbacks($request, $response); $this->shutdown(); } protected function refreshRequest(Request $request) { $this->instance('request', $request); Facade::clearResolvedInstance('request'); } public function callFinishCallbacks(SymfonyRequest $request, SymfonyResponse $response) { foreach ($this->finishCallbacks as $callback) { call_user_func($callback, $request, $response); } } protected function fireAppCallbacks(array $callbacks) { foreach ($callbacks as $callback) { call_user_func($callback, $this); } } public function prepareRequest(Request $request) { if (!is_null($this['config']['session.driver']) && !$request->hasSession()) { $request->setSession($this['session']->driver()); } return $request; } public function prepareResponse($value) { if (!$value instanceof SymfonyResponse) { $value = new Response($value); } return $value->prepare($this['request']); } public function readyForResponses() { return $this->booted; } public function isDownForMaintenance() { return file_exists($this['config']['app.manifest'] . '/down'); } public function down(Closure $callback) { $this['events']->listen('illuminate.app.down', $callback); } public function abort($code, $message = '', array $headers = array()) { if ($code == 404) { throw new NotFoundHttpException($message); } throw new HttpException($code, $message, null, $headers); } public function missing(Closure $callback) { $this->error(function (NotFoundHttpException $e) use($callback) { return call_user_func($callback, $e); }); } public function error(Closure $callback) { $this['exception']->error($callback); } public function pushError(Closure $callback) { $this['exception']->pushError($callback); } public function fatal(Closure $callback) { $this->error(function (FatalErrorException $e) use($callback) { return call_user_func($callback, $e); }); } public function getConfigLoader() { return new FileLoader(new Filesystem(), $this['path'] . '/config'); } public function getEnvironmentVariablesLoader() { return new FileEnvironmentVariablesLoader(new Filesystem(), $this['path.base']); } public function getProviderRepository() { $manifest = $this['config']['app.manifest']; return new ProviderRepository(new Filesystem(), $manifest); } public function getLoadedProviders() { return $this->loadedProviders; } public function setDeferredServices(array $services) { $this->deferredServices = $services; } public function isDeferredService($service) { return isset($this->deferredServices[$service]); } public static function requestClass($class = null) { if (!is_null($class)) { static::$requestClass = $class; } return static::$requestClass; } public function setRequestForConsoleEnvironment() { $url = $this['config']->get('app.url', 'http://localhost'); $parameters = array($url, 'GET', array(), array(), array(), $_SERVER); $this->refreshRequest(static::onRequest('create', $parameters)); } public static function onRequest($method, $parameters = array()) { return forward_static_call_array(array(static::requestClass(), $method), $parameters); } public function getLocale() { return $this['config']->get('app.locale'); } public function setLocale($locale) { $this['config']->set('app.locale', $locale); $this['translator']->setLocale($locale); $this['events']->fire('locale.changed', array($locale)); } public function registerCoreContainerAliases() { $aliases = array('app' => 'Illuminate\\Foundation\\Application', 'artisan' => 'Illuminate\\Console\\Application', 'auth' => 'Illuminate\\Auth\\AuthManager', 'auth.reminder.repository' => 'Illuminate\\Auth\\Reminders\\ReminderRepositoryInterface', 'blade.compiler' => 'Illuminate\\View\\Compilers\\BladeCompiler', 'cache' => 'Illuminate\\Cache\\CacheManager', 'cache.store' => 'Illuminate\\Cache\\Repository', 'config' => 'Illuminate\\Config\\Repository', 'cookie' => 'Illuminate\\Cookie\\CookieJar', 'encrypter' => 'Illuminate\\Encryption\\Encrypter', 'db' => 'Illuminate\\Database\\DatabaseManager', 'events' => 'Illuminate\\Events\\Dispatcher', 'files' => 'Illuminate\\Filesystem\\Filesystem', 'form' => 'Illuminate\\Html\\FormBuilder', 'hash' => 'Illuminate\\Hashing\\HasherInterface', 'html' => 'Illuminate\\Html\\HtmlBuilder', 'translator' => 'Illuminate\\Translation\\Translator', 'log' => 'Illuminate\\Log\\Writer', 'mailer' => 'Illuminate\\Mail\\Mailer', 'paginator' => 'Illuminate\\Pagination\\Factory', 'auth.reminder' => 'Illuminate\\Auth\\Reminders\\PasswordBroker', 'queue' => 'Illuminate\\Queue\\QueueManager', 'redirect' => 'Illuminate\\Routing\\Redirector', 'redis' => 'Illuminate\\Redis\\Database', 'request' => 'Illuminate\\Http\\Request', 'router' => 'Illuminate\\Routing\\Router', 'session' => 'Illuminate\\Session\\SessionManager', 'session.store' => 'Illuminate\\Session\\Store', 'remote' => 'Illuminate\\Remote\\RemoteManager', 'url' => 'Illuminate\\Routing\\UrlGenerator', 'validator' => 'Illuminate\\Validation\\Factory', 'view' => 'Illuminate\\View\\Factory'); foreach ($aliases as $key => $alias) { $this->alias($key, $alias); } } } namespace Illuminate\Foundation; use Closure; class EnvironmentDetector { public function detect($environments, $consoleArgs = null) { if ($consoleArgs) { return $this->detectConsoleEnvironment($environments, $consoleArgs); } return $this->detectWebEnvironment($environments); } protected function detectWebEnvironment($environments) { if ($environments instanceof Closure) { return call_user_func($environments); } foreach ($environments as $environment => $hosts) { foreach ((array) $hosts as $host) { if ($this->isMachine($host)) { return $environment; } } } return 'production'; } protected function detectConsoleEnvironment($environments, array $args) { if (!is_null($value = $this->getEnvironmentArgument($args))) { return head(array_slice(explode('=', $value), 1)); } return $this->detectWebEnvironment($environments); } protected function getEnvironmentArgument(array $args) { return array_first($args, function ($k, $v) { return starts_with($v, '--env'); }); } public function isMachine($name) { return str_is($name, gethostname()); } } namespace Illuminate\Http; use SplFileInfo; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; class Request extends SymfonyRequest { protected $json; protected $sessionStore; public function instance() { return $this; } public function method() { return $this->getMethod(); } public function root() { return rtrim($this->getSchemeAndHttpHost() . $this->getBaseUrl(), '/'); } public function url() { return rtrim(preg_replace('/\\?.*/', '', $this->getUri()), '/'); } public function fullUrl() { $query = $this->getQueryString(); return $query ? $this->url() . '?' . $query : $this->url(); } public function path() { $pattern = trim($this->getPathInfo(), '/'); return $pattern == '' ? '/' : $pattern; } public function decodedPath() { return rawurldecode($this->path()); } public function segment($index, $default = null) { return array_get($this->segments(), $index - 1, $default); } public function segments() { $segments = explode('/', $this->path()); return array_values(array_filter($segments, function ($v) { return $v != ''; })); } public function is() { foreach (func_get_args() as $pattern) { if (str_is($pattern, urldecode($this->path()))) { return true; } } return false; } public function ajax() { return $this->isXmlHttpRequest(); } public function secure() { return $this->isSecure(); } public function ip() { return $this->getClientIp(); } public function ips() { return $this->getClientIps(); } public function exists($key) { $keys = is_array($key) ? $key : func_get_args(); $input = $this->all(); foreach ($keys as $value) { if (!array_key_exists($value, $input)) { return false; } } return true; } public function has($key) { $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $value) { if ($this->isEmptyString($value)) { return false; } } return true; } protected function isEmptyString($key) { $boolOrArray = is_bool($this->input($key)) || is_array($this->input($key)); return !$boolOrArray && trim((string) $this->input($key)) === ''; } public function all() { return array_replace_recursive($this->input(), $this->files->all()); } public function input($key = null, $default = null) { $input = $this->getInputSource()->all() + $this->query->all(); return array_get($input, $key, $default); } public function only($keys) { $keys = is_array($keys) ? $keys : func_get_args(); $results = array(); $input = $this->all(); foreach ($keys as $key) { array_set($results, $key, array_get($input, $key)); } return $results; } public function except($keys) { $keys = is_array($keys) ? $keys : func_get_args(); $results = $this->all(); array_forget($results, $keys); return $results; } public function query($key = null, $default = null) { return $this->retrieveItem('query', $key, $default); } public function hasCookie($key) { return !is_null($this->cookie($key)); } public function cookie($key = null, $default = null) { return $this->retrieveItem('cookies', $key, $default); } public function file($key = null, $default = null) { return array_get($this->files->all(), $key, $default); } public function hasFile($key) { if (!is_array($files = $this->file($key))) { $files = array($files); } foreach ($files as $file) { if ($this->isValidFile($file)) { return true; } } return false; } protected function isValidFile($file) { return $file instanceof SplFileInfo && $file->getPath() != ''; } public function header($key = null, $default = null) { return $this->retrieveItem('headers', $key, $default); } public function server($key = null, $default = null) { return $this->retrieveItem('server', $key, $default); } public function old($key = null, $default = null) { return $this->session()->getOldInput($key, $default); } public function flash($filter = null, $keys = array()) { $flash = !is_null($filter) ? $this->{$filter}($keys) : $this->input(); $this->session()->flashInput($flash); } public function flashOnly($keys) { $keys = is_array($keys) ? $keys : func_get_args(); return $this->flash('only', $keys); } public function flashExcept($keys) { $keys = is_array($keys) ? $keys : func_get_args(); return $this->flash('except', $keys); } public function flush() { $this->session()->flashInput(array()); } protected function retrieveItem($source, $key, $default) { if (is_null($key)) { return $this->{$source}->all(); } return $this->{$source}->get($key, $default, true); } public function merge(array $input) { $this->getInputSource()->add($input); } public function replace(array $input) { $this->getInputSource()->replace($input); } public function json($key = null, $default = null) { if (!isset($this->json)) { $this->json = new ParameterBag((array) json_decode($this->getContent(), true)); } if (is_null($key)) { return $this->json; } return array_get($this->json->all(), $key, $default); } protected function getInputSource() { if ($this->isJson()) { return $this->json(); } return $this->getMethod() == 'GET' ? $this->query : $this->request; } public function isJson() { return str_contains($this->header('CONTENT_TYPE'), '/json'); } public function wantsJson() { $acceptable = $this->getAcceptableContentTypes(); return isset($acceptable[0]) && $acceptable[0] == 'application/json'; } public function format($default = 'html') { foreach ($this->getAcceptableContentTypes() as $type) { if ($format = $this->getFormat($type)) { return $format; } } return $default; } public static function createFromBase(SymfonyRequest $request) { if ($request instanceof static) { return $request; } $content = $request->content; $request = (new static())->duplicate($request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all()); $request->content = $content; $request->request = $request->getInputSource(); return $request; } public function session() { if (!$this->hasSession()) { throw new \RuntimeException('Session store not set on request.'); } return $this->getSession(); } } namespace Illuminate\Http; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; class FrameGuard implements HttpKernelInterface { protected $app; public function __construct(HttpKernelInterface $app) { $this->app = $app; } public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { $response = $this->app->handle($request, $type, $catch); $response->headers->set('X-Frame-Options', 'SAMEORIGIN', false); return $response; } } namespace Illuminate\Support; use ReflectionClass; abstract class ServiceProvider { protected $app; protected $defer = false; public function __construct($app) { $this->app = $app; } public function boot() { } public abstract function register(); public function package($package, $namespace = null, $path = null) { $namespace = $this->getPackageNamespace($package, $namespace); $path = $path ?: $this->guessPackagePath(); $config = $path . '/config'; if ($this->app['files']->isDirectory($config)) { $this->app['config']->package($package, $config, $namespace); } $lang = $path . '/lang'; if ($this->app['files']->isDirectory($lang)) { $this->app['translator']->addNamespace($namespace, $lang); } $appView = $this->getAppViewPath($package); if ($this->app['files']->isDirectory($appView)) { $this->app['view']->addNamespace($namespace, $appView); } $view = $path . '/views'; if ($this->app['files']->isDirectory($view)) { $this->app['view']->addNamespace($namespace, $view); } } public function guessPackagePath() { $path = (new ReflectionClass($this))->getFileName(); return realpath(dirname($path) . '/../../'); } protected function getPackageNamespace($package, $namespace) { if (is_null($namespace)) { list($vendor, $namespace) = explode('/', $package); } return $namespace; } public function commands($commands) { $commands = is_array($commands) ? $commands : func_get_args(); $events = $this->app['events']; $events->listen('artisan.start', function ($artisan) use($commands) { $artisan->resolveCommands($commands); }); } protected function getAppViewPath($package) { return $this->app['path'] . "/views/packages/{$package}"; } public function provides() { return array(); } public function when() { return array(); } public function isDeferred() { return $this->defer; } } namespace Illuminate\Exception; use Whoops\Run; use Whoops\Handler\PrettyPageHandler; use Whoops\Handler\JsonResponseHandler; use Illuminate\Support\ServiceProvider; class ExceptionServiceProvider extends ServiceProvider { public function register() { $this->registerDisplayers(); $this->registerHandler(); } protected function registerDisplayers() { $this->registerPlainDisplayer(); $this->registerDebugDisplayer(); } protected function registerHandler() { $this->app['exception'] = $this->app->share(function ($app) { return new Handler($app, $app['exception.plain'], $app['exception.debug']); }); } protected function registerPlainDisplayer() { $this->app['exception.plain'] = $this->app->share(function ($app) { if ($app->runningInConsole()) { return $app['exception.debug']; } else { return new PlainDisplayer(); } }); } protected function registerDebugDisplayer() { $this->registerWhoops(); $this->app['exception.debug'] = $this->app->share(function ($app) { return new WhoopsDisplayer($app['whoops'], $app->runningInConsole()); }); } protected function registerWhoops() { $this->registerWhoopsHandler(); $this->app['whoops'] = $this->app->share(function ($app) { with($whoops = new Run())->allowQuit(false); $whoops->writeToOutput(false); return $whoops->pushHandler($app['whoops.handler']); }); } protected function registerWhoopsHandler() { if ($this->shouldReturnJson()) { $this->app['whoops.handler'] = $this->app->share(function () { return new JsonResponseHandler(); }); } else { $this->registerPrettyWhoopsHandler(); } } protected function shouldReturnJson() { return $this->app->runningInConsole() || $this->requestWantsJson(); } protected function requestWantsJson() { return $this->app['request']->ajax() || $this->app['request']->wantsJson(); } protected function registerPrettyWhoopsHandler() { $this->app['whoops.handler'] = $this->app->share(function () { with($handler = new PrettyPageHandler())->setEditor('sublime'); return $handler; }); } } namespace Illuminate\Routing; use Illuminate\Support\ServiceProvider; class RoutingServiceProvider extends ServiceProvider { public function register() { $this->registerRouter(); $this->registerUrlGenerator(); $this->registerRedirector(); } protected function registerRouter() { $this->app['router'] = $this->app->share(function ($app) { $router = new Router($app['events'], $app); if ($app['env'] == 'testing') { $router->disableFilters(); } return $router; }); } protected function registerUrlGenerator() { $this->app['url'] = $this->app->share(function ($app) { $routes = $app['router']->getRoutes(); return new UrlGenerator($routes, $app->rebinding('request', function ($app, $request) { $app['url']->setRequest($request); })); }); } protected function registerRedirector() { $this->app['redirect'] = $this->app->share(function ($app) { $redirector = new Redirector($app['url']); if (isset($app['session.store'])) { $redirector->setSession($app['session.store']); } return $redirector; }); } } namespace Illuminate\Events; use Illuminate\Support\ServiceProvider; class EventServiceProvider extends ServiceProvider { public function register() { $this->app['events'] = $this->app->share(function ($app) { return new Dispatcher($app); }); } } namespace Illuminate\Support\Facades; use Mockery\MockInterface; abstract class Facade { protected static $app; protected static $resolvedInstance; public static function swap($instance) { static::$resolvedInstance[static::getFacadeAccessor()] = $instance; static::$app->instance(static::getFacadeAccessor(), $instance); } public static function shouldReceive() { $name = static::getFacadeAccessor(); if (static::isMock()) { $mock = static::$resolvedInstance[$name]; } else { $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(); return isset(static::$resolvedInstance[$name]) && static::$resolvedInstance[$name] instanceof MockInterface; } protected static function getMockableClass() { if ($root = static::getFacadeRoot()) { return get_class($root); } } public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); } protected static function getFacadeAccessor() { throw new \RuntimeException('Facade does not implement getFacadeAccessor method.'); } protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; } public static function clearResolvedInstance($name) { unset(static::$resolvedInstance[$name]); } public static function clearResolvedInstances() { static::$resolvedInstance = array(); } public static function getFacadeApplication() { return static::$app; } public static function setFacadeApplication($app) { static::$app = $app; } public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); switch (count($args)) { case 0: return $instance->{$method}(); case 1: return $instance->{$method}($args[0]); case 2: return $instance->{$method}($args[0], $args[1]); case 3: return $instance->{$method}($args[0], $args[1], $args[2]); case 4: return $instance->{$method}($args[0], $args[1], $args[2], $args[3]); default: return call_user_func_array(array($instance, $method), $args); } } } namespace Illuminate\Support\Traits; trait MacroableTrait { protected static $macros = array(); public static function macro($name, callable $macro) { static::$macros[$name] = $macro; } public static function hasMacro($name) { return isset(static::$macros[$name]); } public static function __callStatic($method, $parameters) { if (static::hasMacro($method)) { return call_user_func_array(static::$macros[$method], $parameters); } throw new \BadMethodCallException("Method {$method} does not exist."); } public function __call($method, $parameters) { return static::__callStatic($method, $parameters); } } namespace Illuminate\Support; use Closure; use Illuminate\Support\Traits\MacroableTrait; class Arr { use MacroableTrait; public static function add($array, $key, $value) { if (is_null(static::get($array, $key))) { static::set($array, $key, $value); } return $array; } public static function build($array, Closure $callback) { $results = array(); foreach ($array as $key => $value) { list($innerKey, $innerValue) = call_user_func($callback, $key, $value); $results[$innerKey] = $innerValue; } return $results; } public static function divide($array) { return array(array_keys($array), array_values($array)); } public static function dot($array, $prepend = '') { $results = array(); foreach ($array as $key => $value) { if (is_array($value)) { $results = array_merge($results, static::dot($value, $prepend . $key . '.')); } else { $results[$prepend . $key] = $value; } } return $results; } public static function except($array, $keys) { return array_diff_key($array, array_flip((array) $keys)); } public static function fetch($array, $key) { foreach (explode('.', $key) as $segment) { $results = array(); foreach ($array as $value) { if (array_key_exists($segment, $value = (array) $value)) { $results[] = $value[$segment]; } } $array = array_values($results); } return array_values($results); } public static function first($array, $callback, $default = null) { foreach ($array as $key => $value) { if (call_user_func($callback, $key, $value)) { return $value; } } return value($default); } public static function last($array, $callback, $default = null) { return static::first(array_reverse($array), $callback, $default); } public static function flatten($array) { $return = array(); array_walk_recursive($array, function ($x) use(&$return) { $return[] = $x; }); return $return; } public static function forget(&$array, $keys) { $original =& $array; foreach ((array) $keys as $key) { $parts = explode('.', $key); while (count($parts) > 1) { $part = array_shift($parts); if (isset($array[$part]) && is_array($array[$part])) { $array =& $array[$part]; } } unset($array[array_shift($parts)]); $array =& $original; } } public static function get($array, $key, $default = null) { if (is_null($key)) { return $array; } if (isset($array[$key])) { return $array[$key]; } foreach (explode('.', $key) as $segment) { if (!is_array($array) || !array_key_exists($segment, $array)) { return value($default); } $array = $array[$segment]; } return $array; } public static function has($array, $key) { if (empty($array) || is_null($key)) { return false; } if (array_key_exists($key, $array)) { return true; } foreach (explode('.', $key) as $segment) { if (!is_array($array) || !array_key_exists($segment, $array)) { return false; } $array = $array[$segment]; } return true; } public static function only($array, $keys) { return array_intersect_key($array, array_flip((array) $keys)); } public static function pluck($array, $value, $key = null) { $results = array(); foreach ($array as $item) { $itemValue = is_object($item) ? $item->{$value} : $item[$value]; if (is_null($key)) { $results[] = $itemValue; } else { $itemKey = is_object($item) ? $item->{$key} : $item[$key]; $results[$itemKey] = $itemValue; } } return $results; } public static function pull(&$array, $key, $default = null) { $value = static::get($array, $key, $default); static::forget($array, $key); return $value; } public static function set(&$array, $key, $value) { if (is_null($key)) { return $array = $value; } $keys = explode('.', $key); while (count($keys) > 1) { $key = array_shift($keys); if (!isset($array[$key]) || !is_array($array[$key])) { $array[$key] = array(); } $array =& $array[$key]; } $array[array_shift($keys)] = $value; return $array; } public static function sort($array, Closure $callback) { return Collection::make($array)->sortBy($callback)->all(); } public static function where($array, Closure $callback) { $filtered = array(); foreach ($array as $key => $value) { if (call_user_func($callback, $key, $value)) { $filtered[$key] = $value; } } return $filtered; } } namespace Illuminate\Support; use Patchwork\Utf8; use Illuminate\Support\Traits\MacroableTrait; class Str { use MacroableTrait; protected static $snakeCache = array(); protected static $camelCache = array(); protected static $studlyCache = array(); public static function ascii($value) { return Utf8::toAscii($value); } public static function camel($value) { if (isset(static::$camelCache[$value])) { return static::$camelCache[$value]; } return static::$camelCache[$value] = lcfirst(static::studly($value)); } public static function contains($haystack, $needles) { foreach ((array) $needles as $needle) { if ($needle != '' && strpos($haystack, $needle) !== false) { return true; } } return false; } public static function endsWith($haystack, $needles) { foreach ((array) $needles as $needle) { if ((string) $needle === substr($haystack, -strlen($needle))) { return true; } } return false; } public static function finish($value, $cap) { $quoted = preg_quote($cap, '/'); return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap; } public static function is($pattern, $value) { if ($pattern == $value) { return true; } $pattern = preg_quote($pattern, '#'); $pattern = str_replace('\\*', '.*', $pattern) . '\\z'; return (bool) preg_match('#^' . $pattern . '#', $value); } public static function length($value) { return mb_strlen($value); } public static function limit($value, $limit = 100, $end = '...') { if (mb_strlen($value) <= $limit) { return $value; } return rtrim(mb_substr($value, 0, $limit, 'UTF-8')) . $end; } public static function lower($value) { return mb_strtolower($value); } public static function words($value, $words = 100, $end = '...') { preg_match('/^\\s*+(?:\\S++\\s*+){1,' . $words . '}/u', $value, $matches); if (!isset($matches[0]) || strlen($value) === strlen($matches[0])) { return $value; } return rtrim($matches[0]) . $end; } public static function parseCallback($callback, $default) { return static::contains($callback, '@') ? explode('@', $callback, 2) : array($callback, $default); } public static function plural($value, $count = 2) { return Pluralizer::plural($value, $count); } public static function random($length = 16) { if (function_exists('openssl_random_pseudo_bytes')) { $bytes = openssl_random_pseudo_bytes($length * 2); if ($bytes === false) { throw new \RuntimeException('Unable to generate random string.'); } return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length); } return static::quickRandom($length); } public static function quickRandom($length = 16) { $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return substr(str_shuffle(str_repeat($pool, $length)), 0, $length); } public static function upper($value) { 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); } public static function slug($title, $separator = '-') { $title = static::ascii($title); $flip = $separator == '-' ? '_' : '-'; $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title); $title = preg_replace('![^' . preg_quote($separator) . '\\pL\\pN\\s]+!u', '', mb_strtolower($title)); $title = preg_replace('![' . preg_quote($separator) . '\\s]+!u', $separator, $title); return trim($title, $separator); } public static function snake($value, $delimiter = '_') { $key = $value . $delimiter; if (isset(static::$snakeCache[$key])) { return static::$snakeCache[$key]; } if (!ctype_lower($value)) { $replace = '$1' . $delimiter . '$2'; $value = strtolower(preg_replace('/(.)([A-Z])/', $replace, $value)); } return static::$snakeCache[$key] = $value; } public static function startsWith($haystack, $needles) { foreach ((array) $needles as $needle) { if ($needle != '' && strpos($haystack, $needle) === 0) { return true; } } return false; } public static function studly($value) { $key = $value; if (isset(static::$studlyCache[$key])) { return static::$studlyCache[$key]; } $value = ucwords(str_replace(array('-', '_'), ' ', $value)); return static::$studlyCache[$key] = str_replace(' ', '', $value); } } namespace Illuminate\Config; use Closure; use ArrayAccess; use Illuminate\Support\NamespacedItemResolver; class Repository extends NamespacedItemResolver implements ArrayAccess { protected $loader; protected $environment; protected $items = array(); protected $packages = array(); protected $afterLoad = array(); public function __construct(LoaderInterface $loader, $environment) { $this->loader = $loader; $this->environment = $environment; } public function has($key) { $default = microtime(true); return $this->get($key, $default) !== $default; } public function hasGroup($key) { list($namespace, $group, $item) = $this->parseKey($key); return $this->loader->exists($group, $namespace); } public function get($key, $default = null) { list($namespace, $group, $item) = $this->parseKey($key); $collection = $this->getCollection($group, $namespace); $this->load($group, $namespace, $collection); return array_get($this->items[$collection], $item, $default); } public function set($key, $value) { list($namespace, $group, $item) = $this->parseKey($key); $collection = $this->getCollection($group, $namespace); $this->load($group, $namespace, $collection); if (is_null($item)) { $this->items[$collection] = $value; } else { array_set($this->items[$collection], $item, $value); } } protected function load($group, $namespace, $collection) { $env = $this->environment; if (isset($this->items[$collection])) { return; } $items = $this->loader->load($env, $group, $namespace); if (isset($this->afterLoad[$namespace])) { $items = $this->callAfterLoad($namespace, $group, $items); } $this->items[$collection] = $items; } protected function callAfterLoad($namespace, $group, $items) { $callback = $this->afterLoad[$namespace]; return call_user_func($callback, $this, $group, $items); } protected function parseNamespacedSegments($key) { list($namespace, $item) = explode('::', $key); if (in_array($namespace, $this->packages)) { return $this->parsePackageSegments($key, $namespace, $item); } return parent::parseNamespacedSegments($key); } protected function parsePackageSegments($key, $namespace, $item) { $itemSegments = explode('.', $item); if (!$this->loader->exists($itemSegments[0], $namespace)) { return array($namespace, 'config', $item); } return parent::parseNamespacedSegments($key); } public function package($package, $hint, $namespace = null) { $namespace = $this->getPackageNamespace($package, $namespace); $this->packages[] = $namespace; $this->addNamespace($namespace, $hint); $this->afterLoading($namespace, function ($me, $group, $items) use($package) { $env = $me->getEnvironment(); $loader = $me->getLoader(); return $loader->cascadePackage($env, $package, $group, $items); }); } protected function getPackageNamespace($package, $namespace) { if (is_null($namespace)) { list($vendor, $namespace) = explode('/', $package); } return $namespace; } public function afterLoading($namespace, Closure $callback) { $this->afterLoad[$namespace] = $callback; } protected function getCollection($group, $namespace = null) { $namespace = $namespace ?: '*'; return $namespace . '::' . $group; } public function addNamespace($namespace, $hint) { $this->loader->addNamespace($namespace, $hint); } public function getNamespaces() { return $this->loader->getNamespaces(); } public function getLoader() { return $this->loader; } public function setLoader(LoaderInterface $loader) { $this->loader = $loader; } public function getEnvironment() { return $this->environment; } public function getAfterLoadCallbacks() { return $this->afterLoad; } public function getItems() { return $this->items; } public function offsetExists($key) { return $this->has($key); } public function offsetGet($key) { return $this->get($key); } public function offsetSet($key, $value) { $this->set($key, $value); } public function offsetUnset($key) { $this->set($key, null); } } namespace Illuminate\Support; class NamespacedItemResolver { protected $parsed = array(); public function parseKey($key) { if (isset($this->parsed[$key])) { return $this->parsed[$key]; } if (strpos($key, '::') === false) { $segments = explode('.', $key); $parsed = $this->parseBasicSegments($segments); } else { $parsed = $this->parseNamespacedSegments($key); } return $this->parsed[$key] = $parsed; } protected function parseBasicSegments(array $segments) { $group = $segments[0]; if (count($segments) == 1) { return array(null, $group, null); } else { $item = implode('.', array_slice($segments, 1)); return array(null, $group, $item); } } protected function parseNamespacedSegments($key) { list($namespace, $item) = explode('::', $key); $itemSegments = explode('.', $item); $groupAndItem = array_slice($this->parseBasicSegments($itemSegments), 1); return array_merge(array($namespace), $groupAndItem); } public function setParsedKey($key, $parsed) { $this->parsed[$key] = $parsed; } } namespace Illuminate\Config; use Illuminate\Filesystem\Filesystem; class FileLoader implements LoaderInterface { protected $files; protected $defaultPath; protected $hints = array(); protected $exists = array(); public function __construct(Filesystem $files, $defaultPath) { $this->files = $files; $this->defaultPath = $defaultPath; } public function load($environment, $group, $namespace = null) { $items = array(); $path = $this->getPath($namespace); if (is_null($path)) { return $items; } $file = "{$path}/{$group}.php"; if ($this->files->exists($file)) { $items = $this->getRequire($file); } $file = "{$path}/{$environment}/{$group}.php"; if ($this->files->exists($file)) { $items = $this->mergeEnvironment($items, $file); } return $items; } protected function mergeEnvironment(array $items, $file) { return array_replace_recursive($items, $this->getRequire($file)); } public function exists($group, $namespace = null) { $key = $group . $namespace; if (isset($this->exists[$key])) { return $this->exists[$key]; } $path = $this->getPath($namespace); if (is_null($path)) { return $this->exists[$key] = false; } $file = "{$path}/{$group}.php"; $exists = $this->files->exists($file); return $this->exists[$key] = $exists; } public function cascadePackage($env, $package, $group, $items) { $file = "packages/{$package}/{$group}.php"; if ($this->files->exists($path = $this->defaultPath . '/' . $file)) { $items = array_merge($items, $this->getRequire($path)); } $path = $this->getPackagePath($env, $package, $group); if ($this->files->exists($path)) { $items = array_merge($items, $this->getRequire($path)); } return $items; } protected function getPackagePath($env, $package, $group) { $file = "packages/{$package}/{$env}/{$group}.php"; return $this->defaultPath . '/' . $file; } protected function getPath($namespace) { if (is_null($namespace)) { return $this->defaultPath; } elseif (isset($this->hints[$namespace])) { return $this->hints[$namespace]; } } public function addNamespace($namespace, $hint) { $this->hints[$namespace] = $hint; } public function getNamespaces() { return $this->hints; } protected function getRequire($path) { return $this->files->getRequire($path); } public function getFilesystem() { return $this->files; } } namespace Illuminate\Config; interface LoaderInterface { public function load($environment, $group, $namespace = null); public function exists($group, $namespace = null); public function addNamespace($namespace, $hint); public function getNamespaces(); public function cascadePackage($environment, $package, $group, $items); } namespace Illuminate\Config; interface EnvironmentVariablesLoaderInterface { public function load($environment = null); } namespace Illuminate\Config; use Illuminate\Filesystem\Filesystem; class FileEnvironmentVariablesLoader implements EnvironmentVariablesLoaderInterface { protected $files; protected $path; public function __construct(Filesystem $files, $path = null) { $this->files = $files; $this->path = $path ?: base_path(); } public function load($environment = null) { if ($environment == 'production') { $environment = null; } if (!$this->files->exists($path = $this->getFile($environment))) { return array(); } return array_dot($this->files->getRequire($path)); } protected function getFile($environment) { if ($environment) { return $this->path . '/.env.' . $environment . '.php'; } return $this->path . '/.env.php'; } } namespace Illuminate\Config; class EnvironmentVariables { protected $loader; public function __construct(EnvironmentVariablesLoaderInterface $loader) { $this->loader = $loader; } public function load($environment = null) { foreach ($this->loader->load($environment) as $key => $value) { $_ENV[$key] = $value; $_SERVER[$key] = $value; putenv("{$key}={$value}"); } } } namespace Illuminate\Filesystem; use FilesystemIterator; use Symfony\Component\Finder\Finder; class Filesystem { public function exists($path) { return file_exists($path); } public function get($path) { if ($this->isFile($path)) { return file_get_contents($path); } throw new FileNotFoundException("File does not exist at path {$path}"); } public function getRequire($path) { if ($this->isFile($path)) { return require $path; } throw new FileNotFoundException("File does not exist at path {$path}"); } public function requireOnce($file) { require_once $file; } public function put($path, $contents, $lock = false) { return file_put_contents($path, $contents, $lock ? LOCK_EX : 0); } public function prepend($path, $data) { if ($this->exists($path)) { return $this->put($path, $data . $this->get($path)); } return $this->put($path, $data); } public function append($path, $data) { return file_put_contents($path, $data, FILE_APPEND); } public function delete($paths) { $paths = is_array($paths) ? $paths : func_get_args(); $success = true; foreach ($paths as $path) { if (!@unlink($path)) { $success = false; } } return $success; } public function move($path, $target) { return rename($path, $target); } public function copy($path, $target) { return copy($path, $target); } public function name($path) { return pathinfo($path, PATHINFO_FILENAME); } public function extension($path) { return pathinfo($path, PATHINFO_EXTENSION); } public function type($path) { return filetype($path); } public function size($path) { return filesize($path); } public function lastModified($path) { return filemtime($path); } public function isDirectory($directory) { return is_dir($directory); } public function isWritable($path) { return is_writable($path); } public function isFile($file) { return is_file($file); } public function glob($pattern, $flags = 0) { return glob($pattern, $flags); } public function files($directory) { $glob = glob($directory . '/*'); if ($glob === false) { return array(); } return array_filter($glob, function ($file) { return filetype($file) == 'file'; }); } public function allFiles($directory) { return iterator_to_array(Finder::create()->files()->in($directory), false); } public function directories($directory) { $directories = array(); foreach (Finder::create()->in($directory)->directories()->depth(0) as $dir) { $directories[] = $dir->getPathname(); } return $directories; } public function makeDirectory($path, $mode = 493, $recursive = false, $force = false) { if ($force) { return @mkdir($path, $mode, $recursive); } return mkdir($path, $mode, $recursive); } public function copyDirectory($directory, $destination, $options = null) { if (!$this->isDirectory($directory)) { return false; } $options = $options ?: FilesystemIterator::SKIP_DOTS; if (!$this->isDirectory($destination)) { $this->makeDirectory($destination, 511, true); } $items = new FilesystemIterator($directory, $options); foreach ($items as $item) { $target = $destination . '/' . $item->getBasename(); if ($item->isDir()) { $path = $item->getPathname(); if (!$this->copyDirectory($path, $target, $options)) { return false; } } else { if (!$this->copy($item->getPathname(), $target)) { return false; } } } return true; } public function deleteDirectory($directory, $preserve = false) { if (!$this->isDirectory($directory)) { return false; } $items = new FilesystemIterator($directory); foreach ($items as $item) { if ($item->isDir()) { $this->deleteDirectory($item->getPathname()); } else { $this->delete($item->getPathname()); } } if (!$preserve) { @rmdir($directory); } return true; } public function cleanDirectory($directory) { return $this->deleteDirectory($directory, true); } } namespace Illuminate\Foundation; class AliasLoader { protected $aliases; protected $registered = false; protected static $instance; public function __construct(array $aliases = array()) { $this->aliases = $aliases; } public static function getInstance(array $aliases = array()) { if (is_null(static::$instance)) { return static::$instance = new static($aliases); } $aliases = array_merge(static::$instance->getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; } public function load($alias) { if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } } public function alias($class, $alias) { $this->aliases[$class] = $alias; } public function register() { if (!$this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } protected function prependToLoaderStack() { spl_autoload_register(array($this, 'load'), true, true); } public function getAliases() { return $this->aliases; } public function setAliases(array $aliases) { $this->aliases = $aliases; } public function isRegistered() { return $this->registered; } public function setRegistered($value) { $this->registered = $value; } public static function setInstance($loader) { static::$instance = $loader; } } namespace Illuminate\Foundation; use Illuminate\Filesystem\Filesystem; class ProviderRepository { protected $files; protected $manifestPath; protected $default = array('when' => array()); public function __construct(Filesystem $files, $manifestPath) { $this->files = $files; $this->manifestPath = $manifestPath; } public function load(Application $app, array $providers) { $manifest = $this->loadManifest(); if ($this->shouldRecompile($manifest, $providers)) { $manifest = $this->compileManifest($app, $providers); } if ($app->runningInConsole()) { $manifest['eager'] = $manifest['providers']; } foreach ($manifest['when'] as $provider => $events) { $this->registerLoadEvents($app, $provider, $events); } foreach ($manifest['eager'] as $provider) { $app->register($this->createProvider($app, $provider)); } $app->setDeferredServices($manifest['deferred']); } protected function registerLoadEvents(Application $app, $provider, array $events) { if (count($events) < 1) { return; } $app->make('events')->listen($events, function () use($app, $provider) { $app->register($provider); }); } protected function compileManifest(Application $app, $providers) { $manifest = $this->freshManifest($providers); foreach ($providers as $provider) { $instance = $this->createProvider($app, $provider); if ($instance->isDeferred()) { foreach ($instance->provides() as $service) { $manifest['deferred'][$service] = $provider; } $manifest['when'][$provider] = $instance->when(); } else { $manifest['eager'][] = $provider; } } return $this->writeManifest($manifest); } public function createProvider(Application $app, $provider) { return new $provider($app); } public function shouldRecompile($manifest, $providers) { return is_null($manifest) || $manifest['providers'] != $providers; } public function loadManifest() { $path = $this->manifestPath . '/services.json'; if ($this->files->exists($path)) { $manifest = json_decode($this->files->get($path), true); return array_merge($this->default, $manifest); } } public function writeManifest($manifest) { $path = $this->manifestPath . '/services.json'; $this->files->put($path, json_encode($manifest, JSON_PRETTY_PRINT)); return $manifest; } protected function freshManifest(array $providers) { list($eager, $deferred) = array(array(), array()); return compact('providers', 'eager', 'deferred'); } public function getFilesystem() { return $this->files; } } namespace Illuminate\Cookie; use Illuminate\Support\ServiceProvider; class CookieServiceProvider extends ServiceProvider { public function register() { $this->app->bindShared('cookie', function ($app) { $config = $app['config']['session']; return (new CookieJar())->setDefaultPathAndDomain($config['path'], $config['domain']); }); } } namespace Illuminate\Database; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\ServiceProvider; use Illuminate\Database\Connectors\ConnectionFactory; class DatabaseServiceProvider extends ServiceProvider { public function boot() { Model::setConnectionResolver($this->app['db']); Model::setEventDispatcher($this->app['events']); } public function register() { $this->app->bindShared('db.factory', function ($app) { return new ConnectionFactory($app); }); $this->app->bindShared('db', function ($app) { return new DatabaseManager($app, $app['db.factory']); }); } } namespace Illuminate\Encryption; use Illuminate\Support\ServiceProvider; class EncryptionServiceProvider extends ServiceProvider { public function register() { $this->app->bindShared('encrypter', function ($app) { $encrypter = new Encrypter($app['config']['app.key']); if ($app['config']->has('app.cipher')) { $encrypter->setCipher($app['config']['app.cipher']); } return $encrypter; }); } } namespace Illuminate\Filesystem; use Illuminate\Support\ServiceProvider; class FilesystemServiceProvider extends ServiceProvider { public function register() { $this->app->bindShared('files', function () { return new Filesystem(); }); } } namespace Illuminate\Session; use Illuminate\Support\ServiceProvider; class SessionServiceProvider extends ServiceProvider { public function register() { $this->setupDefaultDriver(); $this->registerSessionManager(); $this->registerSessionDriver(); } protected function setupDefaultDriver() { if ($this->app->runningInConsole()) { $this->app['config']['session.driver'] = 'array'; } } protected function registerSessionManager() { $this->app->bindShared('session', function ($app) { return new SessionManager($app); }); } protected function registerSessionDriver() { $this->app->bindShared('session.store', function ($app) { $manager = $app['session']; return $manager->driver(); }); } } namespace Illuminate\View; use Illuminate\Support\ViewErrorBag; use Illuminate\View\Engines\PhpEngine; use Illuminate\Support\ServiceProvider; use Illuminate\View\Engines\CompilerEngine; use Illuminate\View\Engines\EngineResolver; use Illuminate\View\Compilers\BladeCompiler; class ViewServiceProvider extends ServiceProvider { public function register() { $this->registerEngineResolver(); $this->registerViewFinder(); $this->registerFactory(); $this->registerSessionBinder(); } public function registerEngineResolver() { $this->app->bindShared('view.engine.resolver', function () { $resolver = new EngineResolver(); foreach (array('php', 'blade') as $engine) { $this->{'register' . ucfirst($engine) . 'Engine'}($resolver); } return $resolver; }); } public function registerPhpEngine($resolver) { $resolver->register('php', function () { return new PhpEngine(); }); } public function registerBladeEngine($resolver) { $app = $this->app; $app->bindShared('blade.compiler', function ($app) { $cache = $app['path.storage'] . '/views'; return new BladeCompiler($app['files'], $cache); }); $resolver->register('blade', function () use($app) { return new CompilerEngine($app['blade.compiler'], $app['files']); }); } public function registerViewFinder() { $this->app->bindShared('view.finder', function ($app) { $paths = $app['config']['view.paths']; return new FileViewFinder($app['files'], $paths); }); } public function registerFactory() { $this->app->bindShared('view', function ($app) { $resolver = $app['view.engine.resolver']; $finder = $app['view.finder']; $env = new Factory($resolver, $finder, $app['events']); $env->setContainer($app); $env->share('app', $app); return $env; }); } protected function registerSessionBinder() { list($app, $me) = array($this->app, $this); $app->booted(function () use($app, $me) { if ($me->sessionHasErrors($app)) { $errors = $app['session.store']->get('errors'); $app['view']->share('errors', $errors); } else { $app['view']->share('errors', new ViewErrorBag()); } }); } public function sessionHasErrors($app) { $config = $app['config']['session']; if (isset($app['session.store']) && !is_null($config['driver'])) { return $app['session.store']->has('errors'); } } } namespace Illuminate\Routing; interface RouteFiltererInterface { public function filter($name, $callback); public function callRouteFilter($filter, $parameters, $route, $request, $response = null); } namespace Illuminate\Routing; use Closure; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Events\Dispatcher; use Illuminate\Container\Container; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class Router implements HttpKernelInterface, RouteFiltererInterface { protected $events; protected $container; protected $routes; protected $current; protected $currentRequest; protected $controllerDispatcher; protected $inspector; protected $filtering = true; protected $patternFilters = array(); protected $regexFilters = array(); protected $binders = array(); protected $patterns = array(); protected $groupStack = array(); public static $verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'); protected $resourceDefaults = array('index', 'create', 'store', 'show', 'edit', 'update', 'destroy'); public function __construct(Dispatcher $events, Container $container = null) { $this->events = $events; $this->routes = new RouteCollection(); $this->container = $container ?: new Container(); $this->bind('_missing', function ($v) { return explode('/', $v); }); } public function get($uri, $action) { return $this->addRoute(array('GET', 'HEAD'), $uri, $action); } public function post($uri, $action) { return $this->addRoute('POST', $uri, $action); } public function put($uri, $action) { return $this->addRoute('PUT', $uri, $action); } public function patch($uri, $action) { return $this->addRoute('PATCH', $uri, $action); } public function delete($uri, $action) { return $this->addRoute('DELETE', $uri, $action); } public function options($uri, $action) { return $this->addRoute('OPTIONS', $uri, $action); } public function any($uri, $action) { $verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'); return $this->addRoute($verbs, $uri, $action); } public function match($methods, $uri, $action) { return $this->addRoute(array_map('strtoupper', (array) $methods), $uri, $action); } public function controllers(array $controllers) { foreach ($controllers as $uri => $name) { $this->controller($uri, $name); } } public function controller($uri, $controller, $names = array()) { $prepended = $controller; if (!empty($this->groupStack)) { $prepended = $this->prependGroupUses($controller); } $routable = $this->getInspector()->getRoutable($prepended, $uri); foreach ($routable as $method => $routes) { foreach ($routes as $route) { $this->registerInspected($route, $controller, $method, $names); } } $this->addFallthroughRoute($controller, $uri); } protected function registerInspected($route, $controller, $method, &$names) { $action = array('uses' => $controller . '@' . $method); $action['as'] = array_get($names, $method); $this->{$route['verb']}($route['uri'], $action); } protected function addFallthroughRoute($controller, $uri) { $missing = $this->any($uri . '/{_missing}', $controller . '@missingMethod'); $missing->where('_missing', '(.*)'); } public function resource($name, $controller, array $options = array()) { if (str_contains($name, '/')) { $this->prefixedResource($name, $controller, $options); return; } $base = $this->getResourceWildcard(last(explode('.', $name))); $defaults = $this->resourceDefaults; foreach ($this->getResourceMethods($defaults, $options) as $m) { $this->{'addResource' . ucfirst($m)}($name, $base, $controller, $options); } } protected function prefixedResource($name, $controller, array $options) { list($name, $prefix) = $this->getResourcePrefix($name); $callback = function ($me) use($name, $controller, $options) { $me->resource($name, $controller, $options); }; return $this->group(compact('prefix'), $callback); } protected function getResourcePrefix($name) { $segments = explode('/', $name); $prefix = implode('/', array_slice($segments, 0, -1)); return array(end($segments), $prefix); } protected function getResourceMethods($defaults, $options) { if (isset($options['only'])) { return array_intersect($defaults, (array) $options['only']); } elseif (isset($options['except'])) { return array_diff($defaults, (array) $options['except']); } return $defaults; } public function getResourceUri($resource) { if (!str_contains($resource, '.')) { return $resource; } $segments = explode('.', $resource); $uri = $this->getNestedResourceUri($segments); return str_replace('/{' . $this->getResourceWildcard(last($segments)) . '}', '', $uri); } protected function getNestedResourceUri(array $segments) { return implode('/', array_map(function ($s) { return $s . '/{' . $this->getResourceWildcard($s) . '}'; }, $segments)); } protected function getResourceAction($resource, $controller, $method, $options) { $name = $this->getResourceName($resource, $method, $options); return array('as' => $name, 'uses' => $controller . '@' . $method); } protected function getResourceName($resource, $method, $options) { if (isset($options['names'][$method])) { return $options['names'][$method]; } $prefix = isset($options['as']) ? $options['as'] . '.' : ''; if (empty($this->groupStack)) { return $prefix . $resource . '.' . $method; } return $this->getGroupResourceName($prefix, $resource, $method); } protected function getGroupResourceName($prefix, $resource, $method) { $group = str_replace('/', '.', $this->getLastGroupPrefix()); if (empty($group)) { return trim("{$prefix}{$resource}.{$method}", '.'); } return trim("{$prefix}{$group}.{$resource}.{$method}", '.'); } public function getResourceWildcard($value) { return str_replace('-', '_', $value); } protected function addResourceIndex($name, $base, $controller, $options) { $uri = $this->getResourceUri($name); $action = $this->getResourceAction($name, $controller, 'index', $options); return $this->get($uri, $action); } protected function addResourceCreate($name, $base, $controller, $options) { $uri = $this->getResourceUri($name) . '/create'; $action = $this->getResourceAction($name, $controller, 'create', $options); return $this->get($uri, $action); } protected function addResourceStore($name, $base, $controller, $options) { $uri = $this->getResourceUri($name); $action = $this->getResourceAction($name, $controller, 'store', $options); return $this->post($uri, $action); } protected function addResourceShow($name, $base, $controller, $options) { $uri = $this->getResourceUri($name) . '/{' . $base . '}'; $action = $this->getResourceAction($name, $controller, 'show', $options); return $this->get($uri, $action); } protected function addResourceEdit($name, $base, $controller, $options) { $uri = $this->getResourceUri($name) . '/{' . $base . '}/edit'; $action = $this->getResourceAction($name, $controller, 'edit', $options); return $this->get($uri, $action); } protected function addResourceUpdate($name, $base, $controller, $options) { $this->addPutResourceUpdate($name, $base, $controller, $options); return $this->addPatchResourceUpdate($name, $base, $controller); } protected function addPutResourceUpdate($name, $base, $controller, $options) { $uri = $this->getResourceUri($name) . '/{' . $base . '}'; $action = $this->getResourceAction($name, $controller, 'update', $options); return $this->put($uri, $action); } protected function addPatchResourceUpdate($name, $base, $controller) { $uri = $this->getResourceUri($name) . '/{' . $base . '}'; $this->patch($uri, $controller . '@update'); } protected function addResourceDestroy($name, $base, $controller, $options) { $uri = $this->getResourceUri($name) . '/{' . $base . '}'; $action = $this->getResourceAction($name, $controller, 'destroy', $options); return $this->delete($uri, $action); } public function group(array $attributes, Closure $callback) { $this->updateGroupStack($attributes); call_user_func($callback, $this); array_pop($this->groupStack); } protected function updateGroupStack(array $attributes) { if (!empty($this->groupStack)) { $attributes = $this->mergeGroup($attributes, last($this->groupStack)); } $this->groupStack[] = $attributes; } public function mergeWithLastGroup($new) { return $this->mergeGroup($new, last($this->groupStack)); } public static function mergeGroup($new, $old) { $new['namespace'] = static::formatUsesPrefix($new, $old); $new['prefix'] = static::formatGroupPrefix($new, $old); if (isset($new['domain'])) { unset($old['domain']); } $new['where'] = array_merge(array_get($old, 'where', array()), array_get($new, 'where', array())); return array_merge_recursive(array_except($old, array('namespace', 'prefix', 'where')), $new); } protected static function formatUsesPrefix($new, $old) { if (isset($new['namespace']) && isset($old['namespace'])) { return trim(array_get($old, 'namespace'), '\\') . '\\' . trim($new['namespace'], '\\'); } elseif (isset($new['namespace'])) { return trim($new['namespace'], '\\'); } return array_get($old, 'namespace'); } protected static function formatGroupPrefix($new, $old) { if (isset($new['prefix'])) { return trim(array_get($old, 'prefix'), '/') . '/' . trim($new['prefix'], '/'); } return array_get($old, 'prefix'); } protected function getLastGroupPrefix() { if (!empty($this->groupStack)) { $last = end($this->groupStack); return isset($last['prefix']) ? $last['prefix'] : ''; } return ''; } protected function addRoute($methods, $uri, $action) { return $this->routes->add($this->createRoute($methods, $uri, $action)); } protected function createRoute($methods, $uri, $action) { if ($this->routingToController($action)) { $action = $this->getControllerAction($action); } $route = $this->newRoute($methods, $uri = $this->prefix($uri), $action); if (!empty($this->groupStack)) { $this->mergeController($route); } $this->addWhereClausesToRoute($route); return $route; } protected function newRoute($methods, $uri, $action) { return new Route($methods, $uri, $action); } protected function prefix($uri) { return trim(trim($this->getLastGroupPrefix(), '/') . '/' . trim($uri, '/'), '/') ?: '/'; } protected function addWhereClausesToRoute($route) { $route->where(array_merge($this->patterns, array_get($route->getAction(), 'where', array()))); return $route; } protected function mergeController($route) { $action = $this->mergeWithLastGroup($route->getAction()); $route->setAction($action); } protected function routingToController($action) { if ($action instanceof Closure) { return false; } return is_string($action) || is_string(array_get($action, 'uses')); } protected function getControllerAction($action) { if (is_string($action)) { $action = array('uses' => $action); } if (!empty($this->groupStack)) { $action['uses'] = $this->prependGroupUses($action['uses']); } $action['controller'] = $action['uses']; $closure = $this->getClassClosure($action['uses']); return array_set($action, 'uses', $closure); } protected function getClassClosure($controller) { $d = $this->getControllerDispatcher(); return function () use($d, $controller) { $route = $this->current(); $request = $this->getCurrentRequest(); list($class, $method) = explode('@', $controller); return $d->dispatch($route, $request, $class, $method); }; } protected function prependGroupUses($uses) { $group = last($this->groupStack); return isset($group['namespace']) ? $group['namespace'] . '\\' . $uses : $uses; } public function dispatch(Request $request) { $this->currentRequest = $request; $response = $this->callFilter('before', $request); if (is_null($response)) { $response = $this->dispatchToRoute($request); } $response = $this->prepareResponse($request, $response); $this->callFilter('after', $request, $response); return $response; } public function dispatchToRoute(Request $request) { $route = $this->findRoute($request); $this->events->fire('router.matched', array($route, $request)); $response = $this->callRouteBefore($route, $request); if (is_null($response)) { $response = $route->run($request); } $response = $this->prepareResponse($request, $response); $this->callRouteAfter($route, $request, $response); return $response; } protected function findRoute($request) { $this->current = $route = $this->routes->match($request); return $this->substituteBindings($route); } protected function substituteBindings($route) { foreach ($route->parameters() as $key => $value) { if (isset($this->binders[$key])) { $route->setParameter($key, $this->performBinding($key, $value, $route)); } } return $route; } protected function performBinding($key, $value, $route) { return call_user_func($this->binders[$key], $value, $route); } public function matched($callback) { $this->events->listen('router.matched', $callback); } public function before($callback) { $this->addGlobalFilter('before', $callback); } public function after($callback) { $this->addGlobalFilter('after', $callback); } protected function addGlobalFilter($filter, $callback) { $this->events->listen('router.' . $filter, $this->parseFilter($callback)); } public function filter($name, $callback) { $this->events->listen('router.filter: ' . $name, $this->parseFilter($callback)); } protected function parseFilter($callback) { if (is_string($callback) && !str_contains($callback, '@')) { return $callback . '@filter'; } return $callback; } public function when($pattern, $name, $methods = null) { if (!is_null($methods)) { $methods = array_map('strtoupper', (array) $methods); } $this->patternFilters[$pattern][] = compact('name', 'methods'); } public function whenRegex($pattern, $name, $methods = null) { if (!is_null($methods)) { $methods = array_map('strtoupper', (array) $methods); } $this->regexFilters[$pattern][] = compact('name', 'methods'); } public function model($key, $class, Closure $callback = null) { $this->bind($key, function ($value) use($class, $callback) { if (is_null($value)) { return null; } if ($model = (new $class())->find($value)) { return $model; } if ($callback instanceof Closure) { return call_user_func($callback); } throw new NotFoundHttpException(); }); } public function bind($key, $binder) { if (is_string($binder)) { $binder = $this->createClassBinding($binder); } $this->binders[str_replace('-', '_', $key)] = $binder; } public function createClassBinding($binding) { return function ($value, $route) use($binding) { $segments = explode('@', $binding); $method = count($segments) == 2 ? $segments[1] : 'bind'; $callable = array($this->container->make($segments[0]), $method); return call_user_func($callable, $value, $route); }; } public function pattern($key, $pattern) { $this->patterns[$key] = $pattern; } public function patterns($patterns) { foreach ($patterns as $key => $pattern) { $this->pattern($key, $pattern); } } protected function callFilter($filter, $request, $response = null) { if (!$this->filtering) { return null; } return $this->events->until('router.' . $filter, array($request, $response)); } public function callRouteBefore($route, $request) { $response = $this->callPatternFilters($route, $request); return $response ?: $this->callAttachedBefores($route, $request); } protected function callPatternFilters($route, $request) { foreach ($this->findPatternFilters($request) as $filter => $parameters) { $response = $this->callRouteFilter($filter, $parameters, $route, $request); if (!is_null($response)) { return $response; } } } public function findPatternFilters($request) { $results = array(); list($path, $method) = array($request->path(), $request->getMethod()); foreach ($this->patternFilters as $pattern => $filters) { if (str_is($pattern, $path)) { $merge = $this->patternsByMethod($method, $filters); $results = array_merge($results, $merge); } } foreach ($this->regexFilters as $pattern => $filters) { if (preg_match($pattern, $path)) { $merge = $this->patternsByMethod($method, $filters); $results = array_merge($results, $merge); } } return $results; } protected function patternsByMethod($method, $filters) { $results = array(); foreach ($filters as $filter) { if ($this->filterSupportsMethod($filter, $method)) { $parsed = Route::parseFilters($filter['name']); $results = array_merge($results, $parsed); } } return $results; } protected function filterSupportsMethod($filter, $method) { $methods = $filter['methods']; return is_null($methods) || in_array($method, $methods); } protected function callAttachedBefores($route, $request) { foreach ($route->beforeFilters() as $filter => $parameters) { $response = $this->callRouteFilter($filter, $parameters, $route, $request); if (!is_null($response)) { return $response; } } } public function callRouteAfter($route, $request, $response) { foreach ($route->afterFilters() as $filter => $parameters) { $this->callRouteFilter($filter, $parameters, $route, $request, $response); } } public function callRouteFilter($filter, $parameters, $route, $request, $response = null) { if (!$this->filtering) { return null; } $data = array_merge(array($route, $request, $response), $parameters); return $this->events->until('router.filter: ' . $filter, $this->cleanFilterParameters($data)); } protected function cleanFilterParameters(array $parameters) { return array_filter($parameters, function ($p) { return !is_null($p) && $p !== ''; }); } protected function prepareResponse($request, $response) { if (!$response instanceof SymfonyResponse) { $response = new Response($response); } return $response->prepare($request); } public function withoutFilters(callable $callback) { $this->disableFilters(); call_user_func($callback); $this->enableFilters(); } public function enableFilters() { $this->filtering = true; } public function disableFilters() { $this->filtering = false; } public function input($key, $default = null) { return $this->current()->parameter($key, $default); } public function getCurrentRoute() { return $this->current(); } public function current() { return $this->current; } public function has($name) { return $this->routes->hasNamedRoute($name); } public function currentRouteName() { return $this->current() ? $this->current()->getName() : null; } public function is() { foreach (func_get_args() as $pattern) { if (str_is($pattern, $this->currentRouteName())) { return true; } } return false; } public function currentRouteNamed($name) { return $this->current() ? $this->current()->getName() == $name : false; } public function currentRouteAction() { if (!$this->current()) { return; } $action = $this->current()->getAction(); return isset($action['controller']) ? $action['controller'] : null; } public function uses() { foreach (func_get_args() as $pattern) { if (str_is($pattern, $this->currentRouteAction())) { return true; } } return false; } public function currentRouteUses($action) { return $this->currentRouteAction() == $action; } public function getCurrentRequest() { return $this->currentRequest; } public function getRoutes() { return $this->routes; } public function getControllerDispatcher() { if (is_null($this->controllerDispatcher)) { $this->controllerDispatcher = new ControllerDispatcher($this, $this->container); } return $this->controllerDispatcher; } public function setControllerDispatcher(ControllerDispatcher $dispatcher) { $this->controllerDispatcher = $dispatcher; } public function getInspector() { return $this->inspector ?: ($this->inspector = new ControllerInspector()); } public function getPatterns() { return $this->patterns; } public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { return $this->dispatch(Request::createFromBase($request)); } } namespace Illuminate\Routing; use Illuminate\Http\Request; use Illuminate\Routing\Matching\UriValidator; use Illuminate\Routing\Matching\HostValidator; use Illuminate\Routing\Matching\MethodValidator; use Illuminate\Routing\Matching\SchemeValidator; use Symfony\Component\Routing\Route as SymfonyRoute; class Route { protected $uri; protected $methods; protected $action; protected $defaults = array(); protected $wheres = array(); protected $parameters; protected $parameterNames; protected $compiled; protected static $validators; public function __construct($methods, $uri, $action) { $this->uri = $uri; $this->methods = (array) $methods; $this->action = $this->parseAction($action); if (in_array('GET', $this->methods) && !in_array('HEAD', $this->methods)) { $this->methods[] = 'HEAD'; } if (isset($this->action['prefix'])) { $this->prefix($this->action['prefix']); } } public function run() { $parameters = array_filter($this->parameters(), function ($p) { return isset($p); }); return call_user_func_array($this->action['uses'], $parameters); } public function matches(Request $request, $includingMethod = true) { $this->compileRoute(); foreach ($this->getValidators() as $validator) { if (!$includingMethod && $validator instanceof MethodValidator) { continue; } if (!$validator->matches($this, $request)) { return false; } } return true; } protected function compileRoute() { $optionals = $this->extractOptionalParameters(); $uri = preg_replace('/\\{(\\w+?)\\?\\}/', '{$1}', $this->uri); $this->compiled = with(new SymfonyRoute($uri, $optionals, $this->wheres, array(), $this->domain() ?: ''))->compile(); } protected function extractOptionalParameters() { preg_match_all('/\\{(\\w+?)\\?\\}/', $this->uri, $matches); return isset($matches[1]) ? array_fill_keys($matches[1], null) : array(); } public function beforeFilters() { if (!isset($this->action['before'])) { return array(); } return $this->parseFilters($this->action['before']); } public function afterFilters() { if (!isset($this->action['after'])) { return array(); } return $this->parseFilters($this->action['after']); } public static function parseFilters($filters) { return array_build(static::explodeFilters($filters), function ($key, $value) { return Route::parseFilter($value); }); } protected static function explodeFilters($filters) { if (is_array($filters)) { return static::explodeArrayFilters($filters); } return array_map('trim', explode('|', $filters)); } protected static function explodeArrayFilters(array $filters) { $results = array(); foreach ($filters as $filter) { $results = array_merge($results, array_map('trim', explode('|', $filter))); } return $results; } public static function parseFilter($filter) { if (!str_contains($filter, ':')) { return array($filter, array()); } return static::parseParameterFilter($filter); } protected static function parseParameterFilter($filter) { list($name, $parameters) = explode(':', $filter, 2); return array($name, explode(',', $parameters)); } public function getParameter($name, $default = null) { return $this->parameter($name, $default); } public function parameter($name, $default = null) { return array_get($this->parameters(), $name, $default); } public function setParameter($name, $value) { $this->parameters(); $this->parameters[$name] = $value; } public function forgetParameter($name) { $this->parameters(); unset($this->parameters[$name]); } public function parameters() { if (isset($this->parameters)) { return array_map(function ($value) { return is_string($value) ? rawurldecode($value) : $value; }, $this->parameters); } throw new \LogicException('Route is not bound.'); } public function parametersWithoutNulls() { return array_filter($this->parameters(), function ($p) { return !is_null($p); }); } public function parameterNames() { if (isset($this->parameterNames)) { return $this->parameterNames; } return $this->parameterNames = $this->compileParameterNames(); } protected function compileParameterNames() { preg_match_all('/\\{(.*?)\\}/', $this->domain() . $this->uri, $matches); return array_map(function ($m) { return trim($m, '?'); }, $matches[1]); } public function bind(Request $request) { $this->compileRoute(); $this->bindParameters($request); return $this; } public function bindParameters(Request $request) { $params = $this->matchToKeys(array_slice($this->bindPathParameters($request), 1)); if (!is_null($this->compiled->getHostRegex())) { $params = $this->bindHostParameters($request, $params); } return $this->parameters = $this->replaceDefaults($params); } protected function bindPathParameters(Request $request) { preg_match($this->compiled->getRegex(), '/' . $request->decodedPath(), $matches); return $matches; } protected function bindHostParameters(Request $request, $parameters) { preg_match($this->compiled->getHostRegex(), $request->getHost(), $matches); return array_merge($this->matchToKeys(array_slice($matches, 1)), $parameters); } protected function matchToKeys(array $matches) { if (count($this->parameterNames()) == 0) { return array(); } $parameters = array_intersect_key($matches, array_flip($this->parameterNames())); return array_filter($parameters, function ($value) { return is_string($value) && strlen($value) > 0; }); } protected function replaceDefaults(array $parameters) { foreach ($parameters as $key => &$value) { $value = isset($value) ? $value : array_get($this->defaults, $key); } return $parameters; } protected function parseAction($action) { if (is_callable($action)) { return array('uses' => $action); } elseif (!isset($action['uses'])) { $action['uses'] = $this->findClosure($action); } return $action; } protected function findClosure(array $action) { return array_first($action, function ($key, $value) { return is_callable($value); }); } public static function getValidators() { if (isset(static::$validators)) { return static::$validators; } return static::$validators = array(new MethodValidator(), new SchemeValidator(), new HostValidator(), new UriValidator()); } public function before($filters) { return $this->addFilters('before', $filters); } public function after($filters) { return $this->addFilters('after', $filters); } protected function addFilters($type, $filters) { $filters = static::explodeFilters($filters); if (isset($this->action[$type])) { $existing = static::explodeFilters($this->action[$type]); $this->action[$type] = array_merge($existing, $filters); } else { $this->action[$type] = $filters; } return $this; } public function defaults($key, $value) { $this->defaults[$key] = $value; return $this; } public function where($name, $expression = null) { foreach ($this->parseWhere($name, $expression) as $name => $expression) { $this->wheres[$name] = $expression; } return $this; } protected function parseWhere($name, $expression) { return is_array($name) ? $name : array($name => $expression); } protected function whereArray(array $wheres) { foreach ($wheres as $name => $expression) { $this->where($name, $expression); } return $this; } public function prefix($prefix) { $this->uri = trim($prefix, '/') . '/' . trim($this->uri, '/'); return $this; } public function getPath() { return $this->uri(); } public function uri() { return $this->uri; } public function getMethods() { return $this->methods(); } public function methods() { return $this->methods; } public function httpOnly() { return in_array('http', $this->action, true); } public function httpsOnly() { return $this->secure(); } public function secure() { return in_array('https', $this->action, true); } public function domain() { return isset($this->action['domain']) ? $this->action['domain'] : null; } public function getUri() { return $this->uri; } public function setUri($uri) { $this->uri = $uri; return $this; } public function getPrefix() { return isset($this->action['prefix']) ? $this->action['prefix'] : null; } public function getName() { return isset($this->action['as']) ? $this->action['as'] : null; } public function getActionName() { return isset($this->action['controller']) ? $this->action['controller'] : 'Closure'; } public function getAction() { return $this->action; } public function setAction(array $action) { $this->action = $action; return $this; } public function getCompiled() { return $this->compiled; } } namespace Illuminate\Routing; use Countable; use ArrayIterator; use IteratorAggregate; use Illuminate\Http\Request; use Illuminate\Http\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; class RouteCollection implements Countable, IteratorAggregate { protected $routes = array(); protected $allRoutes = array(); protected $nameList = array(); protected $actionList = array(); public function add(Route $route) { $this->addToCollections($route); $this->addLookups($route); return $route; } protected function addToCollections($route) { $domainAndUri = $route->domain() . $route->getUri(); foreach ($route->methods() as $method) { $this->routes[$method][$domainAndUri] = $route; } $this->allRoutes[$method . $domainAndUri] = $route; } protected function addLookups($route) { $action = $route->getAction(); if (isset($action['as'])) { $this->nameList[$action['as']] = $route; } if (isset($action['controller'])) { $this->addToActionList($action, $route); } } protected function addToActionList($action, $route) { if (!isset($this->actionList[$action['controller']])) { $this->actionList[$action['controller']] = $route; } } public function match(Request $request) { $routes = $this->get($request->getMethod()); $route = $this->check($routes, $request); if (!is_null($route)) { return $route->bind($request); } $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getOtherMethodsRoute($request, $others); } throw new NotFoundHttpException(); } protected function checkForAlternateVerbs($request) { $methods = array_diff(Router::$verbs, array($request->getMethod())); $others = array(); foreach ($methods as $method) { if (!is_null($this->check($this->get($method), $request, false))) { $others[] = $method; } } return $others; } protected function getOtherMethodsRoute($request, array $others) { if ($request->method() == 'OPTIONS') { return (new Route('OPTIONS', $request->path(), function () use($others) { return new Response('', 200, array('Allow' => implode(',', $others))); }))->bind($request); } $this->methodNotAllowed($others); } protected function methodNotAllowed(array $others) { throw new MethodNotAllowedHttpException($others); } protected function check(array $routes, $request, $includingMethod = true) { return array_first($routes, function ($key, $value) use($request, $includingMethod) { return $value->matches($request, $includingMethod); }); } protected function get($method = null) { if (is_null($method)) { return $this->getRoutes(); } return array_get($this->routes, $method, array()); } public function hasNamedRoute($name) { return !is_null($this->getByName($name)); } public function getByName($name) { return isset($this->nameList[$name]) ? $this->nameList[$name] : null; } public function getByAction($action) { return isset($this->actionList[$action]) ? $this->actionList[$action] : null; } public function getRoutes() { return array_values($this->allRoutes); } public function getIterator() { return new ArrayIterator($this->getRoutes()); } public function count() { return count($this->getRoutes()); } } namespace Illuminate\Routing; use Closure; use Illuminate\Http\Request; use Illuminate\Container\Container; class ControllerDispatcher { protected $filterer; protected $container; public function __construct(RouteFiltererInterface $filterer, Container $container = null) { $this->filterer = $filterer; $this->container = $container; } public function dispatch(Route $route, Request $request, $controller, $method) { $instance = $this->makeController($controller); $this->assignAfter($instance, $route, $request, $method); $response = $this->before($instance, $route, $request, $method); if (is_null($response)) { $response = $this->call($instance, $route, $method); } return $response; } protected function makeController($controller) { Controller::setFilterer($this->filterer); return $this->container->make($controller); } protected function call($instance, $route, $method) { $parameters = $route->parametersWithoutNulls(); return $instance->callAction($method, $parameters); } protected function before($instance, $route, $request, $method) { foreach ($instance->getBeforeFilters() as $filter) { if ($this->filterApplies($filter, $request, $method)) { $response = $this->callFilter($filter, $route, $request); if (!is_null($response)) { return $response; } } } } protected function assignAfter($instance, $route, $request, $method) { foreach ($instance->getAfterFilters() as $filter) { if ($this->filterApplies($filter, $request, $method)) { $route->after($this->getAssignableAfter($filter)); } } } protected function getAssignableAfter($filter) { return $filter['original'] instanceof Closure ? $filter['filter'] : $filter['original']; } protected function filterApplies($filter, $request, $method) { foreach (array('Only', 'Except', 'On') as $type) { if ($this->{"filterFails{$type}"}($filter, $request, $method)) { return false; } } return true; } protected function filterFailsOnly($filter, $request, $method) { if (!isset($filter['options']['only'])) { return false; } return !in_array($method, (array) $filter['options']['only']); } protected function filterFailsExcept($filter, $request, $method) { if (!isset($filter['options']['except'])) { return false; } return in_array($method, (array) $filter['options']['except']); } protected function filterFailsOn($filter, $request, $method) { $on = array_get($filter, 'options.on'); if (is_null($on)) { return false; } if (is_string($on)) { $on = explode('|', $on); } return !in_array(strtolower($request->getMethod()), $on); } protected function callFilter($filter, $route, $request) { extract($filter); return $this->filterer->callRouteFilter($filter, $parameters, $route, $request); } } namespace Illuminate\Routing; use Illuminate\Http\Request; use InvalidArgumentException; class UrlGenerator { protected $routes; protected $request; protected $forcedRoot; protected $forceSchema; protected $dontEncode = array('%2F' => '/', '%40' => '@', '%3A' => ':', '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|'); public function __construct(RouteCollection $routes, Request $request) { $this->routes = $routes; $this->setRequest($request); } public function full() { return $this->request->fullUrl(); } public function current() { return $this->to($this->request->getPathInfo()); } public function previous() { return $this->to($this->request->headers->get('referer')); } public function to($path, $extra = array(), $secure = null) { if ($this->isValidUrl($path)) { return $path; } $scheme = $this->getScheme($secure); $tail = implode('/', array_map('rawurlencode', (array) $extra)); $root = $this->getRootUrl($scheme); return $this->trimUrl($root, $path, $tail); } public function secure($path, $parameters = array()) { return $this->to($path, $parameters, true); } public function asset($path, $secure = null) { if ($this->isValidUrl($path)) { return $path; } $root = $this->getRootUrl($this->getScheme($secure)); return $this->removeIndex($root) . '/' . trim($path, '/'); } protected function removeIndex($root) { $i = 'index.php'; return str_contains($root, $i) ? str_replace('/' . $i, '', $root) : $root; } public function secureAsset($path) { return $this->asset($path, true); } protected function getScheme($secure) { if (is_null($secure)) { return $this->forceSchema ?: $this->request->getScheme() . '://'; } return $secure ? 'https://' : 'http://'; } public function forceSchema($schema) { $this->forceSchema = $schema . '://'; } public function route($name, $parameters = array(), $absolute = true, $route = null) { $route = $route ?: $this->routes->getByName($name); $parameters = (array) $parameters; if (!is_null($route)) { return $this->toRoute($route, $parameters, $absolute); } throw new InvalidArgumentException("Route [{$name}] not defined."); } protected function toRoute($route, array $parameters, $absolute) { $domain = $this->getRouteDomain($route, $parameters); $uri = strtr(rawurlencode($this->trimUrl($root = $this->replaceRoot($route, $domain, $parameters), $this->replaceRouteParameters($route->uri(), $parameters))), $this->dontEncode) . $this->getRouteQueryString($parameters); return $absolute ? $uri : '/' . ltrim(str_replace($root, '', $uri), '/'); } protected function replaceRoot($route, $domain, &$parameters) { return $this->replaceRouteParameters($this->getRouteRoot($route, $domain), $parameters); } protected function replaceRouteParameters($path, array &$parameters) { if (count($parameters)) { $path = preg_replace_sub('/\\{.*?\\}/', $parameters, $this->replaceNamedParameters($path, $parameters)); } return trim(preg_replace('/\\{.*?\\?\\}/', '', $path), '/'); } protected function replaceNamedParameters($path, &$parameters) { return preg_replace_callback('/\\{(.*?)\\??\\}/', function ($m) use(&$parameters) { return isset($parameters[$m[1]]) ? array_pull($parameters, $m[1]) : $m[0]; }, $path); } protected function getRouteQueryString(array $parameters) { if (count($parameters) == 0) { return ''; } $query = http_build_query($keyed = $this->getStringParameters($parameters)); if (count($keyed) < count($parameters)) { $query .= '&' . implode('&', $this->getNumericParameters($parameters)); } return '?' . trim($query, '&'); } protected function getStringParameters(array $parameters) { return array_where($parameters, function ($k, $v) { return is_string($k); }); } protected function getNumericParameters(array $parameters) { return array_where($parameters, function ($k, $v) { return is_numeric($k); }); } protected function getRouteDomain($route, &$parameters) { return $route->domain() ? $this->formatDomain($route, $parameters) : null; } protected function formatDomain($route, &$parameters) { return $this->addPortToDomain($this->getDomainAndScheme($route)); } protected function getDomainAndScheme($route) { return $this->getRouteScheme($route) . $route->domain(); } protected function addPortToDomain($domain) { if (in_array($this->request->getPort(), array('80', '443'))) { return $domain; } return $domain . ':' . $this->request->getPort(); } protected function getRouteRoot($route, $domain) { return $this->getRootUrl($this->getRouteScheme($route), $domain); } protected function getRouteScheme($route) { if ($route->httpOnly()) { return $this->getScheme(false); } elseif ($route->httpsOnly()) { return $this->getScheme(true); } return $this->getScheme(null); } public function action($action, $parameters = array(), $absolute = true) { return $this->route($action, $parameters, $absolute, $this->routes->getByAction($action)); } protected function getRootUrl($scheme, $root = null) { if (is_null($root)) { $root = $this->forcedRoot ?: $this->request->root(); } $start = starts_with($root, 'http://') ? 'http://' : 'https://'; return preg_replace('~' . $start . '~', $scheme, $root, 1); } public function forceRootUrl($root) { $this->forcedRoot = $root; } public function isValidUrl($path) { if (starts_with($path, array('#', '//', 'mailto:', 'tel:', 'http://', 'https://'))) { return true; } return filter_var($path, FILTER_VALIDATE_URL) !== false; } protected function trimUrl($root, $path, $tail = '') { return trim($root . '/' . trim($path . '/' . $tail, '/'), '/'); } public function getRequest() { return $this->request; } public function setRequest(Request $request) { $this->request = $request; } } namespace Illuminate\Routing\Matching; use Illuminate\Http\Request; use Illuminate\Routing\Route; interface ValidatorInterface { public function matches(Route $route, Request $request); } namespace Illuminate\Routing\Matching; use Illuminate\Http\Request; use Illuminate\Routing\Route; class HostValidator implements ValidatorInterface { public function matches(Route $route, Request $request) { if (is_null($route->getCompiled()->getHostRegex())) { return true; } return preg_match($route->getCompiled()->getHostRegex(), $request->getHost()); } } namespace Illuminate\Routing\Matching; use Illuminate\Http\Request; use Illuminate\Routing\Route; class MethodValidator implements ValidatorInterface { public function matches(Route $route, Request $request) { return in_array($request->getMethod(), $route->methods()); } } namespace Illuminate\Routing\Matching; use Illuminate\Http\Request; use Illuminate\Routing\Route; class SchemeValidator implements ValidatorInterface { public function matches(Route $route, Request $request) { if ($route->httpOnly()) { return !$request->secure(); } elseif ($route->secure()) { return $request->secure(); } return true; } } namespace Illuminate\Routing\Matching; use Illuminate\Http\Request; use Illuminate\Routing\Route; class UriValidator implements ValidatorInterface { public function matches(Route $route, Request $request) { $path = $request->path() == '/' ? '/' : '/' . $request->path(); return preg_match($route->getCompiled()->getRegex(), rawurldecode($path)); } } namespace Illuminate\Workbench; use Illuminate\Support\ServiceProvider; use Illuminate\Workbench\Console\WorkbenchMakeCommand; class WorkbenchServiceProvider extends ServiceProvider { protected $defer = false; public function register() { $this->app->bindShared('package.creator', function ($app) { return new PackageCreator($app['files']); }); $this->app->bindShared('command.workbench', function ($app) { return new WorkbenchMakeCommand($app['package.creator']); }); $this->commands('command.workbench'); } public function provides() { return array('package.creator', 'command.workbench'); } } namespace Illuminate\Events; use Illuminate\Container\Container; class Dispatcher { protected $container; protected $listeners = array(); protected $wildcards = array(); protected $sorted = array(); protected $firing = array(); public function __construct(Container $container = null) { $this->container = $container ?: new Container(); } public function listen($events, $listener, $priority = 0) { foreach ((array) $events as $event) { if (str_contains($event, '*')) { $this->setupWildcardListen($event, $listener); } else { $this->listeners[$event][$priority][] = $this->makeListener($listener); unset($this->sorted[$event]); } } } protected function setupWildcardListen($event, $listener) { $this->wildcards[$event][] = $this->makeListener($listener); } public function hasListeners($eventName) { return isset($this->listeners[$eventName]); } public function queue($event, $payload = array()) { $this->listen($event . '_queue', function () use($event, $payload) { $this->fire($event, $payload); }); } public function subscribe($subscriber) { $subscriber = $this->resolveSubscriber($subscriber); $subscriber->subscribe($this); } protected function resolveSubscriber($subscriber) { if (is_string($subscriber)) { return $this->container->make($subscriber); } return $subscriber; } public function until($event, $payload = array()) { return $this->fire($event, $payload, true); } public function flush($event) { $this->fire($event . '_queue'); } public function firing() { return last($this->firing); } public function fire($event, $payload = array(), $halt = false) { $responses = array(); if (!is_array($payload)) { $payload = array($payload); } $this->firing[] = $event; foreach ($this->getListeners($event) as $listener) { $response = call_user_func_array($listener, $payload); if (!is_null($response) && $halt) { array_pop($this->firing); return $response; } if ($response === false) { break; } $responses[] = $response; } array_pop($this->firing); return $halt ? null : $responses; } public function getListeners($eventName) { $wildcards = $this->getWildcardListeners($eventName); if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return array_merge($this->sorted[$eventName], $wildcards); } protected function getWildcardListeners($eventName) { $wildcards = array(); foreach ($this->wildcards as $key => $listeners) { if (str_is($key, $eventName)) { $wildcards = array_merge($wildcards, $listeners); } } return $wildcards; } protected function sortListeners($eventName) { $this->sorted[$eventName] = array(); if (isset($this->listeners[$eventName])) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } public function makeListener($listener) { if (is_string($listener)) { $listener = $this->createClassListener($listener); } return $listener; } public function createClassListener($listener) { $container = $this->container; return function () use($listener, $container) { $segments = explode('@', $listener); $method = count($segments) == 2 ? $segments[1] : 'handle'; $callable = array($container->make($segments[0]), $method); $data = func_get_args(); return call_user_func_array($callable, $data); }; } public function forget($event) { unset($this->listeners[$event], $this->sorted[$event]); } public function forgetQueued() { foreach ($this->listeners as $key => $value) { if (ends_with($key, '_queue')) { $this->forget($key); } } } } namespace Illuminate\Database\Eloquent; use DateTime; use ArrayAccess; use Carbon\Carbon; use LogicException; use JsonSerializable; use Illuminate\Events\Dispatcher; use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Support\Contracts\JsonableInterface; use Illuminate\Support\Contracts\ArrayableInterface; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\ConnectionResolverInterface as Resolver; abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterface, JsonSerializable { protected $connection; protected $table; protected $primaryKey = 'id'; protected $perPage = 15; public $incrementing = true; public $timestamps = true; protected $attributes = array(); protected $original = array(); protected $relations = array(); protected $hidden = array(); protected $visible = array(); protected $appends = array(); protected $fillable = array(); protected $guarded = array('*'); protected $dates = array(); protected $touches = array(); protected $observables = array(); protected $with = array(); protected $morphClass; public $exists = false; public static $snakeAttributes = true; protected static $resolver; protected static $dispatcher; protected static $booted = array(); protected static $globalScopes = array(); protected static $unguarded = false; protected static $mutatorCache = array(); public static $manyMethods = array('belongsToMany', 'morphToMany', 'morphedByMany'); const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; public function __construct(array $attributes = array()) { $this->bootIfNotBooted(); $this->syncOriginal(); $this->fill($attributes); } protected function bootIfNotBooted() { $class = get_class($this); if (!isset(static::$booted[$class])) { static::$booted[$class] = true; $this->fireModelEvent('booting', false); static::boot(); $this->fireModelEvent('booted', false); } } protected static function boot() { $class = get_called_class(); static::$mutatorCache[$class] = array(); foreach (get_class_methods($class) as $method) { if (preg_match('/^get(.+)Attribute$/', $method, $matches)) { if (static::$snakeAttributes) { $matches[1] = snake_case($matches[1]); } static::$mutatorCache[$class][] = lcfirst($matches[1]); } } static::bootTraits(); } protected static function bootTraits() { foreach (class_uses_recursive(get_called_class()) as $trait) { if (method_exists(get_called_class(), $method = 'boot' . class_basename($trait))) { forward_static_call(array(get_called_class(), $method)); } } } public static function addGlobalScope(ScopeInterface $scope) { static::$globalScopes[get_called_class()][get_class($scope)] = $scope; } public static function hasGlobalScope($scope) { return !is_null(static::getGlobalScope($scope)); } public static function getGlobalScope($scope) { return array_first(static::$globalScopes[get_called_class()], function ($key, $value) use($scope) { return $scope instanceof $value; }); } public function getGlobalScopes() { return array_get(static::$globalScopes, get_class($this), array()); } public static function observe($class) { $instance = new static(); $className = get_class($class); foreach ($instance->getObservableEvents() as $event) { if (method_exists($class, $event)) { static::registerModelEvent($event, $className . '@' . $event); } } } public function fill(array $attributes) { $totallyGuarded = $this->totallyGuarded(); foreach ($this->fillableFromArray($attributes) as $key => $value) { $key = $this->removeTableFromKey($key); if ($this->isFillable($key)) { $this->setAttribute($key, $value); } elseif ($totallyGuarded) { throw new MassAssignmentException($key); } } return $this; } protected function fillableFromArray(array $attributes) { if (count($this->fillable) > 0 && !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); $model->exists = $exists; return $model; } public function newFromBuilder($attributes = array()) { $instance = $this->newInstance(array(), true); $instance->setRawAttributes((array) $attributes, true); return $instance; } public static function hydrate(array $items, $connection = null) { $collection = with($instance = new static())->newCollection(); foreach ($items as $item) { $model = $instance->newFromBuilder($item); if (!is_null($connection)) { $model->setConnection($connection); } $collection->push($model); } return $collection; } public static function hydrateRaw($query, $bindings = array(), $connection = null) { $instance = new static(); if (!is_null($connection)) { $instance->setConnection($connection); } $items = $instance->getConnection()->select($query, $bindings); return static::hydrate($items, $connection); } public static function create(array $attributes) { $model = new static($attributes); $model->save(); return $model; } public static function firstOrCreate(array $attributes) { if (!is_null($instance = static::where($attributes)->first())) { return $instance; } return static::create($attributes); } public static function firstOrNew(array $attributes) { if (!is_null($instance = static::where($attributes)->first())) { return $instance; } return new static($attributes); } public static function updateOrCreate(array $attributes, array $values = array()) { $instance = static::firstOrNew($attributes); $instance->fill($values)->save(); return $instance; } protected static function firstByAttributes($attributes) { return static::where($attributes)->first(); } public static function query() { return (new static())->newQuery(); } public static function on($connection = null) { $instance = new static(); $instance->setConnection($connection); return $instance->newQuery(); } public static function onWriteConnection() { $instance = new static(); return $instance->newQuery()->useWritePdo(); } public static function all($columns = array('*')) { $instance = new static(); return $instance->newQuery()->get($columns); } public static function find($id, $columns = array('*')) { $instance = new static(); if (is_array($id) && empty($id)) { return $instance->newCollection(); } return $instance->newQuery()->find($id, $columns); } public static function findOrNew($id, $columns = array('*')) { if (!is_null($model = static::find($id, $columns))) { return $model; } return new static(); } public static function findOrFail($id, $columns = array('*')) { if (!is_null($model = static::find($id, $columns))) { return $model; } throw (new ModelNotFoundException())->setModel(get_called_class()); } public function load($relations) { if (is_string($relations)) { $relations = func_get_args(); } $query = $this->newQuery()->with($relations); $query->eagerLoadRelations(array($this)); return $this; } public static function with($relations) { if (is_string($relations)) { $relations = func_get_args(); } $instance = new static(); return $instance->newQuery()->with($relations); } public function hasOne($related, $foreignKey = null, $localKey = null) { $foreignKey = $foreignKey ?: $this->getForeignKey(); $instance = new $related(); $localKey = $localKey ?: $this->getKeyName(); return new HasOne($instance->newQuery(), $this, $instance->getTable() . '.' . $foreignKey, $localKey); } public function morphOne($related, $name, $type = null, $id = null, $localKey = null) { $instance = new $related(); list($type, $id) = $this->getMorphs($name, $type, $id); $table = $instance->getTable(); $localKey = $localKey ?: $this->getKeyName(); return new MorphOne($instance->newQuery(), $this, $table . '.' . $type, $table . '.' . $id, $localKey); } public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null) { if (is_null($relation)) { list(, $caller) = debug_backtrace(false, 2); $relation = $caller['function']; } if (is_null($foreignKey)) { $foreignKey = snake_case($relation) . '_id'; } $instance = new $related(); $query = $instance->newQuery(); $otherKey = $otherKey ?: $instance->getKeyName(); return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation); } public function morphTo($name = null, $type = null, $id = null) { if (is_null($name)) { list(, $caller) = debug_backtrace(false, 2); $name = snake_case($caller['function']); } list($type, $id) = $this->getMorphs($name, $type, $id); if (is_null($class = $this->{$type})) { return new MorphTo($this->newQuery(), $this, $id, null, $type, $name); } else { $instance = new $class(); return new MorphTo($instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name); } } public function hasMany($related, $foreignKey = null, $localKey = null) { $foreignKey = $foreignKey ?: $this->getForeignKey(); $instance = new $related(); $localKey = $localKey ?: $this->getKeyName(); return new HasMany($instance->newQuery(), $this, $instance->getTable() . '.' . $foreignKey, $localKey); } public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null) { $through = new $through(); $firstKey = $firstKey ?: $this->getForeignKey(); $secondKey = $secondKey ?: $through->getForeignKey(); return new HasManyThrough((new $related())->newQuery(), $this, $through, $firstKey, $secondKey); } public function morphMany($related, $name, $type = null, $id = null, $localKey = null) { $instance = new $related(); list($type, $id) = $this->getMorphs($name, $type, $id); $table = $instance->getTable(); $localKey = $localKey ?: $this->getKeyName(); return new MorphMany($instance->newQuery(), $this, $table . '.' . $type, $table . '.' . $id, $localKey); } public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null) { if (is_null($relation)) { $relation = $this->getBelongsToManyCaller(); } $foreignKey = $foreignKey ?: $this->getForeignKey(); $instance = new $related(); $otherKey = $otherKey ?: $instance->getForeignKey(); if (is_null($table)) { $table = $this->joiningTable($related); } $query = $instance->newQuery(); return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); } public function morphToMany($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false) { $caller = $this->getBelongsToManyCaller(); $foreignKey = $foreignKey ?: $name . '_id'; $instance = new $related(); $otherKey = $otherKey ?: $instance->getForeignKey(); $query = $instance->newQuery(); $table = $table ?: str_plural($name); return new MorphToMany($query, $this, $name, $table, $foreignKey, $otherKey, $caller, $inverse); } public function morphedByMany($related, $name, $table = null, $foreignKey = null, $otherKey = null) { $foreignKey = $foreignKey ?: $this->getForeignKey(); $otherKey = $otherKey ?: $name . '_id'; return $this->morphToMany($related, $name, $table, $foreignKey, $otherKey, true); } protected function getBelongsToManyCaller() { $self = __FUNCTION__; $caller = array_first(debug_backtrace(false), function ($key, $trace) use($self) { $caller = $trace['function']; return !in_array($caller, Model::$manyMethods) && $caller != $self; }); return !is_null($caller) ? $caller['function'] : null; } public function joiningTable($related) { $base = snake_case(class_basename($this)); $related = snake_case(class_basename($related)); $models = array($related, $base); sort($models); return strtolower(implode('_', $models)); } public static function destroy($ids) { $count = 0; $ids = is_array($ids) ? $ids : func_get_args(); $instance = new static(); $key = $instance->getKeyName(); foreach ($instance->whereIn($key, $ids)->get() as $model) { if ($model->delete()) { $count++; } } return $count; } public function delete() { if (is_null($this->primaryKey)) { throw new \Exception('No primary key defined on model.'); } if ($this->exists) { if ($this->fireModelEvent('deleting') === false) { return false; } $this->touchOwners(); $this->performDeleteOnModel(); $this->exists = false; $this->fireModelEvent('deleted', false); return true; } } public function forceDelete() { return $this->delete(); } protected function performDeleteOnModel() { $this->newQuery()->where($this->getKeyName(), $this->getKey())->delete(); } public static function saving($callback) { static::registerModelEvent('saving', $callback); } public static function saved($callback) { static::registerModelEvent('saved', $callback); } public static function updating($callback) { static::registerModelEvent('updating', $callback); } public static function updated($callback) { static::registerModelEvent('updated', $callback); } public static function creating($callback) { static::registerModelEvent('creating', $callback); } public static function created($callback) { static::registerModelEvent('created', $callback); } public static function deleting($callback) { static::registerModelEvent('deleting', $callback); } public static function deleted($callback) { static::registerModelEvent('deleted', $callback); } public static function flushEventListeners() { if (!isset(static::$dispatcher)) { return; } $instance = new static(); foreach ($instance->getObservableEvents() as $event) { static::$dispatcher->forget("eloquent.{$event}: " . get_called_class()); } } protected static function registerModelEvent($event, $callback) { if (isset(static::$dispatcher)) { $name = get_called_class(); static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback); } } public function getObservableEvents() { return array_merge(array('creating', 'created', 'updating', 'updated', 'deleting', 'deleted', 'saving', 'saved', 'restoring', 'restored'), $this->observables); } public function setObservableEvents(array $observables) { $this->observables = $observables; } public function addObservableEvents($observables) { $observables = is_array($observables) ? $observables : func_get_args(); $this->observables = array_unique(array_merge($this->observables, $observables)); } public function removeObservableEvents($observables) { $observables = is_array($observables) ? $observables : func_get_args(); $this->observables = array_diff($this->observables, $observables); } protected function increment($column, $amount = 1) { return $this->incrementOrDecrement($column, $amount, 'increment'); } protected function decrement($column, $amount = 1) { return $this->incrementOrDecrement($column, $amount, 'decrement'); } protected function incrementOrDecrement($column, $amount, $method) { $query = $this->newQuery(); if (!$this->exists) { return $query->{$method}($column, $amount); } $this->incrementOrDecrementAttributeValue($column, $amount, $method); return $query->where($this->getKeyName(), $this->getKey())->{$method}($column, $amount); } protected function incrementOrDecrementAttributeValue($column, $amount, $method) { $this->{$column} = $this->{$column} + ($method == 'increment' ? $amount : $amount * -1); $this->syncOriginalAttribute($column); } public function update(array $attributes = array()) { if (!$this->exists) { return $this->newQuery()->update($attributes); } return $this->fill($attributes)->save(); } public function push() { if (!$this->save()) { return false; } foreach ($this->relations as $models) { foreach (Collection::make($models) as $model) { if (!$model->push()) { return false; } } } return true; } public function save(array $options = array()) { $query = $this->newQueryWithoutScopes(); if ($this->fireModelEvent('saving') === false) { return false; } if ($this->exists) { $saved = $this->performUpdate($query, $options); } else { $saved = $this->performInsert($query, $options); } if ($saved) { $this->finishSave($options); } return $saved; } protected function finishSave(array $options) { $this->fireModelEvent('saved', false); $this->syncOriginal(); if (array_get($options, 'touch', true)) { $this->touchOwners(); } } protected function performUpdate(Builder $query, array $options = array()) { $dirty = $this->getDirty(); if (count($dirty) > 0) { if ($this->fireModelEvent('updating') === false) { return false; } if ($this->timestamps && array_get($options, 'timestamps', true)) { $this->updateTimestamps(); } $dirty = $this->getDirty(); if (count($dirty) > 0) { $this->setKeysForSaveQuery($query)->update($dirty); $this->fireModelEvent('updated', false); } } return true; } protected function performInsert(Builder $query, array $options = array()) { if ($this->fireModelEvent('creating') === false) { return false; } if ($this->timestamps && array_get($options, 'timestamps', true)) { $this->updateTimestamps(); } $attributes = $this->attributes; if ($this->incrementing) { $this->insertAndSetId($query, $attributes); } else { $query->insert($attributes); } $this->exists = true; $this->fireModelEvent('created', false); return true; } protected function insertAndSetId(Builder $query, $attributes) { $id = $query->insertGetId($attributes, $keyName = $this->getKeyName()); $this->setAttribute($keyName, $id); } public function touchOwners() { foreach ($this->touches as $relation) { $this->{$relation}()->touch(); if (!is_null($this->{$relation})) { $this->{$relation}->touchOwners(); } } } public function touches($relation) { return in_array($relation, $this->touches); } protected function fireModelEvent($event, $halt = true) { if (!isset(static::$dispatcher)) { return true; } $event = "eloquent.{$event}: " . get_class($this); $method = $halt ? 'until' : 'fire'; return static::$dispatcher->{$method}($event, $this); } protected function setKeysForSaveQuery(Builder $query) { $query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery()); return $query; } protected function getKeyForSaveQuery() { if (isset($this->original[$this->getKeyName()])) { return $this->original[$this->getKeyName()]; } return $this->getAttribute($this->getKeyName()); } public function touch() { $this->updateTimestamps(); return $this->save(); } protected function updateTimestamps() { $time = $this->freshTimestamp(); if (!$this->isDirty(static::UPDATED_AT)) { $this->setUpdatedAt($time); } if (!$this->exists && !$this->isDirty(static::CREATED_AT)) { $this->setCreatedAt($time); } } public function setCreatedAt($value) { $this->{static::CREATED_AT} = $value; } public function setUpdatedAt($value) { $this->{static::UPDATED_AT} = $value; } public function getCreatedAtColumn() { return static::CREATED_AT; } public function getUpdatedAtColumn() { return static::UPDATED_AT; } public function freshTimestamp() { return new Carbon(); } public function freshTimestampString() { return $this->fromDateTime($this->freshTimestamp()); } public function newQuery() { $builder = $this->newQueryWithoutScopes(); return $this->applyGlobalScopes($builder); } public function newQueryWithoutScope($scope) { $this->getGlobalScope($scope)->remove($builder = $this->newQuery(), $this); return $builder; } public function newQueryWithoutScopes() { $builder = $this->newEloquentBuilder($this->newBaseQueryBuilder()); return $builder->setModel($this)->with($this->with); } public function applyGlobalScopes($builder) { foreach ($this->getGlobalScopes() as $scope) { $scope->apply($builder, $this); } return $builder; } public function removeGlobalScopes($builder) { foreach ($this->getGlobalScopes() as $scope) { $scope->remove($builder, $this); } return $builder; } public function newEloquentBuilder($query) { return new Builder($query); } protected function newBaseQueryBuilder() { $conn = $this->getConnection(); $grammar = $conn->getQueryGrammar(); return new QueryBuilder($conn, $grammar, $conn->getPostProcessor()); } public function newCollection(array $models = array()) { 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)) { return $this->table; } return str_replace('\\', '', snake_case(str_plural(class_basename($this)))); } public function setTable($table) { $this->table = $table; } public function getKey() { return $this->getAttribute($this->getKeyName()); } public function getKeyName() { return $this->primaryKey; } public function setKeyName($key) { $this->primaryKey = $key; } public function getQualifiedKeyName() { return $this->getTable() . '.' . $this->getKeyName(); } public function usesTimestamps() { return $this->timestamps; } protected function getMorphs($name, $type, $id) { $type = $type ?: $name . '_type'; $id = $id ?: $name . '_id'; return array($type, $id); } public function getMorphClass() { return $this->morphClass ?: get_class($this); } public function getPerPage() { return $this->perPage; } public function setPerPage($perPage) { $this->perPage = $perPage; } public function getForeignKey() { return snake_case(class_basename($this)) . '_id'; } public function getHidden() { return $this->hidden; } public function setHidden(array $hidden) { $this->hidden = $hidden; } public function setVisible(array $visible) { $this->visible = $visible; } public function setAppends(array $appends) { $this->appends = $appends; } public function getFillable() { return $this->fillable; } public function fillable(array $fillable) { $this->fillable = $fillable; return $this; } public function getGuarded() { return $this->guarded; } public function guard(array $guarded) { $this->guarded = $guarded; return $this; } public static function unguard() { static::$unguarded = true; } public static function reguard() { static::$unguarded = false; } public static function setUnguardState($state) { static::$unguarded = $state; } public function isFillable($key) { if (static::$unguarded) { return true; } if (in_array($key, $this->fillable)) { return true; } if ($this->isGuarded($key)) { return false; } return empty($this->fillable) && !starts_with($key, '_'); } public function isGuarded($key) { return in_array($key, $this->guarded) || $this->guarded == array('*'); } public function totallyGuarded() { return count($this->fillable) == 0 && $this->guarded == array('*'); } protected function removeTableFromKey($key) { if (!str_contains($key, '.')) { return $key; } return last(explode('.', $key)); } public function getTouchedRelations() { return $this->touches; } public function setTouchedRelations(array $touches) { $this->touches = $touches; } public function getIncrementing() { return $this->incrementing; } public function setIncrementing($value) { $this->incrementing = $value; } public function toJson($options = 0) { return json_encode($this->toArray(), $options); } public function jsonSerialize() { return $this->toArray(); } public function toArray() { $attributes = $this->attributesToArray(); return array_merge($attributes, $this->relationsToArray()); } public function attributesToArray() { $attributes = $this->getArrayableAttributes(); foreach ($this->getDates() as $key) { if (!isset($attributes[$key])) { continue; } $attributes[$key] = (string) $this->asDateTime($attributes[$key]); } foreach ($this->getMutatedAttributes() as $key) { if (!array_key_exists($key, $attributes)) { continue; } $attributes[$key] = $this->mutateAttributeForArray($key, $attributes[$key]); } foreach ($this->getArrayableAppends() as $key) { $attributes[$key] = $this->mutateAttributeForArray($key, null); } return $attributes; } protected function getArrayableAttributes() { return $this->getArrayableItems($this->attributes); } protected function getArrayableAppends() { if (!count($this->appends)) { return array(); } return $this->getArrayableItems(array_combine($this->appends, $this->appends)); } public function relationsToArray() { $attributes = array(); foreach ($this->getArrayableRelations() as $key => $value) { if (in_array($key, $this->hidden)) { continue; } if ($value instanceof ArrayableInterface) { $relation = $value->toArray(); } elseif (is_null($value)) { $relation = $value; } if (static::$snakeAttributes) { $key = snake_case($key); } if (isset($relation) || is_null($value)) { $attributes[$key] = $relation; } unset($relation); } return $attributes; } protected function getArrayableRelations() { return $this->getArrayableItems($this->relations); } protected function getArrayableItems(array $values) { if (count($this->visible) > 0) { return array_intersect_key($values, array_flip($this->visible)); } return array_diff_key($values, array_flip($this->hidden)); } public function getAttribute($key) { $inAttributes = array_key_exists($key, $this->attributes); if ($inAttributes || $this->hasGetMutator($key)) { return $this->getAttributeValue($key); } if (array_key_exists($key, $this->relations)) { return $this->relations[$key]; } $camelKey = camel_case($key); if (method_exists($this, $camelKey)) { return $this->getRelationshipFromMethod($key, $camelKey); } } protected function getAttributeValue($key) { $value = $this->getAttributeFromArray($key); if ($this->hasGetMutator($key)) { return $this->mutateAttribute($key, $value); } elseif (in_array($key, $this->getDates())) { if ($value) { return $this->asDateTime($value); } } return $value; } protected function getAttributeFromArray($key) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } } protected function getRelationshipFromMethod($key, $camelKey) { $relations = $this->{$camelKey}(); if (!$relations instanceof Relation) { throw new LogicException('Relationship method must return an object of type ' . 'Illuminate\\Database\\Eloquent\\Relations\\Relation'); } return $this->relations[$key] = $relations->getResults(); } public function hasGetMutator($key) { return method_exists($this, 'get' . studly_case($key) . 'Attribute'); } protected function mutateAttribute($key, $value) { return $this->{'get' . studly_case($key) . 'Attribute'}($value); } protected function mutateAttributeForArray($key, $value) { $value = $this->mutateAttribute($key, $value); return $value instanceof ArrayableInterface ? $value->toArray() : $value; } public function setAttribute($key, $value) { if ($this->hasSetMutator($key)) { $method = 'set' . studly_case($key) . 'Attribute'; return $this->{$method}($value); } elseif (in_array($key, $this->getDates()) && $value) { $value = $this->fromDateTime($value); } $this->attributes[$key] = $value; } public function hasSetMutator($key) { return method_exists($this, 'set' . studly_case($key) . 'Attribute'); } public function getDates() { $defaults = array(static::CREATED_AT, static::UPDATED_AT); return array_merge($this->dates, $defaults); } public function fromDateTime($value) { $format = $this->getDateFormat(); if ($value instanceof DateTime) { } 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)->startOfDay(); } else { $value = Carbon::createFromFormat($format, $value); } return $value->format($format); } protected function asDateTime($value) { 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)->startOfDay(); } elseif (!$value instanceof DateTime) { $format = $this->getDateFormat(); return Carbon::createFromFormat($format, $value); } return Carbon::instance($value); } protected function getDateFormat() { return $this->getConnection()->getQueryGrammar()->getDateFormat(); } public function replicate(array $except = null) { $except = $except ?: array($this->getKeyName(), $this->getCreatedAtColumn(), $this->getUpdatedAtColumn()); $attributes = array_except($this->attributes, $except); with($instance = new static())->setRawAttributes($attributes); return $instance->setRelations($this->relations); } public function getAttributes() { return $this->attributes; } public function setRawAttributes(array $attributes, $sync = false) { $this->attributes = $attributes; if ($sync) { $this->syncOriginal(); } } public function getOriginal($key = null, $default = null) { return array_get($this->original, $key, $default); } public function syncOriginal() { $this->original = $this->attributes; return $this; } public function syncOriginalAttribute($attribute) { $this->original[$attribute] = $this->attributes[$attribute]; return $this; } public function isDirty($attributes = null) { $dirty = $this->getDirty(); if (is_null($attributes)) { return count($dirty) > 0; } if (!is_array($attributes)) { $attributes = func_get_args(); } foreach ($attributes as $attribute) { if (array_key_exists($attribute, $dirty)) { return true; } } return false; } public function getDirty() { $dirty = array(); foreach ($this->attributes as $key => $value) { if (!array_key_exists($key, $this->original)) { $dirty[$key] = $value; } elseif ($value !== $this->original[$key] && !$this->originalIsNumericallyEquivalent($key)) { $dirty[$key] = $value; } } return $dirty; } protected function originalIsNumericallyEquivalent($key) { $current = $this->attributes[$key]; $original = $this->original[$key]; return is_numeric($current) && is_numeric($original) && strcmp((string) $current, (string) $original) === 0; } public function getRelations() { return $this->relations; } public function getRelation($relation) { return $this->relations[$relation]; } public function setRelation($relation, $value) { $this->relations[$relation] = $value; return $this; } public function setRelations(array $relations) { $this->relations = $relations; return $this; } public function getConnection() { return static::resolveConnection($this->connection); } public function getConnectionName() { return $this->connection; } public function setConnection($name) { $this->connection = $name; return $this; } public static function resolveConnection($connection = null) { return static::$resolver->connection($connection); } public static function getConnectionResolver() { return static::$resolver; } public static function setConnectionResolver(Resolver $resolver) { static::$resolver = $resolver; } public static function unsetConnectionResolver() { static::$resolver = null; } public static function getEventDispatcher() { return static::$dispatcher; } public static function setEventDispatcher(Dispatcher $dispatcher) { static::$dispatcher = $dispatcher; } public static function unsetEventDispatcher() { static::$dispatcher = null; } public function getMutatedAttributes() { $class = get_class($this); if (isset(static::$mutatorCache[$class])) { return static::$mutatorCache[$class]; } return array(); } public function __get($key) { return $this->getAttribute($key); } public function __set($key, $value) { $this->setAttribute($key, $value); } public function offsetExists($offset) { return isset($this->{$offset}); } public function offsetGet($offset) { return $this->{$offset}; } public function offsetSet($offset, $value) { $this->{$offset} = $value; } public function offsetUnset($offset) { unset($this->{$offset}); } public function __isset($key) { return isset($this->attributes[$key]) || isset($this->relations[$key]) || $this->hasGetMutator($key) && !is_null($this->getAttributeValue($key)); } public function __unset($key) { unset($this->attributes[$key], $this->relations[$key]); } public function __call($method, $parameters) { if (in_array($method, array('increment', 'decrement'))) { return call_user_func_array(array($this, $method), $parameters); } $query = $this->newQuery(); return call_user_func_array(array($query, $method), $parameters); } public static function __callStatic($method, $parameters) { $instance = new static(); return call_user_func_array(array($instance, $method), $parameters); } public function __toString() { return $this->toJson(); } public function __wakeup() { $this->bootIfNotBooted(); } } namespace Illuminate\Support\Contracts; interface ArrayableInterface { public function toArray(); } namespace Illuminate\Support\Contracts; interface JsonableInterface { public function toJson($options = 0); } namespace Illuminate\Database; use Illuminate\Support\Str; use Illuminate\Database\Connectors\ConnectionFactory; class DatabaseManager implements ConnectionResolverInterface { protected $app; protected $factory; protected $connections = array(); protected $extensions = array(); public function __construct($app, ConnectionFactory $factory) { $this->app = $app; $this->factory = $factory; } public function connection($name = null) { list($name, $type) = $this->parseConnectionName($name); if (!isset($this->connections[$name])) { $connection = $this->makeConnection($name); $this->setPdoForType($connection, $type); $this->connections[$name] = $this->prepare($connection); } return $this->connections[$name]; } protected function parseConnectionName($name) { $name = $name ?: $this->getDefaultConnection(); return Str::endsWith($name, array('::read', '::write')) ? explode('::', $name, 2) : array($name, null); } public function purge($name = null) { $this->disconnect($name); unset($this->connections[$name]); } public function disconnect($name = null) { if (isset($this->connections[$name = $name ?: $this->getDefaultConnection()])) { $this->connections[$name]->disconnect(); } } public function reconnect($name = null) { $this->disconnect($name = $name ?: $this->getDefaultConnection()); if (!isset($this->connections[$name])) { return $this->connection($name); } return $this->refreshPdoConnections($name); } protected function refreshPdoConnections($name) { $fresh = $this->makeConnection($name); return $this->connections[$name]->setPdo($fresh->getPdo())->setReadPdo($fresh->getReadPdo()); } protected function makeConnection($name) { $config = $this->getConfig($name); if (isset($this->extensions[$name])) { return call_user_func($this->extensions[$name], $config, $name); } $driver = $config['driver']; if (isset($this->extensions[$driver])) { return call_user_func($this->extensions[$driver], $config, $name); } return $this->factory->make($config, $name); } protected function prepare(Connection $connection) { $connection->setFetchMode($this->app['config']['database.fetch']); if ($this->app->bound('events')) { $connection->setEventDispatcher($this->app['events']); } $app = $this->app; $connection->setCacheManager(function () use($app) { return $app['cache']; }); $connection->setPaginator(function () use($app) { return $app['paginator']; }); $connection->setReconnector(function ($connection) { $this->reconnect($connection->getName()); }); return $connection; } protected function setPdoForType(Connection $connection, $type = null) { if ($type == 'read') { $connection->setPdo($connection->getReadPdo()); } elseif ($type == 'write') { $connection->setReadPdo($connection->getPdo()); } return $connection; } protected function getConfig($name) { $name = $name ?: $this->getDefaultConnection(); $connections = $this->app['config']['database.connections']; if (is_null($config = array_get($connections, $name))) { throw new \InvalidArgumentException("Database [{$name}] not configured."); } return $config; } public function getDefaultConnection() { return $this->app['config']['database.default']; } public function setDefaultConnection($name) { $this->app['config']['database.default'] = $name; } public function extend($name, callable $resolver) { $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); } } namespace Illuminate\Database; interface ConnectionResolverInterface { public function connection($name = null); public function getDefaultConnection(); public function setDefaultConnection($name); } namespace Illuminate\Database\Connectors; use PDO; use Illuminate\Container\Container; use Illuminate\Database\MySqlConnection; use Illuminate\Database\SQLiteConnection; use Illuminate\Database\PostgresConnection; use Illuminate\Database\SqlServerConnection; class ConnectionFactory { protected $container; public function __construct(Container $container) { $this->container = $container; } public function make(array $config, $name = null) { $config = $this->parseConfig($config, $name); if (isset($config['read'])) { return $this->createReadWriteConnection($config); } return $this->createSingleConnection($config); } protected function createSingleConnection(array $config) { $pdo = $this->createConnector($config)->connect($config); return $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config); } protected function createReadWriteConnection(array $config) { $connection = $this->createSingleConnection($this->getWriteConfig($config)); return $connection->setReadPdo($this->createReadPdo($config)); } protected function createReadPdo(array $config) { $readConfig = $this->getReadConfig($config); return $this->createConnector($readConfig)->connect($readConfig); } protected function getReadConfig(array $config) { $readConfig = $this->getReadWriteConfig($config, 'read'); return $this->mergeReadWriteConfig($config, $readConfig); } protected function getWriteConfig(array $config) { $writeConfig = $this->getReadWriteConfig($config, 'write'); return $this->mergeReadWriteConfig($config, $writeConfig); } protected function getReadWriteConfig(array $config, $type) { if (isset($config[$type][0])) { return $config[$type][array_rand($config[$type])]; } return $config[$type]; } protected function mergeReadWriteConfig(array $config, array $merge) { return array_except(array_merge($config, $merge), array('read', 'write')); } protected function parseConfig(array $config, $name) { return array_add(array_add($config, 'prefix', ''), 'name', $name); } public function createConnector(array $config) { if (!isset($config['driver'])) { throw new \InvalidArgumentException('A driver must be specified.'); } if ($this->container->bound($key = "db.connector.{$config['driver']}")) { return $this->container->make($key); } switch ($config['driver']) { case 'mysql': return new MySqlConnector(); case 'pgsql': return new PostgresConnector(); case 'sqlite': return new SQLiteConnector(); case 'sqlsrv': return new SqlServerConnector(); } throw new \InvalidArgumentException("Unsupported driver [{$config['driver']}]"); } protected function createConnection($driver, PDO $connection, $database, $prefix = '', array $config = array()) { if ($this->container->bound($key = "db.connection.{$driver}")) { return $this->container->make($key, array($connection, $database, $prefix, $config)); } switch ($driver) { case 'mysql': return new MySqlConnection($connection, $database, $prefix, $config); case 'pgsql': return new PostgresConnection($connection, $database, $prefix, $config); case 'sqlite': return new SQLiteConnection($connection, $database, $prefix, $config); case 'sqlsrv': return new SqlServerConnection($connection, $database, $prefix, $config); } throw new \InvalidArgumentException("Unsupported driver [{$driver}]"); } } namespace Illuminate\Session; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface as BaseSessionInterface; interface SessionInterface extends BaseSessionInterface { public function getHandler(); public function handlerNeedsRequest(); public function setRequestOnHandler(Request $request); } namespace Illuminate\Session; use Closure; use Carbon\Carbon; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; class Middleware implements HttpKernelInterface { protected $app; protected $manager; protected $reject; public function __construct(HttpKernelInterface $app, SessionManager $manager, Closure $reject = null) { $this->app = $app; $this->reject = $reject; $this->manager = $manager; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { $this->checkRequestForArraySessions($request); if ($this->sessionConfigured()) { $session = $this->startSession($request); $request->setSession($session); } $response = $this->app->handle($request, $type, $catch); if ($this->sessionConfigured()) { $this->closeSession($session); $this->addCookieToResponse($response, $session); } return $response; } public function checkRequestForArraySessions(Request $request) { if (is_null($this->reject)) { return; } if (call_user_func($this->reject, $request)) { $this->manager->setDefaultDriver('array'); } } protected function startSession(Request $request) { with($session = $this->getSession($request))->setRequestOnHandler($request); $session->start(); return $session; } protected function closeSession(SessionInterface $session) { $session->save(); $this->collectGarbage($session); } protected function getUrl(Request $request) { $url = rtrim(preg_replace('/\\?.*/', '', $request->getUri()), '/'); return $request->getQueryString() ? $url . '?' . $request->getQueryString() : $url; } protected function collectGarbage(SessionInterface $session) { $config = $this->manager->getSessionConfig(); if ($this->configHitsLottery($config)) { $session->getHandler()->gc($this->getLifetimeSeconds()); } } protected function configHitsLottery(array $config) { return mt_rand(1, $config['lottery'][1]) <= $config['lottery'][0]; } protected function addCookieToResponse(Response $response, SessionInterface $session) { $s = $session; if ($this->sessionIsPersistent($c = $this->manager->getSessionConfig())) { $secure = array_get($c, 'secure', false); $response->headers->setCookie(new Cookie($s->getName(), $s->getId(), $this->getCookieLifetime(), $c['path'], $c['domain'], $secure)); } } protected function getLifetimeSeconds() { return array_get($this->manager->getSessionConfig(), 'lifetime') * 60; } protected function getCookieLifetime() { $config = $this->manager->getSessionConfig(); return $config['expire_on_close'] ? 0 : Carbon::now()->addMinutes($config['lifetime']); } protected function sessionConfigured() { return !is_null(array_get($this->manager->getSessionConfig(), 'driver')); } protected function sessionIsPersistent(array $config = null) { $config = $config ?: $this->manager->getSessionConfig(); return !in_array($config['driver'], array(null, 'array')); } public function getSession(Request $request) { $session = $this->manager->driver(); $session->setId($request->cookies->get($session->getName())); return $session; } } namespace Illuminate\Session; use SessionHandlerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; class Store implements SessionInterface { protected $id; protected $name; protected $attributes = array(); protected $bags = array(); protected $metaBag; protected $bagData = array(); protected $handler; protected $started = false; public function __construct($name, SessionHandlerInterface $handler, $id = null) { $this->setId($id); $this->name = $name; $this->handler = $handler; $this->metaBag = new MetadataBag(); } public function start() { $this->loadSession(); if (!$this->has('_token')) { $this->regenerateToken(); } return $this->started = true; } protected function loadSession() { $this->attributes = $this->readFromHandler(); foreach (array_merge($this->bags, array($this->metaBag)) as $bag) { $this->initializeLocalBag($bag); $bag->initialize($this->bagData[$bag->getStorageKey()]); } } protected function readFromHandler() { $data = $this->handler->read($this->getId()); return $data ? unserialize($data) : array(); } protected function initializeLocalBag($bag) { $this->bagData[$bag->getStorageKey()] = $this->pull($bag->getStorageKey(), array()); } public function getId() { return $this->id; } public function setId($id) { if (!$this->isValidId($id)) { $id = $this->generateSessionId(); } $this->id = $id; } public function isValidId($id) { return is_string($id) && preg_match('/^[a-f0-9]{40}$/', $id); } protected function generateSessionId() { return sha1(uniqid('', true) . str_random(25) . microtime(true)); } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function invalidate($lifetime = null) { $this->attributes = array(); $this->migrate(); return true; } public function migrate($destroy = false, $lifetime = null) { if ($destroy) { $this->handler->destroy($this->getId()); } $this->setExists(false); $this->id = $this->generateSessionId(); return true; } public function regenerate($destroy = false) { return $this->migrate($destroy); } public function save() { $this->addBagDataToSession(); $this->ageFlashData(); $this->handler->write($this->getId(), serialize($this->attributes)); $this->started = false; } protected function addBagDataToSession() { foreach (array_merge($this->bags, array($this->metaBag)) as $bag) { $this->put($bag->getStorageKey(), $this->bagData[$bag->getStorageKey()]); } } public function ageFlashData() { foreach ($this->get('flash.old', array()) as $old) { $this->forget($old); } $this->put('flash.old', $this->get('flash.new', array())); $this->put('flash.new', array()); } public function has($name) { return !is_null($this->get($name)); } public function get($name, $default = null) { return array_get($this->attributes, $name, $default); } public function pull($key, $default = null) { return array_pull($this->attributes, $key, $default); } public function hasOldInput($key = null) { $old = $this->getOldInput($key); return is_null($key) ? count($old) > 0 : !is_null($old); } public function getOldInput($key = null, $default = null) { $input = $this->get('_old_input', array()); return array_get($input, $key, $default); } public function set($name, $value) { array_set($this->attributes, $name, $value); } public function put($key, $value = null) { if (!is_array($key)) { $key = array($key => $value); } foreach ($key as $arrayKey => $arrayValue) { $this->set($arrayKey, $arrayValue); } } public function push($key, $value) { $array = $this->get($key, array()); $array[] = $value; $this->put($key, $array); } public function flash($key, $value) { $this->put($key, $value); $this->push('flash.new', $key); $this->removeFromOldFlashData(array($key)); } public function flashInput(array $value) { $this->flash('_old_input', $value); } public function reflash() { $this->mergeNewFlashes($this->get('flash.old', array())); $this->put('flash.old', array()); } public function keep($keys = null) { $keys = is_array($keys) ? $keys : func_get_args(); $this->mergeNewFlashes($keys); $this->removeFromOldFlashData($keys); } protected function mergeNewFlashes(array $keys) { $values = array_unique(array_merge($this->get('flash.new', array()), $keys)); $this->put('flash.new', $values); } protected function removeFromOldFlashData(array $keys) { $this->put('flash.old', array_diff($this->get('flash.old', array()), $keys)); } public function all() { return $this->attributes; } public function replace(array $attributes) { foreach ($attributes as $key => $value) { $this->put($key, $value); } } public function remove($name) { return array_pull($this->attributes, $name); } public function forget($key) { array_forget($this->attributes, $key); } public function clear() { $this->attributes = array(); foreach ($this->bags as $bag) { $bag->clear(); } } public function flush() { $this->clear(); } public function isStarted() { return $this->started; } public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getStorageKey()] = $bag; } public function getBag($name) { return array_get($this->bags, $name, function () { throw new \InvalidArgumentException('Bag not registered.'); }); } public function getMetadataBag() { return $this->metaBag; } public function getBagData($name) { return array_get($this->bagData, $name, array()); } public function token() { return $this->get('_token'); } public function getToken() { return $this->token(); } public function regenerateToken() { $this->put('_token', str_random(40)); } public function setExists($value) { if ($this->handler instanceof ExistenceAwareInterface) { $this->handler->setExists($value); } } public function getHandler() { return $this->handler; } public function handlerNeedsRequest() { return $this->handler instanceof CookieSessionHandler; } public function setRequestOnHandler(Request $request) { if ($this->handlerNeedsRequest()) { $this->handler->setRequest($request); } } } namespace Illuminate\Session; use Illuminate\Support\Manager; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; class SessionManager extends Manager { protected function callCustomCreator($driver) { return $this->buildSession(parent::callCustomCreator($driver)); } protected function createArrayDriver() { return new Store($this->app['config']['session.cookie'], new NullSessionHandler()); } protected function createCookieDriver() { $lifetime = $this->app['config']['session.lifetime']; return $this->buildSession(new CookieSessionHandler($this->app['cookie'], $lifetime)); } protected function createFileDriver() { return $this->createNativeDriver(); } protected function createNativeDriver() { $path = $this->app['config']['session.files']; return $this->buildSession(new FileSessionHandler($this->app['files'], $path)); } protected function createDatabaseDriver() { $connection = $this->getDatabaseConnection(); $table = $this->app['config']['session.table']; return $this->buildSession(new DatabaseSessionHandler($connection, $table)); } protected function getDatabaseConnection() { $connection = $this->app['config']['session.connection']; return $this->app['db']->connection($connection); } protected function createApcDriver() { return $this->createCacheBased('apc'); } protected function createMemcachedDriver() { return $this->createCacheBased('memcached'); } protected function createWincacheDriver() { return $this->createCacheBased('wincache'); } protected function createRedisDriver() { $handler = $this->createCacheHandler('redis'); $handler->getCache()->getStore()->setConnection($this->app['config']['session.connection']); return $this->buildSession($handler); } protected function createCacheBased($driver) { return $this->buildSession($this->createCacheHandler($driver)); } protected function createCacheHandler($driver) { $minutes = $this->app['config']['session.lifetime']; return new CacheBasedSessionHandler($this->app['cache']->driver($driver), $minutes); } protected function buildSession($handler) { return new Store($this->app['config']['session.cookie'], $handler); } public function getSessionConfig() { return $this->app['config']['session']; } public function getDefaultDriver() { return $this->app['config']['session.driver']; } public function setDefaultDriver($name) { $this->app['config']['session.driver'] = $name; } } namespace Illuminate\Support; use Closure; abstract class Manager { protected $app; protected $customCreators = array(); protected $drivers = array(); public function __construct($app) { $this->app = $app; } public abstract function getDefaultDriver(); public function driver($driver = null) { $driver = $driver ?: $this->getDefaultDriver(); if (!isset($this->drivers[$driver])) { $this->drivers[$driver] = $this->createDriver($driver); } return $this->drivers[$driver]; } protected function createDriver($driver) { $method = 'create' . ucfirst($driver) . 'Driver'; if (isset($this->customCreators[$driver])) { return $this->callCustomCreator($driver); } elseif (method_exists($this, $method)) { return $this->{$method}(); } throw new \InvalidArgumentException("Driver [{$driver}] not supported."); } protected function callCustomCreator($driver) { return $this->customCreators[$driver]($this->app); } public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; return $this; } public function getDrivers() { return $this->drivers; } public function __call($method, $parameters) { return call_user_func_array(array($this->driver(), $method), $parameters); } } namespace Illuminate\Cookie; use Symfony\Component\HttpFoundation\Cookie; class CookieJar { protected $path = '/'; protected $domain = null; protected $queued = array(); public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true) { list($path, $domain) = $this->getPathAndDomain($path, $domain); $time = $minutes == 0 ? 0 : time() + $minutes * 60; return new Cookie($name, $value, $time, $path, $domain, $secure, $httpOnly); } public function forever($name, $value, $path = null, $domain = null, $secure = false, $httpOnly = true) { return $this->make($name, $value, 2628000, $path, $domain, $secure, $httpOnly); } public function forget($name, $path = null, $domain = null) { return $this->make($name, null, -2628000, $path, $domain); } public function hasQueued($key) { return !is_null($this->queued($key)); } public function queued($key, $default = null) { return array_get($this->queued, $key, $default); } 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]); } protected function getPathAndDomain($path, $domain) { return array($path ?: $this->path, $domain ?: $this->domain); } public function setDefaultPathAndDomain($path, $domain) { list($this->path, $this->domain) = array($path, $domain); return $this; } public function getQueuedCookies() { return $this->queued; } } namespace Illuminate\Cookie; use Illuminate\Encryption\Encrypter; use Illuminate\Encryption\DecryptException; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; class Guard implements HttpKernelInterface { protected $app; protected $encrypter; public function __construct(HttpKernelInterface $app, Encrypter $encrypter) { $this->app = $app; $this->encrypter = $encrypter; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { return $this->encrypt($this->app->handle($this->decrypt($request), $type, $catch)); } protected function decrypt(Request $request) { foreach ($request->cookies as $key => $c) { try { $request->cookies->set($key, $this->decryptCookie($c)); } catch (DecryptException $e) { $request->cookies->set($key, null); } } return $request; } protected function decryptCookie($cookie) { return is_array($cookie) ? $this->decryptArray($cookie) : $this->encrypter->decrypt($cookie); } protected function decryptArray(array $cookie) { $decrypted = array(); foreach ($cookie as $key => $value) { $decrypted[$key] = $this->encrypter->decrypt($value); } return $decrypted; } protected function encrypt(Response $response) { foreach ($response->headers->getCookies() as $key => $c) { $encrypted = $this->encrypter->encrypt($c->getValue()); $response->headers->setCookie($this->duplicate($c, $encrypted)); } return $response; } protected function duplicate(Cookie $c, $value) { return new Cookie($c->getName(), $value, $c->getExpiresTime(), $c->getPath(), $c->getDomain(), $c->isSecure(), $c->isHttpOnly()); } } namespace Illuminate\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; class Queue implements HttpKernelInterface { protected $app; protected $cookies; public function __construct(HttpKernelInterface $app, CookieJar $cookies) { $this->app = $app; $this->cookies = $cookies; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { $response = $this->app->handle($request, $type, $catch); foreach ($this->cookies->getQueuedCookies() as $cookie) { $response->headers->setCookie($cookie); } return $response; } } namespace Illuminate\Encryption; use Symfony\Component\Security\Core\Util\StringUtils; use Symfony\Component\Security\Core\Util\SecureRandom; class Encrypter { protected $key; protected $cipher = MCRYPT_RIJNDAEL_128; protected $mode = MCRYPT_MODE_CBC; protected $block = 16; public function __construct($key) { $this->key = (string) $key; } public function encrypt($value) { $iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer()); $value = base64_encode($this->padAndMcrypt($value, $iv)); $mac = $this->hash($iv = base64_encode($iv), $value); return base64_encode(json_encode(compact('iv', 'value', 'mac'))); } protected function padAndMcrypt($value, $iv) { $value = $this->addPadding(serialize($value)); return mcrypt_encrypt($this->cipher, $this->key, $value, $this->mode, $iv); } public function decrypt($payload) { $payload = $this->getJsonPayload($payload); $value = base64_decode($payload['value']); $iv = base64_decode($payload['iv']); return unserialize($this->stripPadding($this->mcryptDecrypt($value, $iv))); } protected function mcryptDecrypt($value, $iv) { try { return mcrypt_decrypt($this->cipher, $this->key, $value, $this->mode, $iv); } catch (\Exception $e) { throw new DecryptException($e->getMessage()); } } protected function getJsonPayload($payload) { $payload = json_decode(base64_decode($payload), true); if (!$payload || $this->invalidPayload($payload)) { throw new DecryptException('Invalid data.'); } if (!$this->validMac($payload)) { throw new DecryptException('MAC is invalid.'); } return $payload; } protected function validMac(array $payload) { if (!function_exists('openssl_random_pseudo_bytes')) { throw new \RuntimeException('OpenSSL extension is required.'); } $bytes = (new SecureRandom())->nextBytes(16); $calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true); return StringUtils::equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac); } protected function hash($iv, $value) { return hash_hmac('sha256', $iv . $value, $this->key); } protected function addPadding($value) { $pad = $this->block - strlen($value) % $this->block; return $value . str_repeat(chr($pad), $pad); } protected function stripPadding($value) { $pad = ord($value[($len = strlen($value)) - 1]); return $this->paddingIsValid($pad, $value) ? substr($value, 0, $len - $pad) : $value; } protected function paddingIsValid($pad, $value) { $beforePad = strlen($value) - $pad; return substr($value, $beforePad) == str_repeat(substr($value, -1), $pad); } protected function invalidPayload($data) { return !is_array($data) || !isset($data['iv']) || !isset($data['value']) || !isset($data['mac']); } protected function getIvSize() { return mcrypt_get_iv_size($this->cipher, $this->mode); } protected function getRandomizer() { if (defined('MCRYPT_DEV_URANDOM')) { return MCRYPT_DEV_URANDOM; } if (defined('MCRYPT_DEV_RANDOM')) { return MCRYPT_DEV_RANDOM; } mt_srand(); return MCRYPT_RAND; } public function setKey($key) { $this->key = (string) $key; } public function setCipher($cipher) { $this->cipher = $cipher; $this->updateBlockSize(); } public function setMode($mode) { $this->mode = $mode; $this->updateBlockSize(); } protected function updateBlockSize() { $this->block = mcrypt_get_iv_size($this->cipher, $this->mode); } } namespace Illuminate\Support\Facades; class Log extends Facade { protected static function getFacadeAccessor() { return 'log'; } } namespace Illuminate\Log; use Monolog\Logger; use Illuminate\Support\ServiceProvider; class LogServiceProvider extends ServiceProvider { protected $defer = true; public function register() { $logger = new Writer(new Logger($this->app['env']), $this->app['events']); $this->app->instance('log', $logger); $this->app->bind('Psr\\Log\\LoggerInterface', function ($app) { return $app['log']->getMonolog(); }); if (isset($this->app['log.setup'])) { call_user_func($this->app['log.setup'], $logger); } } public function provides() { return array('log', 'Psr\\Log\\LoggerInterface'); } } namespace Illuminate\Log; use Closure; use Illuminate\Events\Dispatcher; use Monolog\Handler\StreamHandler; use Monolog\Logger as MonologLogger; use Monolog\Formatter\LineFormatter; use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\RotatingFileHandler; use Illuminate\Support\Contracts\JsonableInterface; use Illuminate\Support\Contracts\ArrayableInterface; class Writer { protected $monolog; protected $levels = array('debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency'); protected $dispatcher; public function __construct(MonologLogger $monolog, Dispatcher $dispatcher = null) { $this->monolog = $monolog; if (isset($dispatcher)) { $this->dispatcher = $dispatcher; } } protected function callMonolog($method, $parameters) { if (is_array($parameters[0])) { $parameters[0] = json_encode($parameters[0]); } return call_user_func_array(array($this->monolog, $method), $parameters); } public function useFiles($path, $level = 'debug') { $level = $this->parseLevel($level); $this->monolog->pushHandler($handler = new StreamHandler($path, $level)); $handler->setFormatter($this->getDefaultFormatter()); } public function useDailyFiles($path, $days = 0, $level = 'debug') { $level = $this->parseLevel($level); $this->monolog->pushHandler($handler = new RotatingFileHandler($path, $days, $level)); $handler->setFormatter($this->getDefaultFormatter()); } public function useErrorLog($level = 'debug', $messageType = ErrorLogHandler::OPERATING_SYSTEM) { $level = $this->parseLevel($level); $this->monolog->pushHandler($handler = new ErrorLogHandler($messageType, $level)); $handler->setFormatter($this->getDefaultFormatter()); } protected function getDefaultFormatter() { return new LineFormatter(null, null, true); } protected function parseLevel($level) { switch ($level) { case 'debug': return MonologLogger::DEBUG; case 'info': return MonologLogger::INFO; case 'notice': return MonologLogger::NOTICE; case 'warning': return MonologLogger::WARNING; case 'error': return MonologLogger::ERROR; case 'critical': return MonologLogger::CRITICAL; case 'alert': return MonologLogger::ALERT; case 'emergency': return MonologLogger::EMERGENCY; default: throw new \InvalidArgumentException('Invalid log level.'); } } public function listen(Closure $callback) { if (!isset($this->dispatcher)) { throw new \RuntimeException('Events dispatcher has not been set.'); } $this->dispatcher->listen('illuminate.log', $callback); } public function getMonolog() { return $this->monolog; } public function getEventDispatcher() { return $this->dispatcher; } public function setEventDispatcher(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } protected function fireLogEvent($level, $message, array $context = array()) { if (isset($this->dispatcher)) { $this->dispatcher->fire('illuminate.log', compact('level', 'message', 'context')); } } public function write() { $level = head(func_get_args()); return call_user_func_array(array($this, $level), array_slice(func_get_args(), 1)); } public function __call($method, $parameters) { if (in_array($method, $this->levels)) { $this->formatParameters($parameters); call_user_func_array(array($this, 'fireLogEvent'), array_merge(array($method), $parameters)); $method = 'add' . ucfirst($method); return $this->callMonolog($method, $parameters); } throw new \BadMethodCallException("Method [{$method}] does not exist."); } protected function formatParameters(&$parameters) { if (isset($parameters[0])) { if (is_array($parameters[0])) { $parameters[0] = var_export($parameters[0], true); } elseif ($parameters[0] instanceof JsonableInterface) { $parameters[0] = $parameters[0]->toJson(); } elseif ($parameters[0] instanceof ArrayableInterface) { $parameters[0] = var_export($parameters[0]->toArray(), true); } } } } namespace Monolog; use Monolog\Handler\HandlerInterface; use Monolog\Handler\StreamHandler; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; use Exception; class Logger implements LoggerInterface, ResettableInterface { const DEBUG = 100; const INFO = 200; const NOTICE = 250; const WARNING = 300; const ERROR = 400; const CRITICAL = 500; const ALERT = 550; const EMERGENCY = 600; const API = 1; protected static $levels = array(self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY'); protected static $timezone; protected $name; protected $handlers; protected $processors; protected $microsecondTimestamps = true; protected $exceptionHandler; public function __construct($name, array $handlers = array(), array $processors = array()) { $this->name = $name; $this->setHandlers($handlers); $this->processors = $processors; } public function getName() { return $this->name; } public function withName($name) { $new = clone $this; $new->name = $name; return $new; } public function pushHandler(HandlerInterface $handler) { array_unshift($this->handlers, $handler); return $this; } public function popHandler() { if (!$this->handlers) { throw new \LogicException('You tried to pop from an empty handler stack.'); } return array_shift($this->handlers); } public function setHandlers(array $handlers) { $this->handlers = array(); foreach (array_reverse($handlers) as $handler) { $this->pushHandler($handler); } return $this; } public function getHandlers() { return $this->handlers; } public function pushProcessor($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . var_export($callback, true) . ' given'); } array_unshift($this->processors, $callback); return $this; } public function popProcessor() { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } public function getProcessors() { return $this->processors; } public function useMicrosecondTimestamps($micro) { $this->microsecondTimestamps = (bool) $micro; } public function addRecord($level, $message, array $context = array()) { if (!$this->handlers) { $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); } $levelName = static::getLevelName($level); $handlerKey = null; reset($this->handlers); while ($handler = current($this->handlers)) { if ($handler->isHandling(array('level' => $level))) { $handlerKey = key($this->handlers); break; } next($this->handlers); } if (null === $handlerKey) { return false; } if (!static::$timezone) { static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); } if ($this->microsecondTimestamps && PHP_VERSION_ID < 70100) { $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone); } else { $ts = new \DateTime(null, static::$timezone); } $ts->setTimezone(static::$timezone); $record = array('message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => $ts, 'extra' => array()); try { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } while ($handler = current($this->handlers)) { if (true === $handler->handle($record)) { break; } next($this->handlers); } } catch (Exception $e) { $this->handleException($e, $record); } return true; } public function close() { foreach ($this->handlers as $handler) { if (method_exists($handler, 'close')) { $handler->close(); } } } public function reset() { foreach ($this->handlers as $handler) { if ($handler instanceof ResettableInterface) { $handler->reset(); } } foreach ($this->processors as $processor) { if ($processor instanceof ResettableInterface) { $processor->reset(); } } } public function addDebug($message, array $context = array()) { return $this->addRecord(static::DEBUG, $message, $context); } public function addInfo($message, array $context = array()) { return $this->addRecord(static::INFO, $message, $context); } public function addNotice($message, array $context = array()) { return $this->addRecord(static::NOTICE, $message, $context); } public function addWarning($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } public function addError($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } public function addCritical($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } public function addAlert($message, array $context = array()) { return $this->addRecord(static::ALERT, $message, $context); } public function addEmergency($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } public static function getLevels() { return array_flip(static::$levels); } public static function getLevelName($level) { if (!isset(static::$levels[$level])) { throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels))); } return static::$levels[$level]; } public static function toMonologLevel($level) { if (is_string($level)) { $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY'); if (defined(__CLASS__ . '::' . $upper)) { return constant(__CLASS__ . '::' . $upper); } } return $level; } public function isHandling($level) { $record = array('level' => $level); foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { return true; } } return false; } public function setExceptionHandler($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), ' . var_export($callback, true) . ' given'); } $this->exceptionHandler = $callback; return $this; } public function getExceptionHandler() { return $this->exceptionHandler; } protected function handleException(Exception $e, array $record) { if (!$this->exceptionHandler) { throw $e; } call_user_func($this->exceptionHandler, $e, $record); } public function log($level, $message, array $context = array()) { $level = static::toMonologLevel($level); return $this->addRecord($level, $message, $context); } public function debug($message, array $context = array()) { return $this->addRecord(static::DEBUG, $message, $context); } public function info($message, array $context = array()) { return $this->addRecord(static::INFO, $message, $context); } public function notice($message, array $context = array()) { return $this->addRecord(static::NOTICE, $message, $context); } public function warn($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } public function warning($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } public function err($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } public function error($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } public function crit($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } public function critical($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } public function alert($message, array $context = array()) { return $this->addRecord(static::ALERT, $message, $context); } public function emerg($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } public function emergency($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } public static function setTimezone(\DateTimeZone $tz) { self::$timezone = $tz; } } namespace Psr\Log; interface LoggerInterface { public function emergency($message, array $context = array()); public function alert($message, array $context = array()); public function critical($message, array $context = array()); public function error($message, array $context = array()); public function warning($message, array $context = array()); public function notice($message, array $context = array()); public function info($message, array $context = array()); public function debug($message, array $context = array()); public function log($level, $message, array $context = array()); } namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Logger; use Monolog\ResettableInterface; abstract class AbstractHandler implements HandlerInterface, ResettableInterface { protected $level = Logger::DEBUG; protected $bubble = true; protected $formatter; protected $processors = array(); public function __construct($level = Logger::DEBUG, $bubble = true) { $this->setLevel($level); $this->bubble = $bubble; } public function isHandling(array $record) { return $record['level'] >= $this->level; } public function handleBatch(array $records) { foreach ($records as $record) { $this->handle($record); } } public function close() { } public function pushProcessor($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . var_export($callback, true) . ' given'); } array_unshift($this->processors, $callback); return $this; } public function popProcessor() { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } public function setFormatter(FormatterInterface $formatter) { $this->formatter = $formatter; return $this; } public function getFormatter() { if (!$this->formatter) { $this->formatter = $this->getDefaultFormatter(); } return $this->formatter; } public function setLevel($level) { $this->level = Logger::toMonologLevel($level); return $this; } public function getLevel() { return $this->level; } public function setBubble($bubble) { $this->bubble = $bubble; return $this; } public function getBubble() { return $this->bubble; } public function __destruct() { try { $this->close(); } catch (\Exception $e) { } catch (\Throwable $e) { } } public function reset() { foreach ($this->processors as $processor) { if ($processor instanceof ResettableInterface) { $processor->reset(); } } } protected function getDefaultFormatter() { return new LineFormatter(); } } namespace Monolog\Handler; use Monolog\ResettableInterface; abstract class AbstractProcessingHandler extends AbstractHandler { public function handle(array $record) { if (!$this->isHandling($record)) { return false; } $record = $this->processRecord($record); $record['formatted'] = $this->getFormatter()->format($record); $this->write($record); return false === $this->bubble; } protected abstract function write(array $record); protected function processRecord(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } return $record; } } namespace Monolog\Handler; use Monolog\Logger; class StreamHandler extends AbstractProcessingHandler { protected $stream; protected $url; private $errorMessage; protected $filePermission; protected $useLocking; private $dirCreated; public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { parent::__construct($level, $bubble); if (is_resource($stream)) { $this->stream = $stream; } 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() { if ($this->url && is_resource($this->stream)) { fclose($this->stream); } $this->stream = null; $this->dirCreated = null; } public function getStream() { return $this->stream; } public function getUrl() { return $this->url; } protected function write(array $record) { if (!is_resource($this->stream)) { if (null === $this->url || '' === $this->url) { throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); } $this->createDir(); $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: ' . $this->errorMessage, $this->url)); } } if ($this->useLocking) { flock($this->stream, LOCK_EX); } $this->streamWrite($this->stream, $record); if ($this->useLocking) { flock($this->stream, LOCK_UN); } } protected function streamWrite($stream, array $record) { fwrite($stream, (string) $record['formatted']); } private function customErrorHandler($code, $msg) { $this->errorMessage = preg_replace('{^(fopen|mkdir)\\(.*?\\): }', '', $msg); } private function getDirFromStream($stream) { $pos = strpos($stream, '://'); if ($pos === false) { return dirname($stream); } if ('file://' === substr($stream, 0, 7)) { return dirname(substr($stream, 7)); } return; } private function createDir() { if ($this->dirCreated) { return; } $dir = $this->getDirFromStream($this->url); if (null !== $dir && !is_dir($dir)) { $this->errorMessage = null; set_error_handler(array($this, 'customErrorHandler')); $status = mkdir($dir, 511, true); restore_error_handler(); if (false === $status && !is_dir($dir)) { throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: ' . $this->errorMessage, $dir)); } } $this->dirCreated = true; } } namespace Monolog\Handler; use Monolog\Logger; class RotatingFileHandler extends StreamHandler { const FILE_PER_DAY = 'Y-m-d'; const FILE_PER_MONTH = 'Y-m'; const FILE_PER_YEAR = 'Y'; protected $filename; protected $maxFiles; protected $mustRotate; protected $nextRotation; 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'); $this->filenameFormat = '{filename}-{date}'; $this->dateFormat = 'Y-m-d'; parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); } public function close() { parent::close(); if (true === $this->mustRotate) { $this->rotate(); } } public function reset() { parent::reset(); if (true === $this->mustRotate) { $this->rotate(); } } public function setFilenameFormat($filenameFormat, $dateFormat) { if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { trigger_error('Invalid date format - format must be one of ' . 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") ' . 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the ' . 'date formats using slashes, underscores and/or dots instead of dashes.', E_USER_DEPRECATED); } if (substr_count($filenameFormat, '{date}') === 0) { trigger_error('Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.', E_USER_DEPRECATED); } $this->filenameFormat = $filenameFormat; $this->dateFormat = $dateFormat; $this->url = $this->getTimedFilename(); $this->close(); } protected function write(array $record) { if (null === $this->mustRotate) { $this->mustRotate = !file_exists($this->url); } if ($this->nextRotation < $record['datetime']) { $this->mustRotate = true; $this->close(); } parent::write($record); } protected function rotate() { $this->url = $this->getTimedFilename(); $this->nextRotation = new \DateTime('tomorrow'); if (0 === $this->maxFiles) { return; } $logFiles = glob($this->getGlobPattern()); if ($this->maxFiles >= count($logFiles)) { return; } usort($logFiles, function ($a, $b) { return strcmp($b, $a); }); foreach (array_slice($logFiles, $this->maxFiles) as $file) { if (is_writable($file)) { set_error_handler(function ($errno, $errstr, $errfile, $errline) { }); unlink($file); restore_error_handler(); } } $this->mustRotate = false; } protected function getTimedFilename() { $fileInfo = pathinfo($this->filename); $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'], '[0-9][0-9][0-9][0-9]*'), $fileInfo['dirname'] . '/' . $this->filenameFormat); if (!empty($fileInfo['extension'])) { $glob .= '.' . $fileInfo['extension']; } return $glob; } } namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; interface HandlerInterface { public function isHandling(array $record); public function handle(array $record); public function handleBatch(array $records); public function pushProcessor($callback); public function popProcessor(); public function setFormatter(FormatterInterface $formatter); public function getFormatter(); } namespace Illuminate\Support\Facades; class App extends Facade { protected static function getFacadeAccessor() { return 'app'; } } namespace Illuminate\Exception; use Exception; interface ExceptionDisplayerInterface { public function display(Exception $exception); } namespace Illuminate\Exception; use Exception; use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\HttpFoundation\JsonResponse; class SymfonyDisplayer implements ExceptionDisplayerInterface { protected $symfony; protected $returnJson; public function __construct(ExceptionHandler $symfony, $returnJson = false) { $this->symfony = $symfony; $this->returnJson = $returnJson; } public function display(Exception $exception) { if ($this->returnJson) { return new JsonResponse(array('error' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()), 500); } return $this->symfony->createResponse($exception); } } namespace Illuminate\Exception; use Exception; use Whoops\Run; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class WhoopsDisplayer implements ExceptionDisplayerInterface { protected $whoops; protected $runningInConsole; public function __construct(Run $whoops, $runningInConsole) { $this->whoops = $whoops; $this->runningInConsole = $runningInConsole; } public function display(Exception $exception) { $status = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500; $headers = $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : array(); return new Response($this->whoops->handleException($exception), $status, $headers); } } namespace Illuminate\Exception; use Closure; use ErrorException; use ReflectionFunction; use Symfony\Component\Debug\Exception\FatalThrowableError; use Illuminate\Support\Contracts\ResponsePreparerInterface; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\Debug\Exception\FatalErrorException as FatalError; class Handler { protected $responsePreparer; protected $plainDisplayer; protected $debugDisplayer; protected $debug; protected $handlers = array(); protected $handled = array(); public function __construct(ResponsePreparerInterface $responsePreparer, ExceptionDisplayerInterface $plainDisplayer, ExceptionDisplayerInterface $debugDisplayer, $debug = true) { $this->debug = $debug; $this->plainDisplayer = $plainDisplayer; $this->debugDisplayer = $debugDisplayer; $this->responsePreparer = $responsePreparer; } public function register($environment) { $this->registerErrorHandler(); $this->registerExceptionHandler(); if ($environment != 'testing') { $this->registerShutdownHandler(); } } protected function registerErrorHandler() { set_error_handler(array($this, 'handleError')); } protected function registerExceptionHandler() { set_exception_handler(array($this, 'handleUncaughtException')); } protected function registerShutdownHandler() { register_shutdown_function(array($this, 'handleShutdown')); } public function handleError($level, $message, $file = '', $line = 0, $context = array()) { if (error_reporting() & $level) { throw new ErrorException($message, 0, $level, $file, $line); } } public function handleException($exception) { $response = $this->callCustomHandlers($exception); if (!is_null($response)) { return $this->prepareResponse($response); } return $this->displayException($exception); } public function handleUncaughtException($exception) { $this->handleException($exception)->send(); } public function handleShutdown() { $error = error_get_last(); if (!is_null($error)) { extract($error); if (!$this->isFatal($type)) { return; } $this->handleException(new FatalError($message, $type, 0, $file, $line))->send(); } } protected function isFatal($type) { return in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE)); } public function handleConsole($exception) { return $this->callCustomHandlers($exception, true); } protected function callCustomHandlers($exception, $fromConsole = false) { foreach ($this->handlers as $handler) { if (!$this->handlesException($handler, $exception)) { continue; } elseif ($exception instanceof HttpExceptionInterface) { $code = $exception->getStatusCode(); } else { $code = 500; } try { $response = $handler($exception, $code, $fromConsole); } catch (\Exception $e) { $response = $this->formatException($e); } catch (\Throwable $e) { $response = $this->formatException($e); } if (isset($response) && !is_null($response)) { return $response; } } } protected function displayException($exception) { $displayer = $this->debug ? $this->debugDisplayer : $this->plainDisplayer; if (!$exception instanceof \Exception) { $exception = new FatalThrowableError($exception); } return $displayer->display($exception); } protected function handlesException(Closure $handler, $exception) { $reflection = new ReflectionFunction($handler); return $reflection->getNumberOfParameters() == 0 || $this->hints($reflection, $exception); } protected function hints(ReflectionFunction $reflection, $exception) { $parameters = $reflection->getParameters(); $expected = $parameters[0]; return !$expected->getClass() || $expected->getClass()->isInstance($exception); } protected function formatException(\Exception $e) { 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) { array_unshift($this->handlers, $callback); } public function pushError(Closure $callback) { $this->handlers[] = $callback; } protected function prepareResponse($response) { return $this->responsePreparer->prepareResponse($response); } public function runningInConsole() { return php_sapi_name() == 'cli'; } public function setDebug($debug) { $this->debug = $debug; } } namespace Illuminate\Support\Facades; class Route extends Facade { protected static function getFacadeAccessor() { return 'router'; } } namespace Illuminate\View\Engines; use Closure; class EngineResolver { protected $resolvers = array(); protected $resolved = array(); public function register($engine, Closure $resolver) { $this->resolvers[$engine] = $resolver; } public function resolve($engine) { if (isset($this->resolved[$engine])) { return $this->resolved[$engine]; } if (isset($this->resolvers[$engine])) { return $this->resolved[$engine] = call_user_func($this->resolvers[$engine]); } throw new \InvalidArgumentException("Engine {$engine} not found."); } } namespace Illuminate\View; interface ViewFinderInterface { public function find($view); public function addLocation($location); public function addNamespace($namespace, $hints); public function prependNamespace($namespace, $hints); public function addExtension($extension); } namespace Illuminate\View; use Illuminate\Filesystem\Filesystem; class FileViewFinder implements ViewFinderInterface { protected $files; protected $paths; protected $views = array(); protected $hints = array(); protected $extensions = array('blade.php', 'php'); const HINT_PATH_DELIMITER = '::'; public function __construct(Filesystem $files, array $paths, array $extensions = null) { $this->files = $files; $this->paths = $paths; if (isset($extensions)) { $this->extensions = $extensions; } } public function find($name) { if (isset($this->views[$name])) { return $this->views[$name]; } if ($this->hasHintInformation($name = trim($name))) { return $this->views[$name] = $this->findNamedPathView($name); } return $this->views[$name] = $this->findInPaths($name, $this->paths); } protected function findNamedPathView($name) { list($namespace, $view) = $this->getNamespaceSegments($name); return $this->findInPaths($view, $this->hints[$namespace]); } protected function getNamespaceSegments($name) { $segments = explode(static::HINT_PATH_DELIMITER, $name); if (count($segments) != 2) { throw new \InvalidArgumentException("View [{$name}] has an invalid name."); } if (!isset($this->hints[$segments[0]])) { throw new \InvalidArgumentException("No hint path defined for [{$segments[0]}]."); } return $segments; } protected function findInPaths($name, $paths) { foreach ((array) $paths as $path) { foreach ($this->getPossibleViewFiles($name) as $file) { if ($this->files->exists($viewPath = $path . '/' . $file)) { return $viewPath; } } } throw new \InvalidArgumentException("View [{$name}] not found."); } protected function getPossibleViewFiles($name) { return array_map(function ($extension) use($name) { return str_replace('.', '/', $name) . '.' . $extension; }, $this->extensions); } public function addLocation($location) { $this->paths[] = $location; } public function addNamespace($namespace, $hints) { $hints = (array) $hints; if (isset($this->hints[$namespace])) { $hints = array_merge($this->hints[$namespace], $hints); } $this->hints[$namespace] = $hints; } public function prependNamespace($namespace, $hints) { $hints = (array) $hints; if (isset($this->hints[$namespace])) { $hints = array_merge($hints, $this->hints[$namespace]); } $this->hints[$namespace] = $hints; } public function addExtension($extension) { if (($index = array_search($extension, $this->extensions)) !== false) { unset($this->extensions[$index]); } array_unshift($this->extensions, $extension); } public function hasHintInformation($name) { return strpos($name, static::HINT_PATH_DELIMITER) > 0; } public function getFilesystem() { return $this->files; } public function getPaths() { return $this->paths; } public function getHints() { return $this->hints; } public function getExtensions() { return $this->extensions; } } namespace Illuminate\Support\Contracts; interface MessageProviderInterface { public function getMessageBag(); } namespace Illuminate\Support; use Countable; use JsonSerializable; use Illuminate\Support\Contracts\JsonableInterface; use Illuminate\Support\Contracts\ArrayableInterface; use Illuminate\Support\Contracts\MessageProviderInterface; class MessageBag implements ArrayableInterface, Countable, JsonableInterface, MessageProviderInterface, JsonSerializable { protected $messages = array(); protected $format = ':message'; public function __construct(array $messages = array()) { foreach ($messages as $key => $value) { $this->messages[$key] = (array) $value; } } public function add($key, $message) { if ($this->isUnique($key, $message)) { $this->messages[$key][] = $message; } return $this; } public function merge($messages) { if ($messages instanceof MessageProviderInterface) { $messages = $messages->getMessageBag()->getMessages(); } $this->messages = array_merge_recursive($this->messages, $messages); return $this; } protected function isUnique($key, $message) { $messages = (array) $this->messages; return !isset($messages[$key]) || !in_array($message, $messages[$key]); } public function has($key = null) { return $this->first($key) !== ''; } public function first($key = null, $format = null) { $messages = is_null($key) ? $this->all($format) : $this->get($key, $format); return count($messages) > 0 ? $messages[0] : ''; } public function get($key, $format = null) { $format = $this->checkFormat($format); if (array_key_exists($key, $this->messages)) { return $this->transform($this->messages[$key], $format, $key); } return array(); } public function all($format = null) { $format = $this->checkFormat($format); $all = array(); foreach ($this->messages as $key => $messages) { $all = array_merge($all, $this->transform($messages, $format, $key)); } return $all; } protected function transform($messages, $format, $messageKey) { $messages = (array) $messages; foreach ($messages as &$message) { $replace = array(':message', ':key'); $message = str_replace($replace, array($message, $messageKey), $format); } return $messages; } protected function checkFormat($format) { return $format === null ? $this->format : $format; } public function getMessages() { return $this->messages; } public function getMessageBag() { return $this; } public function getFormat() { return $this->format; } public function setFormat($format = ':message') { $this->format = $format; return $this; } public function isEmpty() { return !$this->any(); } public function any() { return $this->count() > 0; } public function count() { return count($this->messages, COUNT_RECURSIVE) - count($this->messages); } public function toArray() { return $this->getMessages(); } public function jsonSerialize() { return $this->toArray(); } public function toJson($options = 0) { return json_encode($this->toArray(), $options); } public function __toString() { return $this->toJson(); } } namespace Illuminate\Support\Facades; class View extends Facade { protected static function getFacadeAccessor() { return 'view'; } } namespace Illuminate\Support\Contracts; interface RenderableInterface { public function render(); } namespace Illuminate\View; use ArrayAccess; use Closure; use Illuminate\Support\MessageBag; use Illuminate\View\Engines\EngineInterface; use Illuminate\Support\Contracts\MessageProviderInterface; use Illuminate\Support\Contracts\ArrayableInterface as Arrayable; use Illuminate\Support\Contracts\RenderableInterface as Renderable; class View implements ArrayAccess, Renderable { protected $factory; protected $engine; protected $view; protected $data; protected $path; public function __construct(Factory $factory, EngineInterface $engine, $view, $path, $data = array()) { $this->view = $view; $this->path = $path; $this->engine = $engine; $this->factory = $factory; $this->data = $data instanceof Arrayable ? $data->toArray() : (array) $data; } public function render(Closure $callback = null) { try { $contents = $this->renderContents(); $response = isset($callback) ? $callback($this, $contents) : null; $this->factory->flushSectionsIfDoneRendering(); return $response ?: $contents; } catch (Exception $e) { $this->factory->flushSections(); throw $e; } } protected function renderContents() { $this->factory->incrementRender(); $this->factory->callComposer($this); $contents = $this->getContents(); $this->factory->decrementRender(); return $contents; } public function renderSections() { $env = $this->factory; return $this->render(function ($view) use($env) { return $env->getSections(); }); } protected function getContents() { return $this->engine->get($this->path, $this->gatherData()); } protected function gatherData() { $data = array_merge($this->factory->getShared(), $this->data); foreach ($data as $key => $value) { if ($value instanceof Renderable) { $data[$key] = $value->render(); } } return $data; } public function with($key, $value = null) { if (is_array($key)) { $this->data = array_merge($this->data, $key); } else { $this->data[$key] = $value; } return $this; } public function nest($key, $view, array $data = array()) { return $this->with($key, $this->factory->make($view, $data)); } public function withErrors($provider) { if ($provider instanceof MessageProviderInterface) { $this->with('errors', $provider->getMessageBag()); } else { $this->with('errors', new MessageBag((array) $provider)); } return $this; } public function getFactory() { return $this->factory; } public function getEngine() { return $this->engine; } public function getName() { return $this->view; } public function getData() { return $this->data; } public function getPath() { return $this->path; } public function setPath($path) { $this->path = $path; } public function offsetExists($key) { return array_key_exists($key, $this->data); } public function offsetGet($key) { return $this->data[$key]; } public function offsetSet($key, $value) { $this->with($key, $value); } public function offsetUnset($key) { unset($this->data[$key]); } public function &__get($key) { return $this->data[$key]; } public function __set($key, $value) { $this->with($key, $value); } public function __isset($key) { return isset($this->data[$key]); } public function __unset($key) { 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(); } } namespace Illuminate\View\Engines; interface EngineInterface { public function get($path, array $data = array()); } namespace Illuminate\View\Engines; class PhpEngine implements EngineInterface { public function get($path, array $data = array()) { return $this->evaluatePath($path, $data); } protected function evaluatePath($__path, $__data) { $obLevel = ob_get_level(); ob_start(); extract($__data); try { include $__path; } catch (\Exception $e) { $this->handleViewException($e, $obLevel); } catch (\Throwable $e) { $this->handleViewException($e, $obLevel); } return ltrim(ob_get_clean()); } protected function handleViewException($e, $obLevel) { while (ob_get_level() > $obLevel) { ob_end_clean(); } throw $e; } } namespace Illuminate\Http; use Symfony\Component\HttpFoundation\Cookie; trait ResponseTrait { public function header($key, $value, $replace = true) { $this->headers->set($key, $value, $replace); return $this; } public function withCookie(Cookie $cookie) { $this->headers->setCookie($cookie); return $this; } } namespace Illuminate\Http; use ArrayObject; use Illuminate\Support\Contracts\JsonableInterface; use Illuminate\Support\Contracts\RenderableInterface; class Response extends \Symfony\Component\HttpFoundation\Response { use ResponseTrait; public $original; public function setContent($content) { $this->original = $content; if ($this->shouldBeJson($content)) { $this->headers->set('Content-Type', 'application/json'); $content = $this->morphToJson($content); } elseif ($content instanceof RenderableInterface) { $content = $content->render(); } return parent::setContent($content); } protected function morphToJson($content) { if ($content instanceof JsonableInterface) { return $content->toJson(); } return json_encode($content); } protected function shouldBeJson($content) { return $content instanceof JsonableInterface || $content instanceof ArrayObject || is_array($content); } public function getOriginalContent() { return $this->original; } } namespace Whoops; use Exception; use InvalidArgumentException; use Whoops\Exception\ErrorException; use Whoops\Exception\Inspector; use Whoops\Handler\CallbackHandler; use Whoops\Handler\Handler; use Whoops\Handler\HandlerInterface; class Run { const EXCEPTION_HANDLER = 'handleException'; const ERROR_HANDLER = 'handleError'; const SHUTDOWN_HANDLER = 'handleShutdown'; protected $isRegistered; protected $allowQuit = true; protected $sendOutput = true; protected $sendHttpCode = 500; protected $handlerStack = array(); protected $silencedPatterns = array(); public function pushHandler($handler) { if (is_callable($handler)) { $handler = new CallbackHandler($handler); } if (!$handler instanceof HandlerInterface) { throw new InvalidArgumentException('Argument to ' . __METHOD__ . ' must be a callable, or instance of' . 'Whoops\\Handler\\HandlerInterface'); } $this->handlerStack[] = $handler; return $this; } public function popHandler() { return array_pop($this->handlerStack); } public function getHandlers() { return $this->handlerStack; } public function clearHandlers() { $this->handlerStack = array(); return $this; } protected function getInspector(Exception $exception) { return new Inspector($exception); } public function register() { if (!$this->isRegistered) { class_exists('\\Whoops\\Exception\\ErrorException'); class_exists('\\Whoops\\Exception\\FrameCollection'); class_exists('\\Whoops\\Exception\\Frame'); class_exists('\\Whoops\\Exception\\Inspector'); set_error_handler(array($this, self::ERROR_HANDLER)); set_exception_handler(array($this, self::EXCEPTION_HANDLER)); register_shutdown_function(array($this, self::SHUTDOWN_HANDLER)); $this->isRegistered = true; } return $this; } public function unregister() { if ($this->isRegistered) { restore_exception_handler(); restore_error_handler(); $this->isRegistered = false; } return $this; } public function allowQuit($exit = null) { if (func_num_args() == 0) { return $this->allowQuit; } return $this->allowQuit = (bool) $exit; } public function silenceErrorsInPaths($patterns, $levels = 10240) { $this->silencedPatterns = array_merge($this->silencedPatterns, array_map(function ($pattern) use($levels) { return array('pattern' => $pattern, 'levels' => $levels); }, (array) $patterns)); return $this; } public function sendHttpCode($code = null) { if (func_num_args() == 0) { return $this->sendHttpCode; } if (!$code) { return $this->sendHttpCode = false; } if ($code === true) { $code = 500; } if ($code < 400 || 600 <= $code) { throw new InvalidArgumentException("Invalid status code '{$code}', must be 4xx or 5xx"); } return $this->sendHttpCode = $code; } public function writeToOutput($send = null) { if (func_num_args() == 0) { return $this->sendOutput; } return $this->sendOutput = (bool) $send; } public function handleException(Exception $exception) { $inspector = $this->getInspector($exception); ob_start(); $handlerResponse = null; foreach (array_reverse($this->handlerStack) as $handler) { $handler->setRun($this); $handler->setInspector($inspector); $handler->setException($exception); $handlerResponse = $handler->handle($exception); if (in_array($handlerResponse, array(Handler::LAST_HANDLER, Handler::QUIT))) { break; } } $willQuit = $handlerResponse == Handler::QUIT && $this->allowQuit(); $output = ob_get_clean(); if ($this->writeToOutput()) { if ($willQuit) { while (ob_get_level() > 0) { ob_end_clean(); } } $this->writeToOutputNow($output); } if ($willQuit) { flush(); die(1); } return $output; } public function handleError($level, $message, $file = null, $line = null) { if ($level & error_reporting()) { foreach ($this->silencedPatterns as $entry) { $pathMatches = (bool) preg_match($entry['pattern'], $file); $levelMatches = $level & $entry['levels']; if ($pathMatches && $levelMatches) { return true; } } $exception = new ErrorException($message, $level, $level, $file, $line); if ($this->canThrowExceptions) { throw $exception; } else { $this->handleException($exception); } return true; } return false; } public function handleShutdown() { $this->canThrowExceptions = false; $error = error_get_last(); if ($error && $this->isLevelFatal($error['type'])) { $this->handleError($error['type'], $error['message'], $error['file'], $error['line']); } } private $canThrowExceptions = true; private function writeToOutputNow($output) { if ($this->sendHttpCode() && \Whoops\Util\Misc::canSendHeaders()) { $httpCode = $this->sendHttpCode(); if (function_exists('http_response_code')) { http_response_code($httpCode); } else { header('X-Ignore-This: 1', true, $httpCode); } } echo $output; return $this; } private static function isLevelFatal($level) { $errors = E_ERROR; $errors |= E_PARSE; $errors |= E_CORE_ERROR; $errors |= E_CORE_WARNING; $errors |= E_COMPILE_ERROR; $errors |= E_COMPILE_WARNING; return ($level & $errors) > 0; } } namespace Whoops\Handler; use Exception; use Whoops\Exception\Inspector; use Whoops\Run; interface HandlerInterface { public function handle(); public function setRun(Run $run); public function setException(Exception $exception); public function setInspector(Inspector $inspector); } namespace Whoops\Handler; use Exception; use Whoops\Exception\Inspector; use Whoops\Run; abstract class Handler implements HandlerInterface { const DONE = 16; const LAST_HANDLER = 32; const QUIT = 48; private $run; private $inspector; private $exception; public function setRun(Run $run) { $this->run = $run; } protected function getRun() { return $this->run; } public function setInspector(Inspector $inspector) { $this->inspector = $inspector; } protected function getInspector() { return $this->inspector; } public function setException(Exception $exception) { $this->exception = $exception; } protected function getException() { return $this->exception; } } namespace Whoops\Handler; use Whoops\Exception\Formatter; class JsonResponseHandler extends Handler { private $returnFrames = false; private $onlyForAjaxRequests = false; public function addTraceToOutput($returnFrames = null) { if (func_num_args() == 0) { return $this->returnFrames; } $this->returnFrames = (bool) $returnFrames; return $this; } public function onlyForAjaxRequests($onlyForAjaxRequests = null) { if (func_num_args() == 0) { return $this->onlyForAjaxRequests; } $this->onlyForAjaxRequests = (bool) $onlyForAjaxRequests; } private function isAjaxRequest() { return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; } public function handle() { if ($this->onlyForAjaxRequests() && !$this->isAjaxRequest()) { return Handler::DONE; } $response = array('error' => Formatter::formatExceptionAsDataArray($this->getInspector(), $this->addTraceToOutput())); if (\Whoops\Util\Misc::canSendHeaders()) { header('Content-Type: application/json'); } echo json_encode($response); return Handler::QUIT; } } namespace Stack; use Symfony\Component\HttpKernel\HttpKernelInterface; class Builder { private $specs; public function __construct() { $this->specs = new \SplStack(); } public function unshift() { if (func_num_args() === 0) { throw new \InvalidArgumentException('Missing argument(s) when calling unshift'); } $spec = func_get_args(); $this->specs->unshift($spec); return $this; } public function push() { if (func_num_args() === 0) { throw new \InvalidArgumentException('Missing argument(s) when calling push'); } $spec = func_get_args(); $this->specs->push($spec); return $this; } public function resolve(HttpKernelInterface $app) { $middlewares = array($app); foreach ($this->specs as $spec) { $args = $spec; $firstArg = array_shift($args); if (is_callable($firstArg)) { $app = $firstArg($app); } else { $kernelClass = $firstArg; array_unshift($args, $app); $reflection = new \ReflectionClass($kernelClass); $app = $reflection->newInstanceArgs($args); } array_unshift($middlewares, $app); } return new StackedHttpKernel($app, $middlewares); } } namespace Stack; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class StackedHttpKernel implements HttpKernelInterface, TerminableInterface { private $app; private $middlewares = array(); public function __construct(HttpKernelInterface $app, array $middlewares) { $this->app = $app; $this->middlewares = $middlewares; } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { return $this->app->handle($request, $type, $catch); } public function terminate(Request $request, Response $response) { $prevKernel = null; foreach ($this->middlewares as $kernel) { if (!$prevKernel instanceof TerminableInterface && $kernel instanceof TerminableInterface) { $kernel->terminate($request, $response); } $prevKernel = $kernel; } } }